[BUG] OAuth Authentication Succeeds but MCP Reconnection Fails - Requires Restart
Bug Report: OAuth Authentication Succeeds but MCP Reconnection Fails - Requires Claude Code Restart
Summary
After successful OAuth authentication with an MCP server using streamable-http transport, Claude Code displays "Authentication successful, but server reconnection failed. You may need to manually restart Claude Code for the changes to take effect." The OAuth tokens are correctly stored, but MCP tools remain unavailable until Claude Code is restarted.
Environment
- Claude Code Version: 2.0.26
- OS: Linux (Fedora 42, kernel 6.16.12)
- MCP Server: Custom Quarkus-based MCP server
- Transport: streamable-http
- Auth Method: OAuth 2.0 with Dynamic Client Registration (RFC 7591)
- OAuth Provider: Keycloak 24.0.3
Steps to Reproduce
- Configure an MCP server with OAuth using streamable-http transport:
``bash``
claude mcp add --transport http myserver http://localhost:8080/mcp
- Start MCP server with OAuth/OIDC enabled:
- Server implements Dynamic Client Registration (DCR)
- Server provides protected resource metadata at
/.well-known/oauth-protected-resource - Token lifetime: 24 hours
- Redirect URIs: localhost only (as per MCP spec)
- Run
/mcpcommand in Claude Code
- Complete OAuth flow in browser (login with test user)
- Observe authentication completion in browser
Expected Behavior
Based on Claude Code MCP documentation:
"Authentication tokens are stored securely and refreshed automatically."
Expected: After OAuth completes, Claude Code should:
- Store the OAuth tokens ✅ (works)
- Automatically reconnect to the MCP server using stored tokens ❌ (fails)
- Load authenticated MCP tools immediately ❌ (fails)
- No restart required ❌ (restart IS required)
Actual Behavior
- OAuth authentication completes successfully in browser
- Tokens are correctly stored in
~/.claude/.credentials.json:
``json``
{
"mcpOAuth": {
"myserver|<hash>": {
"serverName": "myserver",
"serverUrl": "http://localhost:8080/mcp",
"clientId": "<dynamically-registered-client-id>",
"accessToken": "[valid 24h JWT token]",
"expiresAt": 1761406726618,
"refreshToken": "[valid refresh token]",
"scope": "email profile"
}
}
}
- Claude Code displays error: "Authentication successful, but server reconnection failed. You may need to manually restart Claude Code for the changes to take effect."
- MCP tools are NOT available in the current session
- Running
claude mcp listshows:✗ Failed to connect - After restarting Claude Code:
- Connection succeeds automatically using stored tokens
- All authenticated MCP tools are available
- No re-authentication needed
Technical Details
Token Validity
The stored access token is valid and working:
- Decoded JWT shows:
exp: 1761406726(24 hours from issuance) - Token contains correct user identity
- Token includes proper scopes (
email profile) - Token can successfully call authenticated API endpoints when tested directly with curl
Server Configuration
- MCP server is running (verified with
curl http://localhost:8080/mcp→ HTTP 405 as expected) - Server properly implements:
- Dynamic Client Registration endpoint
- OAuth 2.0 protected resource metadata (RFC 9728)
- PKCE flow support
- Token validation
Transport Details
- NOT using deprecated SSE (this is different from issue #9127)
- Using modern
streamable-httptransport - Server is properly configured for streamable-http
Workaround
Restart Claude Code after OAuth authentication completes. The stored tokens are preserved and work correctly after restart.
Impact
- Poor user experience: requires manual restart after every OAuth authentication
- Contradicts documentation which states tokens work automatically
- Makes iterative development/testing of OAuth-enabled MCP servers cumbersome
- First-time users may think authentication failed when it actually succeeded
Related Issues
- #9127 - Different issue (SSE-specific servers like Jira)
- #956 - Auto-refresh OAuth (marked as fixed May 2025)
- #1845 - Auth lost on config update
- #7290 - HTTP/SSE transport ignores auth headers
This issue is distinct from #9127 as it affects streamable-http (modern protocol), not deprecated SSE.
Additional Notes
- The OAuth flow itself works perfectly (DCR succeeds, tokens are valid)
- The token storage works correctly
- The issue is specifically in the reconnection logic after initial authentication
- Subsequent Claude Code sessions work fine (tokens persist across restarts)
- The problem only occurs during the initial authentication session
Proposed Fix
After successful OAuth token storage, Claude Code should:
- Use the newly stored tokens to establish an MCP connection
- Load the MCP tools into the current session
- Avoid requiring a restart for a session state that should be hot-reloadable
Questions for Maintainers
- Is the "reconnection failed" + restart requirement intentional behavior?
- If so, why does the documentation not mention this?
- Is there a technical limitation preventing hot-reconnection after OAuth completes?
- Should the error message be clearer about whether restart is always required vs. optional?
---
Would you like me to test any additional scenarios or provide more debug information?
15 Comments
Found 1 possible duplicate issue:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
#9127 is all about SSE, which is deprecated. The problem can be reproduced using streamable HTTP.
same issue with newrelic mcp
<img width="1137" height="129" alt="Image" src="https://github.com/user-attachments/assets/fc4bd3cd-430c-447c-8796-8aeb99cd2647" />
Same here with supabase mcp
I have a custom MCP that uses Microsoft OAuth. Microsoft access tokens are valid for 60-75 minutes, so the MCP regularly enters an unauthenticated state. Refresh tokens are issued, but currently not used by Claude Code to automatically re-authenticate
I think I'm experiencing the same issue with the Notion mcp plugin. I've done additional investigation that suggests this is a Claude Code client-side issue, not a server-side problem.
Environment
Proof: The same OAuth tokens work perfectly via curl
After Claude Code's OAuth flow completed (and failed with 401)
# Debug Log Evidence
From ~/.claude/debug/latest:
[DEBUG] MCP server "plugin:Notion:notion": Initializing HTTP transport to https://mcp.notion.com/mcp
[DEBUG] MCP server "plugin:Notion:notion": HTTP transport options: {"url":"https://mcp.notion.com/mcp","headers":{"User-Agent":"claude-code/2.0.75"},"hasAuthProvider":true,"timeoutMs":60000}
## Tokens are successfully retrieved
[DEBUG] MCP server "plugin:Notion:notion": Returning tokens
[DEBUG] MCP server "plugin:Notion:notion": Token length: 86
[DEBUG] MCP server "plugin:Notion:notion": Has refresh token: true
[DEBUG] MCP server "plugin:Notion:notion": Expires in: 3594s
## Tokens are saved
[DEBUG] MCP server "plugin:Notion:notion": Saving tokens
[DEBUG] MCP server "plugin:Notion:notion": Token expires in: 3600
[DEBUG] MCP server "plugin:Notion:notion": Has refresh token: true
## Then it fails
[DEBUG] MCP server "plugin:Notion:notion": HTTP Connection failed after 1085ms: Streamable HTTP error: Server returned 401 after successful authentication
[ERROR] MCP server "plugin:Notion:notion" Error: Streamable HTTP error: Server returned 401 after successful authentication
[ERROR] MCP server "plugin:Notion:notion" Connection failed: Streamable HTTP error: Server returned 401 after successful authentication
I extracted the tokens and tested manually:
## Initialize MCP session - works!
curl -X POST https://mcp.notion.com/mcp \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize",...}'
Returns: {"result":{"protocolVersion":"2024-11-05","serverInfo":{"name":"Notion MCP"}}}
## Call tools - works!
curl -X POST https://mcp.notion.com/mcp \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Mcp-Session-Id: $SESSION_ID" \
-d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"notion-search",...}}'
Returns search results successfully
This proves:
The bug looks to be specifically in how Claude Code reconnects to the MCP server after storing the OAuth tokens, not in the OAuth flow itself or the server.
Okay, I was able to figure out a workaround for the above error:
do the following instead:
claude mcp add <app> -- npx -y mcp-remote@latest <url>i'm also getting this problem...
Additional data point: Slack's MCP server (
mcp.slack.com/sse) returns a 302 redirect to a shard-specific host before establishing the SSE connection:This may be a contributing factor to the reconnection failure – the SSE/HTTP client may not be following the redirect or carrying the OAuth bearer token through to the target host.
Tested with both
--transport httpand--transport sseusing the new pre-configured OAuth credentials (--client-id/--client-secret) from v2.1.30. Both produce the same 'Authentication successful, but server reconnection failed' result.Might there be any possibility of having this resolved in the near future?
bump!
Please don't go stale. We need this fixed.
I spoke with NR. Here's what they said.
Per this public document, New Relic AI Model Context Protocol (MCP) is in Preview status at this time, which means a user with Core or Full Platform user type that has the Billing User role, must have opted into the New Relic AI MCP Server preview of in the Previews & Trials UI (User menu -> Administration).
Thanks for the report. We've made a number of improvements to authenticated MCP server stability since this was filed, including the post-OAuth reconnect path. Closing this out; if you're still seeing auth or reconnect failures on a current build, please open a new issue with your Claude Code version, the MCP server URL, and the exact error text shown so we can trace it.
This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.