Skip to content

fix(mcp): return plain HTTP 404 for unknown paths so OAuth clients get a clear error#1409

Merged
datlechin merged 2 commits into
mainfrom
fix/mcp-http-404
May 24, 2026
Merged

fix(mcp): return plain HTTP 404 for unknown paths so OAuth clients get a clear error#1409
datlechin merged 2 commits into
mainfrom
fix/mcp-http-404

Conversation

@datlechin

Copy link
Copy Markdown
Member

Problem

Connecting an OAuth-capable MCP client (Claude Code's http transport) with an invalid or expired bearer token failed with a cryptic error:

SDK auth failed: HTTP 404: Invalid OAuth error response: ZodError ...
Raw body: {"id":null,"error":{"message":"Method not found","code":-32601},"jsonrpc":"2.0"}

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 /mcp or /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:

  1. The SDK starts the OAuth flow on any 401 when an authProvider exists (if (response.status === 401 && this._authProvider)), regardless of the WWW-Authenticate header.
  2. It probes /.well-known/oauth-protected-resource and /.well-known/oauth-authorization-server (404s, swallowed), then POSTs Dynamic Client Registration to /register.
  3. /register returned our JSON-RPC body. The SDK validates it with OAuthErrorResponseSchema.parse, where error must be a string. Our error was an object, so it threw the ZodError.

Fix

Separate HTTP-layer errors from JSON-RPC protocol errors:

  • Unknown HTTP paths return a plain HTTP 404 with {"error":"not_found","error_description":"..."} (a string error, the shape the SDK accepts).
  • Unsupported HTTP methods on /mcp return a plain 405.
  • The JSON-RPC -32601 envelope still applies to unknown JSON-RPC methods dispatched on /mcp.

WWW-Authenticate is 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-known OAuth probes, and POST /register all return a plain 404 with a string error and no JSON-RPC envelope.
  • unsupportedMethodReturnsPlain405: PUT /mcp returns a plain 405.
  • SwiftLint --strict clean.

@datlechin datlechin merged commit f7cab94 into main May 24, 2026
2 checks passed
@datlechin datlechin deleted the fix/mcp-http-404 branch May 24, 2026 08:03
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