fix(mcp): return plain HTTP 404 for unknown paths so OAuth clients get a clear error#1409
Merged
Conversation
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.
Problem
Connecting an OAuth-capable MCP client (Claude Code's
httptransport) with an invalid or expired bearer token failed with a cryptic error:The real cause (a bad token) was hidden, and the offered "Authenticate" / "Reconnect" actions could not succeed because TablePro is not an OAuth server.
Root cause
The HTTP router returned a JSON-RPC error envelope for any path that is not
/mcpor/v1/integrations/exchange. JSON-RPC errors are a transport-protocol concept that should only apply to the MCP endpoint. An unknown HTTP path is an HTTP-layer 404.Traced through the MCP TypeScript SDK:
if (response.status === 401 && this._authProvider)), regardless of theWWW-Authenticateheader./.well-known/oauth-protected-resourceand/.well-known/oauth-authorization-server(404s, swallowed), then POSTs Dynamic Client Registration to/register./registerreturned our JSON-RPC body. The SDK validates it withOAuthErrorResponseSchema.parse, whereerrormust be a string. Ourerrorwas an object, so it threw the ZodError.Fix
Separate HTTP-layer errors from JSON-RPC protocol errors:
{"error":"not_found","error_description":"..."}(a stringerror, the shape the SDK accepts)./mcpreturn a plain 405.-32601envelope still applies to unknown JSON-RPC methods dispatched on/mcp.WWW-Authenticateis unchanged: it does not gate the SDK's OAuth trigger, so changing it would have no effect.After the fix, a bad token in Claude Code ends with a clear error instead of the ZodError.
Tests
unknownPathsReturnPlainNotFound: GET, POST, and DELETE on unknown paths, both.well-knownOAuth probes, andPOST /registerall return a plain 404 with a stringerrorand no JSON-RPC envelope.unsupportedMethodReturnsPlain405:PUT /mcpreturns a plain 405.--strictclean.