Skip to content

feat: add check_credits tool via /account/info API (v2)#17

Merged
jdrhyne merged 1 commit intomainfrom
feat/credit-tracking-api-v2
Feb 28, 2026
Merged

feat: add check_credits tool via /account/info API (v2)#17
jdrhyne merged 1 commit intomainfrom
feat/credit-tracking-api-v2

Conversation

@jdrhyne
Copy link
Contributor

@jdrhyne jdrhyne commented Feb 7, 2026

Replaces #16

Complete rewrite of the credit tracking tool, addressing all review feedback from @HungKNguyen and @nickwinder.

What changed from #16

Issue #16 (original) This PR
API schema Hallucinated period breakdowns Matches actual /account/info endpoint
Period parameter day/week/month/all (doesn't exist) Removed — API returns current billing period only
Usage actions balance and usage Single tool, returns both
API key exposure ⚠️ Returned raw response including live API key sanitizeAccountInfo() strips apiKeys before LLM sees it
Local storage None (was removed from #12's SQLite) None

API response schema (from docs)

{
  "apiKeys": { "live": "sk_live_..." },  // ← STRIPPED before LLM
  "signedIn": true,
  "subscriptionType": "free" | "paid" | "enterprise",
  "usage": {
    "totalCredits": 100,
    "usedCredits": 50
  }
}

What the LLM receives

{
  "subscriptionType": "paid",
  "totalCredits": 100,
  "usedCredits": 42,
  "remainingCredits": 58,
  "signedIn": true
}

Files changed

File Change
src/dws/credits.ts New: performCheckCreditsCall() + sanitizeAccountInfo()
src/schemas.ts CheckCreditsArgsSchema (empty object — no params needed)
src/index.ts Tool registration
tests/unit.test.ts 7 new tests

Tests (7 new, 58 total passing)

  • CheckCreditsArgsSchema accepts empty object
  • sanitizeAccountInfo strips apiKeys field
  • sanitizeAccountInfo handles response with no apiKeys
  • API key never appears in serialized output (security test per Hung's request)
  • Successful credit summary extraction with mocked API
  • Non-JSON response error handling
  • Missing API key error

Closes

Supersedes #16 — that PR can be closed once this is merged.

Rewrites the credit tracking implementation to match the actual DWS
/account/info endpoint schema (per Hung's review on #16).

Changes from the original PR:
- Removed hallucinated period breakdown (API doesn't support it)
- Removed usage action — the endpoint is simple: totalCredits and
  usedCredits for the current billing period
- SECURITY: strips apiKeys from the response before sending to the
  LLM (the endpoint returns the live API key)
- No local SQLite DB (uses API directly per Nick's feedback)

Tests (7 new):
- Schema validation for CheckCreditsArgsSchema
- sanitizeAccountInfo strips apiKeys field
- sanitizeAccountInfo handles missing apiKeys
- API key never appears in serialized output (security test)
- Successful credit summary extraction with mocked API
- Non-JSON response handling
- Missing API key error
Copy link
Collaborator

@nickwinder nickwinder left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please address the comments, but otherwise LGTM

Comment on lines +36 to +44
const apiKey = getApiKey()

const response = await axios.get('https://api.nutrient.io/account/info', {
headers: {
Authorization: `Bearer ${apiKey}`,
'User-Agent': `NutrientDWSMCPServer/${getVersion()}`,
},
responseType: 'stream',
})
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already have a helper that can abstract the header setting and required URL in callNutrientApi. By using this we can mock DWS services better for testing , or point at a staging, or dev environment.

Comment on lines +72 to +75
return {
content: [{ type: 'text', text: JSON.stringify(summary, null, 2) }],
isError: false,
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We also have helpers for this. createSuccessResponse

@jdrhyne jdrhyne merged commit 15ce07b into main Feb 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants