Skip to content

Accept the TT_* key spellings in credentials.json#10

Merged
walkerhughes merged 1 commit into
mainfrom
fix/credentials-key-aliases
Jul 25, 2026
Merged

Accept the TT_* key spellings in credentials.json#10
walkerhughes merged 1 commit into
mainfrom
fix/credentials-key-aliases

Conversation

@walkerhughes

Copy link
Copy Markdown
Owner

The loader I shipped in #9 only accepted snake_case keys, so a credentials file written with the TT_* names failed. Reported live as:

~/.tastytrade-mcp/credentials.json is missing client_id, client_secret, and refresh_token

The file had all three values, just under the names used everywhere else. My design error: I mirrored harbor's key style without checking what the values are actually called in this project.

Fix

Both spellings accepted per field, snake_case preferred when both appear:

Canonical Also accepted
client_id TT_CLIENT_ID
client_secret TT_SECRET
refresh_token TT_REFRESH
base_url API_BASE_URL

The TT_* forms are what .env.example, the environment, and the Tastytrade docs all use, so a file written from any of those is the obvious thing to produce and must not be rejected.

The missing-key error now names both spellings and lists which keys the file actually contained, so a naming mismatch is diagnosable from the message rather than reading as "no credentials at all".

TT_USERNAME and TT_PASSWORD are ignored: the OAuth refresh-token grant reads neither. When they are the only keys present the error says so, since they are otherwise secrets sitting at rest that nothing reads.

Verification

Against a real credentials.json using the TT_* names:

resolved OK
source     : /Users/.../.tastytrade-mcp/credentials.json
base_url   : api.tastyworks.com
client_id    : set, 36 chars
client_secret: set, 40 chars
refresh_token: set, 545 chars

A live read-only list_accounts through the plugin launcher returns the account.

Check Result
ruff check / format clean
mypy no issues, 29 files
Unit tests 94 passed
With integration 106 passed, 93.00% coverage
Eval verifiers 12 passed

Four new tests cover the aliases, the both-spellings precedence, ignored username/password keys, and that the error names both spellings while never echoing a value (asserted with distinctive sentinels).

Two notes from debugging this

A transient HTTP 400 appeared on one list_accounts call and did not reproduce; the same call succeeds directly and through the launcher. Along the way I suspected two things and confirmed both were not bugs, rather than "fixing" working code:

  • authenticate() interpolates the form body without URL-encoding. All three values are alphanumeric plus -_., so nothing needs encoding. Still worth knowing it would break on a secret containing + or /.
  • The client sets a blanket Content-Type: application/json on bodyless GETs. The API returns 200 either way.

Version 0.2.0 so installed copies receive this.

The loader only accepted snake_case keys (client_id, client_secret,
refresh_token), but the natural thing to write is the TT_* names, which is what
.env.example, the environment, and the Tastytrade docs all use. A file holding
TT_CLIENT_ID / TT_SECRET / TT_REFRESH was reported as missing all three
credentials, which reads as "no credentials" rather than "wrong key names".

- Both spellings are accepted per field, snake_case preferred when both appear.
  base_url likewise accepts API_BASE_URL.
- The missing-key error now names both spellings and lists which keys the file
  actually contained, so a naming mismatch is diagnosable from the message.
- TT_USERNAME and TT_PASSWORD are ignored: the OAuth refresh-token grant reads
  neither. When they are the only keys present, the error says so, since they
  are otherwise secrets at rest that nothing reads.

Verified against a real credentials.json using the TT_* names: it resolves, and
a live read-only list_accounts through the plugin launcher returns the account.
Values are never echoed in any error; a test asserts that with distinctive
sentinel values.

Version 0.2.0 so installed copies pick this up.
@walkerhughes
walkerhughes merged commit 719623a into main Jul 25, 2026
2 checks passed
@walkerhughes
walkerhughes deleted the fix/credentials-key-aliases branch July 25, 2026 15:46
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.

1 participant