[BUG] MCP OAuth re-auth UI not shown for page reload/background Streamable HTTP auth failure
Preflight Checklist
- [x] I have searched existing issues and did not find this exact behavior
- [x] This is a single bug report
What's Wrong?
For a custom Streamable HTTP MCP server that uses OAuth, Claude shows different auth recovery behavior depending on how the expired MCP access token is encountered.
This is not a refresh-token bug. In this setup the server intentionally does not rely on refresh tokens; when the MCP access token expires, an explicit user re-authentication flow is expected.
Observed split:
- If the token expires while the conversation is still active, and the user sends a follow-up message that invokes the MCP server, Claude surfaces the OAuth/reconnect modal. Completing the OAuth flow reconnects the MCP server and the conversation can continue.
- If the token expires and the user refreshes/reopens the Claude conversation page, Claude appears to reload existing MCP/widget content in the background. That background Streamable HTTP request receives an auth failure, but Claude renders a blocking Streamable HTTP error instead of showing the same OAuth/reconnect UI.
This leaves the existing conversation in a bad state: the user cannot cleanly re-authenticate from the reload path, and sending a new follow-up just to force the reconnect UI dirties the conversation.
What Should Happen?
When a Streamable HTTP MCP request during page reload, conversation rehydration, widget bootstrap, or any other background reload path receives an OAuth 401/auth challenge, Claude should surface the same OAuth/reconnect UI that it surfaces for a user-initiated MCP tool call.
The user should be able to re-authenticate without sending a new chat message.
What Happens Instead?
On page refresh/reopen, Claude shows a hard Streamable HTTP error similar to:
Streamable HTTP error: Error POSTing to endpoint: {
"type":"error",
"error":{
"type":"authentication_error",
"message":"OAuth token has been invalidated. Re-authentication is required.",
"details":{"error_code":"mcp_invalid_oauth_token"}
},
"request_id":"..."
}
No OAuth/reconnect modal is shown in that reload path.
Steps to Reproduce
- Configure a custom Streamable HTTP MCP server using OAuth authorization-code/PKCE.
- Have the MCP server issue short-lived access tokens without relying on refresh tokens.
- Connect the MCP server in Claude and use a tool successfully in a conversation.
- Wait for the MCP access token to expire.
- In the still-open conversation, send a follow-up that needs the MCP server.
- Actual: Claude shows the OAuth/reconnect modal.
- This part works as expected.
- Reconnect, use the MCP server again, then wait for the token to expire again.
- Refresh/reopen the Claude conversation page so existing MCP/widget content is rehydrated.
- Actual: Claude shows a blocking Streamable HTTP auth error.
- Expected: Claude shows the OAuth/reconnect modal without requiring a new user message.
Why This Seems Client-Side
The same expired-token condition can trigger the OAuth/reconnect UI when reached through a user-initiated MCP call. The failure appears specific to the page reload / background rehydration path, where the auth challenge is rendered as a hard Streamable HTTP error instead of being routed through the OAuth reconnect UI.
Related but not exact matches:
- #5706 has a comment noting that mid-session tool invocation and startup/session connection use different refresh/auth paths: https://github.com/anthropics/claude-code/issues/5706#issuecomment-3958067044
- #65036 tracks refresh-token based "Connection expired" behavior, but this report is about explicit re-auth UI not appearing on page reload/background auth failure when refresh tokens are not part of the design.
Claude Surface
Claude web conversation page with a custom Streamable HTTP MCP connector.
Additional Information
This is especially painful for MCP widgets or tool-result content that reloads when the page is refreshed: the user sees a blocking rendering/auth error but has no direct reconnect action in that context.