-
-
Notifications
You must be signed in to change notification settings - Fork 204
Description
Issue
When an MCP server's OAuth access token expires during an active session...
- tool calls from the
Toolstab fail permanently withStreamable HTTP error: Error POSTing to endpoint: {"error":"invalid_token"}. - tool calls from the
App Buildertab fail permanently silently; no response is shown anywhere.
The Inspector does not use the refresh token to obtain a new access token, even though the SDK (MCPClientManager) seems to supports automatic 401 → refresh → retry.
I've asked our good friend Claude why, it says:
The root cause is in
createServerConfig()inmcpjam-inspector/client/src/lib/oauth/mcp-oauth.ts. It bakes the access token into a staticAuthorizationheader and never passesrefreshTokenorclientIdto the backend:function createServerConfig(serverUrl: string, tokens: any): HttpServerConfig { // Note: We don't include authProvider in the config because it can't be serialized // when sent to the backend via JSON. The backend will use the Authorization header instead. // Token refresh should be handled separately if the token expires. return { url: serverUrl, requestInit: { headers: tokens.access_token ? { Authorization: `Bearer ${tokens.access_token}` } : {}, }, }; }Because
refreshTokenandclientIdare absent from the config,MCPClientManager.connectViaHttp()never instantiates aRefreshTokenOAuthProviderand theStreamableHTTPClientTransporthas noauthProvider— so when it receives a 401 there is no refresh path.
How to reproduce
- Configure an MCP server with OAuth 2.0 that issues short-lived access tokens (e.g.
expires_in: 10). - Connect to the server via the Inspector — OAuth flow completes successfully, tools are listed.
- Wait for the access token to expire (10+ seconds in this example).
- Click Run on any tool.
- The Response panel shows:
Streamable HTTP error: Error POSTing to endpoint: {"error":"invalid_token"}. - No refresh token exchange is attempted. All subsequent tool calls also fail.
Expected Behavior
When a tool call receives HTTP 401 with WWW-Authenticate: Bearer error="invalid_token", the Inspector should use the refresh token to obtain a new access token from the server's token endpoint, then retry the request.
Screenshots
Platform
Linux, MCPJam Inspector v2.0.5 (latest)
Additional Context
Our good friend Claude had the following suggestion:
The fix should be straightforward:
createServerConfig()should passrefreshTokenandclientId(both available inlocalStorage) as top-level fields in theHttpServerConfiginstead of a staticAuthorizationheader:function createServerConfig( serverUrl: string, tokens: any, clientId?: string, ): HttpServerConfig { return { url: serverUrl, refreshToken: tokens.refresh_token, clientId: clientId, }; }This would cause
MCPClientManager.connectViaHttp()(line ~1105) to create aRefreshTokenOAuthProviderand pass it asauthProviderto the transport, enabling the automatic 401 → refresh → retry flow that the SDK already supports and tests (sdk/tests/refresh-token-auth.test.ts).