feat: add check_credits tool via /account/info API (v2)#17
Merged
Conversation
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
nickwinder
approved these changes
Feb 10, 2026
Collaborator
nickwinder
left a comment
There was a problem hiding this comment.
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', | ||
| }) |
Collaborator
There was a problem hiding this comment.
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, | ||
| } |
Collaborator
There was a problem hiding this comment.
We also have helpers for this. createSuccessResponse
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Replaces #16
Complete rewrite of the credit tracking tool, addressing all review feedback from @HungKNguyen and @nickwinder.
What changed from #16
/account/infoendpointday/week/month/all(doesn't exist)balanceandusagesanitizeAccountInfo()stripsapiKeysbefore LLM sees itAPI 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
src/dws/credits.tsperformCheckCreditsCall()+sanitizeAccountInfo()src/schemas.tsCheckCreditsArgsSchema(empty object — no params needed)src/index.tstests/unit.test.tsTests (7 new, 58 total passing)
CheckCreditsArgsSchemaaccepts empty objectsanitizeAccountInfostripsapiKeysfieldsanitizeAccountInfohandles response with noapiKeysCloses
Supersedes #16 — that PR can be closed once this is merged.