MCP OAuth Troubleshooting
Technical reference for OAuth-related CrossTrade MCP errors. For a trader-friendly walkthrough, see Troubleshoot 401, 403, and 408 Errors.
Error matrix
| HTTP | error | Cause | Resolution |
|---|---|---|---|
| 401 | invalid_token | Access token expired, revoked, or never issued | Reauthorize from AI Clients |
| 401 | WWW-Authenticate: Bearer realm="..." (no body) | First-call discovery probe | Expected; client follows the header to OAuth discovery |
| 403 | subscription_required / message "MCP requires an Elite subscription" | Account is below Elite | Upgrade |
| 403 | insufficient_scope | Tool requires mcp:trade; token has mcp:read | Reauthorize at mcp:trade |
| 408 | addon_disconnected / generic timeout | NT8 closed or add-on disconnected | Open NT8; verify the add-on panel |
| 400 | invalid_grant | PKCE verifier mismatch, code reuse, or stale code | Restart the auth flow |
| 400 | invalid_request | Malformed registration or token request body | Inspect the client's request shape |
| 400 | invalid_client_metadata | Registration body violates RFC 7591 constraints | Reduce metadata to required fields |
| 429 | too_many_registrations | Rate-limit on /v1/oauth/mcp/register (10/hour/IP) | Reuse the existing client_id or wait |
| 500 | server_error | Transient backend failure | Retry; if persistent, contact support |
401: invalid_token
401 is the default response when a tool is called without a valid bearer token. Two distinct conditions:
- No token presented. Server returns 401 with
WWW-Authenticate: Bearer resource_metadata=.... This is the first step of the OAuth discovery flow. - Token presented but invalid. Server returns 401 with
error: invalid_token. The token expired, was revoked, or was never issued for this client.
Resolution:
- Reauthorize the client from the AI Clients page.
- If the client cached an old token, remove and re-add the MCP server in the client.
- If PKCE timestamps look off, confirm system clock.
403: subscription_required (Elite gate)
The MCP transport itself is Elite-gated. OAuth completes on all tiers (so the discovery flow does not fail), but tools/call returns:
{
"error": "subscription_required",
"message": "MCP requires an Elite subscription"
}
Resolution: upgrade at Subscriptions. REST and WebSocket remain available on Pro.
403: insufficient_scope
The token has mcp:read but the requested tool requires mcp:trade.
{
"error": "insufficient_scope",
"required": "mcp:trade"
}
Resolution: either rewrite the prompt to keep the agent in read-only mode, or revoke and reauthorize at mcp:trade. See Use mcp:read vs mcp:trade.
408: addon_disconnected
Tools that need NT8 state route through the CrossTrade Add-On. If the add-on is not connected, the server returns 408 Request Timeout or addon_disconnected.
Resolution:
- Open NT8.
- Open the CrossTrade Add-On panel.
- Confirm the version is
v1.13.0or higher. - Confirm status shows connected.
- Restart the add-on if necessary.
400: invalid_grant on token exchange
The authorization code is single-use, has a short expiry, and is bound to the PKCE verifier the client sent at the authorization step. Common causes:
- Client tried to reuse a code that was already exchanged.
- The code expired before exchange (default expiry is short).
- PKCE verifier sent at the token endpoint does not match the challenge sent at the authorization endpoint.
Resolution: restart the entire auth flow.
400: invalid_client_metadata (DCR)
POST /v1/oauth/mcp/register rejects metadata that violates RFC 7591 constraints. Common rejections:
scopeincludes anything other thanmcp:readormcp:trade.redirect_urismissing or malformed.
Resolution: send only the supported metadata fields.
429: too_many_registrations
POST /v1/oauth/mcp/register is rate-limited per IP. Default: 10 registrations per hour. Most clients register once and persist the client_id. Re-registering on every connection attempt is a bug in the client.
Resolution:
- Persist the
client_idafter first registration. - If you genuinely need to re-register, wait an hour or use a different IP for the test.
Discovery sequence reference
For the full discovery sequence, see MCP Authentication.
Quick summary:
- Client →
POST /v1/api/mcp(no token) → 401 withWWW-Authenticate. - Client →
GET /.well-known/oauth-protected-resource(RFC 9728). - Client →
GET /.well-known/oauth-authorization-server(RFC 8414). - Client →
POST /v1/oauth/mcp/register(RFC 7591). - Browser → authorization endpoint, user consents.
- Client →
POST /v1/oauth/mcp/token(exchange code). - Client →
POST /v1/api/mcpwithAuthorization: Bearer <token>.
What to send to support
Include:
- HTTP status code
errorfield if present- Approximate timestamp in UTC
- Client name and version
- Whether you completed OAuth in the last 24 hours
- The result of
GetMcpCapabilitiesif it works
Do not send:
- Bearer tokens
- Account numbers or balances
- Webhook secrets
- Full request/response bodies that may contain the above
Related
- Docs: MCP Authentication
- Docs: ChatGPT MCP Authentication
- Docs: MCP Troubleshooting (general)
- Learn: Troubleshoot 401, 403, and 408 Errors
- Learn: Authenticate CrossTrade MCP