[BUG] Claude Desktop doesn't connect to Custom MCPs altogether (not with OAuth 2.1 nor with SSE)
Hi Anthropics Team,
We have developed and deployed an MCP server with OAuth 2.1 authentication for the purposes of our company.
The deployed MCP works fantastically with Claude Code!
claude mcp add --transport http custom_mcp [redacted-url]
It requires the authentication, goes through the authentication process, lists all the tools and use them appropriately. All communication is logged via server logs.
When configured in Clade Desktop as a Connector with the same url, the service is never contacted. When clicking "Connect":
- Claude in a browser issues an event type: event : "claudeai.mcp.auth.init". Soon later it reloads the page with the error: "There was an error connecting to [Your custom Connection] Please check your server URL and make sure your server handles auth correctly.
- Claude Desktop application opens a url: https://claude.ai/api/organizations/[redacted-id]/mcp/start-auth/[redacted-id]?redirect_url=claude%3A%2F%2Fclaude.ai%2Fnew%3F&open_in_browser=1&fromDesktopApp=true , which in turn opens a New Conversation in the application and nothing happens
This time, no request reaches the deployed server. No single query, successful or not, is logged by the service. The communication seems to be broken when it reaches Claude servers.
Please investigate why Claude Desktop doesn't issue any requests (authentication or functional) to Custom Connectors.
66 Comments
Found 3 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
Endorse https://github.com/anthropics/claude-code/issues/3515
Make it high priority.
Close this ticket as a duplicate of https://github.com/anthropics/claude-code/issues/3515
I am also facing the same issue. Is there any workaround for it?
I also faced exactly the same issue
I also faced exactly the same issue
I am also facing this issue. What's working in a variety of other clients (MCP Inspector, VS Code, Cursor, Cloudflare's AI Playground), Claude Desktop appears to not make the followup request to the
resource_metadataURL that is provided in theWWW-Authenticateheader when no Bearer token is provided on theAuthorizationheader, so the OAuth dance stops prematurely.I solved the issue by allowing anthropic's outbound IP addresses to my WAF firewall
Also facing this exact issue - any updates? Works perfectly in Claude Code 👍
Glad that I'm not the only one seeing this.
Debugged it through and through. I'll give a stab at Claude Code. Thanks!
Small update. I managed to get it working, albeit extremely flaky. Hard to tell if the flakiness is due to some state in Claude Desktop, or some bug in the app.
But as mentioned before in this thread by @anyoung-tableau, it seems that Claude Desktop doesn't read or care about the WWW-Authenticate metadata like
resource_metadataetc.Instead it seems to just test some various URLs like:
I tried adding redirects for these to my actual locations, but that didn't seem to work (but again, its hard to tell when it super flaky).
What did finally make it work was just proxying those requests directly (example with Fastify):
Despite this though, it seems to fail about 70% of the time with no clear reason. Whereas in Claude Code it works flawlessly.
+1, same issue here. here is a summary of the debugging session I had with Claude Code. There is 0 debugging on Claude Desktop which doesn't help. Tried both Streamable HTTP and SSE.
TL;DR: everything works fine in Claude Code but fails miserably in Claude Desktop. Long version below.
Claude Desktop SSE MCP Connection Failure - Debugging Summary
Problem Description
Custom MCP server with OAuth 2.0 SSE transport works perfectly with MCP Inspector but fails silently with Claude Desktop after OAuth completion.
Environment
rmcplibraryhttps://{uuid}.saramcp.comWhat Works ✅
initializerequest: ✅ PASStools/listrequest: ✅ PASS (returns 2 tools).well-knownendpoints return correct metadataWhat Fails ❌
Claude Desktop completes OAuth but never establishes SSE connection.
Server Logs Evidence
Network Tab Evidence (Chrome DevTools)
Using
developer_settings.jsonwith DevTools enabled in Claude Desktop:Observed:
Filter: Searching for domain in Network tab shows ZERO requests after OAuth completion.
Connector Behavior
https://{uuid}.saramcp.comclaude.ai/newOAuth Metadata Comparison
Working Server (Doxyde.com)
Our Server (Same Structure)
Both use identical structure. Doxyde works, ours doesn't.
What We Tried (All Failed)
response_modes_supported: ["query"]to auth server metadataresourcefield per RFC 9728resourcefield to match working serversNone of these changed the behavior.
Authorization Server Metadata (Full)
SSE Server Implementation
Library:
rmcp(Rust MCP SDK) - official implementationEndpoints:
GET /- SSE connection endpointPOST /message- Message endpointVerified working with:
Hypothesis
The issue appears to be in Claude Desktop's OAuth-to-SSE bridge:
claude.aicompletes authentication ✅The bug is NOT in:
The bug IS in:
Debug Logs Access
Server logs: Full request/response logging with timestamps
Claude Desktop logs:
~/Library/Logs/Claude/mcp*.log(no errors shown)DevTools: Network tab shows OAuth but no SSE connection
Reproducibility
100% reproducible across multiple attempts, different servers, different configurations.
Request for Anthropic
Could you please add more verbose logging to Claude Desktop's MCP connector system? Specifically:
Currently there is ZERO feedback to developers when this fails. The connector just vanishes silently.
Workaround
None known. MCP Inspector works, but Claude Desktop does not. Claude Code (CLI) works fine.
---
Happy to provide more logs, traces, or test any debugging approaches. Server is running at production URL and can be tested anytime.
I also faced exactly the same issue
Same issue here
Could be same problem as mine - https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1674
But in my case claude receives token as just just calls mcp without it..
@jhiver why 'Browser redirects back to claude.ai/new'? It should redirect to https://claude.ai/api/mcp/auth_callback, no?
Facing same issue
My current theory is that Claude and MCP Inspector both are incorrectly executing the HTTP session handshake on HTTP streamable. When I switched both to sse, I was able to connect properly. Claude Desktop is still doing weird things however. The connection will persist in a chat conversation over many hours, but if I start a new chat, the tool calls fail for both the new chat and the existing chat. My server shows a proper session and refresh token exchange, but also a bunch of new auth requests from Claude. Very strange.
And MCP calls in the client are just rate limited, so even if you get it to work it stinks. I asked Claude to make calls in quick succession and it only made seven relatively slow calls before breaking.
Any workarounds?
Not that I've found yet. Works great for a few minutes, then all the tool calls start failing. I don't have this kind of auth problem with any other AI agent or LLM.
Same issue here.
MCP connection works fine with ChatGPT, Mistral, Dust, but not with Claude.
Worked fine with Claude until October 26.
Auth looks ok but in the browser, at the end of the auth:
https://claude.ai/settings/connectors?&server=189fd97b-ed2c-45fd-92ee-27320c6cc04f&step=end_error
and then authenticate is called with no token.
We desperately tried to get some support from Anthropic for 8 days now, with no answer.
This is crazy.. made whole protocol, made it popular, but dont care about own implementation.. give us at least ability to see some error log..
Got an answer from Anthropic.
The problem was that in the authentication workflow, the initialize method (the one returned in WWW-Authenticate, in my case /oauth-protected-resource) returned 200 instead of 401.
Now /oauth-protected-resource returns the metadata in a 401 answer and it is fine.
I do not see the link between the fix and what I observed (and it used to work with a 200), but it does fix the issue.
I can connect over SSE. I am returning a 401, so my issue isn't the same. Claude itself is convinced the issues on the platform are severe. The same tool call in the stretch of a couple minutes will fail or succeed intermittently. Failed calls never make it to the server. If you do get it to work, it quickly hits a weird ~6 tool call rate limit within one conversation. It's really quite bad in comparison to Claude Code, which works well with no problems.
I'm facing a similar issue. Everything was working fine until last week, but it suddenly stopped. I'm now getting a start_error in the URL. I tried reaching out through the Fin bot, but it keeps repeating the same resolution and doesn't seem to understand the problem. how did you reach out them ?
https://claude.ai/settings/connectors?&server=e231fb70-965e-4fc4-b756-607319035894&step=start_error
We wrote to support@anthropic.com. It took them one week to answer.
So. A couple of additional thoughts. I've had more initial connection stability since making sure that WWW-Authenticate headers were set properly. However, client side tool call failures are still intermittent. On SSE, Claude Desktop makes POST calls to the SSE endpoint that it shouldn't. And on httpstreamable, some tool calls just disappear. No server log for them and they fail client side.
I was able to resolve the issue I was having by doing 2 things:
client_secret_postas an advertised auth method. Previously I was only advertisingclient_secret_basic(even though it was supported by the token endpoint) but Claude usesclient_secret_postand posts client credentials on the token request body, not in the Authorization header.WWW-Authenticateheader always usedhttpfor theresource_metadataURL. Every other client I've used seems to "upgrade" it to https for me but Claude didn't and I hadn't noticed that until now. :)If you are providing Dynamic Client Registration and sending empty or null values in the registration response, such as logo_url: null, then it will silently fail. You should be omitting all the fields that are not applicable or not there.
Infact, it does not even send the
resourceparameter in the authorization request as per their own spec - https://modelcontextprotocol.io/specification/draft/basic/authorization#resource-parameter-implementationI have fixed the Dynamic Client Registration doing this things: (it now connects correctly).
Bearer realm="mcp", resource_metadata="https://mymcphost.com/.well-known/oauth-protected-resource"
token_endpoint_auth_methods_supportedregistration_endpointresponse must have this info.this is a claude request sent to
registration_endpoint`
Define your static credentials here (or pull from env vars for security)
You will provide these values to Claude.ai
STATIC_CLIENT_ID = os.getenv("OAUTH_CLIENT_ID", "mcp-obsidian-client")
STATIC_CLIENT_SECRET = os.getenv("OAUTH_CLIENT_SECRET", "super-secret-obsidian-key-change-this")
-----------------------------
OAuth storage
We pre-populate the allowed client immediately
oauth_clients: Dict[str, dict] = {
STATIC_CLIENT_ID: {
"client_id": STATIC_CLIENT_ID,
"client_secret": STATIC_CLIENT_SECRET,
# You might need to adjust this based on where Claude is redirecting
"redirect_uris": ["https://claude.ai/oauth/callback", "http://localhost:8080/callback"],
"client_name": "Claude"
}
}
oauth_codes: Dict[str, dict] = {}
oauth_tokens: Dict[str, dict] = {}
@app.post("/register")
async def register_client(request: Request):
"""
Dynamic Registration is disabled/modified to return the static credentials.
This ensures only your pre-defined ID/Secret works.
"""
body = await request.json()
# We ignore the request to create new credentials and return our static ones
return JSONResponse({
"client_id": STATIC_CLIENT_ID,
"client_secret": STATIC_CLIENT_SECRET,
"client_id_issued_at": 1234567890,
"redirect_uris": body.get("redirect_uris", [])
})
@app.get("/authorize")
async def authorize(
request: Request,
response_type: str = None,
client_id: str = None,
redirect_uri: str = None,
state: str = None,
code_challenge: str = None,
code_challenge_method: str = None
):
"""OAuth Authorization Endpoint"""
# Check if the requested Client ID matches our static one
if client_id != STATIC_CLIENT_ID:
return HTMLResponse(f"<h1>Invalid client: {client_id}</h1>", status_code=400)
# Auto-approve (skip user consent for simplicity)
code = secrets.token_urlsafe(32)
oauth_codes[code] = {
"client_id": client_id,
"redirect_uri": redirect_uri,
"code_challenge": code_challenge,
"code_challenge_method": code_challenge_method
}
logger.info(f"Issued authorization code for client {client_id}")
# Redirect back to Claude with the code
separator = "&" if "?" in redirect_uri else "?"
redirect_url = f"{redirect_uri}{separator}code={code}"
if state:
redirect_url += f"&state={state}"
return RedirectResponse(redirect_url)
@app.post("/token")
async def token_endpoint(
request: Request,
grant_type: str = Form(None),
code: str = Form(None),
redirect_uri: str = Form(None),
client_id: str = Form(None),
client_secret: str = Form(None),
code_verifier: str = Form(None)
):
"""OAuth Token Endpoint"""
if grant_type != "authorization_code":
return JSONResponse({"error": "unsupported_grant_type"}, status_code=400)
if code not in oauth_codes:
return JSONResponse({"error": "invalid_grant"}, status_code=400)
code_data = oauth_codes[code]
# 1. Validate Client ID
if code_data["client_id"] != client_id:
return JSONResponse({"error": "invalid_client_id"}, status_code=400)
# 2. Validate Client Secret (ADDED THIS CHECK)
# We check against our stored static client
stored_client = oauth_clients.get(client_id)
if not stored_client or stored_client["client_secret"] != client_secret:
logger.warning(f"Failed secret check for client {client_id}")
return JSONResponse({"error": "invalid_client_secret"}, status_code=401)
# Generate access token
access_token = secrets.token_urlsafe(32)
oauth_tokens[access_token] = {
"client_id": client_id,
"scope": "mcp"
}
# Clean up used code
del oauth_codes[code]
logger.info(f"Issued access token for client {client_id}")
return JSONResponse({
"access_token": access_token,
"token_type": "Bearer",
"expires_in": 3600
})`
This Works
My MCP server broke some time after October. For those looking for a fix I was able to correct it by making sure my WWW-Authenticate header had the resource_metadata value set to https. My server is behind a reverse proxy and was returning http instead of https. This apparently used to work (and still works with MCP Inspector) but no longer works with claude.
FIX: ensure resource_metadata="https://your-server.com/.well-known/oauth-protected-resource"
I'm experiencing the same issue. Would you mind sharing what your .well-known/oauth-protected-resource endpoint returns?
In my case, the response looks like this (with sensitive data removed):
Logs from my server:
I ran into most of these same issues while implementing OAuth for my MCP server. Ended up writing down everything I learned: [OAuth for MCP Server: Complete Guide to Protecting Claude](https://www.buildwithmatija.com/blog/oauth-mcp-server-claude)
A few things that caught me:
client_secret_postneeds to be intoken_endpoint_auth_methods_supported(Claude Web uses this specifically)resource_metadatain WWW-Authenticate must be https:// even behind reverse proxies.well-knownendpoints - you need to add exceptionsThe guide has full Next.js code examples and walks through the complete OAuth 2.1 setup. Hope it saves someone the debugging time.
We're having exactly the same problem. These connectors are the only reason we have standard users subscribed in our team plan. If it isn't fixed, we'll unsubscribe them.
I've tried walking through this but haven't had any luck. It authenticates fine but doesn't make any calls once it's authenticated. Will add some details when I get a chance.
Looking at the logs was a saver for me. Are the /mcp/see POST requests coming through (Mine were 401). Another one is the firewall
| # | Check | Status | Details |
|-----|---------------------------------------|--------|-------------------------------------------------------------------------------------------------|
| 1 | Auth Server Metadata | ✅ | issuer, authorization_endpoint, token_endpoint, registration_endpoint all present with https:// |
| 2 | token_endpoint_auth_methods_supported | ✅ | Includes client_secret_post, client_secret_basic, none |
| 3 | code_challenge_methods_supported | ✅ | Includes S256 |
| 4 | grant_types_supported | ✅ | Includes authorization_code, refresh_token |
| 5 | Protected Resource returns 200 | ✅ | HTTP 200 (not 401) |
| 6 | resource field uses https:// | ✅ | https://mcp.example.com and https://mcp.example.com/sse |
| 7 | Dynamic Client Registration | ✅ | Returns 201 with client_id, client_secret, correct fields |
| 8 | No null values in registration | ✅ | 0 null values found |
| 9 | WWW-Authenticate header | ✅ | resource_metadata uses https:// URL |
| 10 | CORS on OAuth metadata | ✅ | access-control-allow-origin: * |
| 11 | CORS on Protected Resource | ✅ | Full CORS headers present |
| 12 | OPTIONS preflight | ✅ | Returns 204 with proper CORS for https://claude.ai |
| 13 | Health check | ✅ | Server responding |
What Works ✅
Claude Code CLI - Works perfectly:
Manual curl testing - Works perfectly:
MCP Inspector - Works perfectly with both transport modes.
What Fails ❌
Claude.ai Web Connector:
https://mcp.example.comorhttps://mcp.example.com/sseServer Logs During Claude.ai Attempt
The server receives the token exchange request and successfully issues a token, but Claude.ai never proceeds to establish the MCP connection.
Server Implementation Details
/,/mcp,/sse(all support Streamable HTTP)@modelcontextprotocol/sdklatestI've implemented all required OAuth metadata endpoints:
/.well-known/oauth-authorization-server/.well-known/oauth-protected-resource/register(Dynamic Client Registration)/oauth/authorize+/oauth/authorize/approve/oauth/token(authorization_code + refresh_token grants)Conclusion
The OAuth flow is completing correctly (verified by server logs showing successful token issuance). The breakdown occurs after token exchange - Claude.ai's infrastructure isn't proceeding to send the MCP
initializerequest. This matches what others are reporting: the requests never leave Claude's side.Potential Workaround: Manual OAuth Credentials
If you're experiencing connection issues with OAuth 2.1, try using manual client credentials instead of automatic discovery:
Why This May Help
Several users (including myself on Claude.ai web/mobile) have found that manual credential entry bypasses OAuth initialization issues that occur during automatic discovery.
OAuth Providers That Support This
Worth testing if you're stuck with authentication failures.
I finally got it going!
Root Cause
Cloudflare Tunnel buffers SSE (Server-Sent Events) responses, preventing real-time streaming required by the MCP Streamable HTTP transport.
The connection flow would succeed up to:
The SSE GET request returns HTTP 200, but Cloudflare buffers the event stream data instead of streaming it in real-time. Claude Web/Desktop waits for SSE events that never arrive, then times out.
Evidence
Solution
Use ngrok instead of Cloudflare Tunnel:
ngrok http <mcp-server-port>
ngrok streams SSE responses correctly, and Claude Web/Desktop connects successfully.
Other Findings
Additional Data Point: Cloudflare Workers (not Tunnel) - Same Issue
I wanted to contribute another data point that might help narrow down this issue.
Our Setup
We're running an OAuth 2.1-protected MCP server on Cloudflare Workers (https://api.8004.dev) using:
/sse, JSON-RPC at/mcpImportant distinction: We're using Cloudflare Workers, not Cloudflare Tunnel. This means the SSE buffering issue mentioned by @boogey100 in cloudflare/cloudflared#1449 does not apply to our infrastructure. Workers streams SSE natively without buffering.
What Works ✅
claude mcp add --transport http``
json
``{
"mcpServers": {
"8004-agents": {
"command": "npx",
"args": ["mcp-remote", "https://api.8004.dev/sse"]
}
}
}
What Doesn't Work ❌
Claude.ai web custom connectors fail after OAuth completes:
GET /ssewith valid Bearer tokenWhat We've Tried (all unsuccessful)
initResponsesending vs. onlyevent: endpoint2024-11-05,2025-03-26,2025-06-18,2025-11-25)Key Insight
Since our infrastructure is Cloudflare Workers (not Tunnel), we can rule out the SSE buffering/flush issues entirely. Our SSE streams work perfectly with:
mcp-remote(npx package)curlwith SSE streamingThe fact that the same SSE endpoint works with Claude Code CLI but fails with Claude.ai/Claude Desktop suggests the issue is client-side in how these clients handle OAuth-protected SSE connections.
Current Workaround
Using
mcp-remoteas a bridge successfully bypasses the OAuth issue:This works because
mcp-remotehandles the OAuth flow correctly and maintains the SSE connection, then bridges it to Claude Desktop via stdio.Hypothesis
Given that:
This points to a client-side timeout or connection handling issue in Claude.ai/Claude Desktop when dealing with OAuth-protected SSE endpoints, rather than an infrastructure or SSE format problem.
Would it be possible to get more verbose client-side logging to see why the connection is being canceled?
---
Server implementation: api.8004.dev (open source, Cloudflare Workers + Hono.js)
Live endpoints:
We don't use tunnels but we do use Cloudflare, and this comment got me thinking, so I went in and turned off the proxy in Cloudflare, and sure enough, it works if the proxy is turned off.
That's 4 hours of my life I'll never get back, but this post right here saved me the rest of the night at least.
Truly superb work, thank you. I had exactly this problem, and been all around the houses modifying the ModelContextProtocol.CSharkSdk thinking it must be a deficiency in that implementation. Turns out it was CloudFlare proxy the whole time. Amazing job @boogey100 !
We got our remote MCP server working properly. Using just the remote MCP URL, and also adding the advanced ClientID/Secret option (that work like implicit creds).
The trick was to use standard port 443 for the server (and all redirects). What doesn't work at all is if you use a port other than 443... that's it.
I had to rebuild mpc-handler from scratch. I got streamed HTTP working which is an upgrade from now legacy SSE. It works in Claude, ChatGPT, ...
You saved at least 24 hours for me. Although I'm a little worried about getting DDOSed without orange cloud turned on.
This issue has been inactive for 30 days. If the issue is still occurring, please comment to let us know. Otherwise, this issue will be automatically closed in 30 days for housekeeping purposes.
Adding another data point here with the official Granola MCP server (
https://mcp.granola.ai/mcp), which uses Streamable HTTP transport with OAuth.Symptoms (identical to OP):
Works in Claude Code CLI:
Inconsistent behavior across users:
A colleague on the same Granola workspace was able to connect the same Granola MCP server in Cowork mode successfully — it completed OAuth, exposed tools, and retrieved meeting data. Same connector URL, same Granola plan. So this doesn't appear to be a universal transport or protocol issue — it's intermittent or user/session-specific.
Resolution: Disconnecting and reconnecting the connector in Desktop settings fixed it. OAuth triggered on the second attempt, tools appeared, and the connector is now functional in Cowork. No changes to the server or account — just a disconnect/reconnect cycle.
This suggests the initial connection attempt gets into a bad state silently, and the UI has no mechanism to surface the failure or retry. The workaround is simple, but the problem is that a user would never know to try it — from the UI it looks like the connector just doesn't work.
For comparison: Atlassian's MCP connector (
https://mcp.atlassian.com/v1/sse, SSE transport) connected on the first attempt without issue on the same machine.Environment: macOS, Claude Desktop (latest), Cowork mode
Same issue with Nia MCP on Claude.ai (Feb 2026)
Experiencing the same connection failure when adding Nia's remote MCP server (
https://apigcp.trynia.ai/mcp) as a custom connector on Claude.ai & Claude DesktopError:
Key details:
a3f5497cb3ce3f7eEnvironment: Claude.ai Max plan, macOS
bumping this bug. This is forcing all MCPs to go through the Claude marketplace as opposed to allowing for custom MCP use.
Experiencing this issue as well, unable to connect to Braintrust MCP because of this, is there an ETA on when this will be fixed??
Experiencing this issue trying to connect to the custom Braintrust MCP at https://api.braintrust.dev/mcp. The first issue took the user to the auth page in browser but displayed the below error message after the flow was complete. The second issue did not ever make it to the browser and showed the same error.
Error Reference:
72231b3347ba4a24The same MCP server works with Claude Code.
There was an error connecting to the MCP server. Please check your server URL and make sure your server handles auth correctly.Also seeing this. Get it fixed ASAP
Same issue. Can't connect to n8n.
is this still an isssue
Very much so.. all remote-hosted MCPs (Cloudflare Workers, for example) are unable to connect, so anyone using iOS/iPad dev environments or agents instead of desktop is down. Hoping for a fix 𝘴𝘰𝘰𝘯..
For reference, see also issue #11814:
https://github.com/anthropics/claude-code/issues/11814
https://github.com/anthropics/claude-code/issues/5826#issuecomment-3660091927
I have a solution! (Tested)
Turns out it’s not a “bug” on Anthropic’s end, but rather specific requirements regarding WAF rules, 401 authentication, and DCR (also make sure you’re not blocking bots and crawlers). If remote hosting your MCP server on CloudFlare as Worker, you’ll also need to create a KV namespace and Bind to it. Here’s the entire procedure:
Prerequisites (one-time per worker)
worker.js requirements (the v4 pattern)
∙ GET /.well-known/oauth-authorization-server - includes registration_endpoint
∙ GET /.well-known/oauth-protected-resource
∙ POST /register - Dynamic Client Registration, stores in KV
∙ GET /authorize - generates one-time code, stores in KV, redirects back
∙ POST /token - exchanges code for BEARER_TOKEN
∙ POST /mcp - returns 401 + WWW-Authenticate when unauthenticated
∙ All above must use env.MCP_DATA for KV ops
Connecting in Claude.ai
If you’re still running into errors upon trying to Connect, type your exact error code into Gemini, it knows them all and will offer suggestions. Gemini seems to know Claude better than Claude.. haha.
I faced two issues building the MCP server for https://github.com/ridafkih/keeper.sh with
better-auth. Putting this here in case anyone else runs into any issues.clientRegistrationAllowedScopes.token_endpoint_auth_method: "client_secret_post"in the registration request, whichbetter-authrejects without being already authenticated, butbetter-authdoesn't downgrade this to'none'and instead rejects the request outright with a 401. You need to downgrade it manually.If all your
/.well-known/...endpoints are configured correctly after that, then you should be good to go. Worked for me once this was done.Please fix, if developers are not able to connect claude reliably to developer tools this will make developers move off the claude platform.
I been waiting for this for last one month Sent from my iPhoneOn Mar 29, 2026, at 8:44 PM, Tushar Shrivastav @.***> wrote:tspython left a comment (anthropics/claude-code#5826)
Please fix, if developers are not able to connect claude reliably to developer tools this will make developers move off the claude platform.
—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you commented.Message ID: @.***>
For those stuck on OAuth/SSE connections with custom MCP servers — NyxID (https://github.com/ChronoAIProject/NyxID) can act as a local proxy that handles the auth layer separately from the MCP transport.
Instead of debugging the OAuth 2.1 handshake between Claude Desktop and your MCP server, you point Claude at NyxID's endpoint. NyxID handles credential injection and token refresh at the proxy layer, forwarding authenticated requests to your actual MCP server.
This decouples the auth problem from the transport problem — if SSE works but OAuth doesn't (or vice versa), NyxID lets you solve them independently.
Self-hosted and open source: https://github.com/ChronoAIProject/NyxID
Hosted version in closed beta — DM me for an invite code.
We're hitting the same issue with a WordPress-based MCP server and Cowork connectors (not Claude Code CLI — that path works fine for us too).
Our setup: OAuth 2.1 with PKCE, DCR, RFC 9728 protected resource metadata, RFC 8414 AS metadata, RFC 9207 iss parameter, public client support, Streamable HTTP transport. Server is on WP Engine staging.
What we can confirm from our side:
Full E2E test passes manually: DCR → PKCE → code exchange → bearer token → 17 tools returned. The OAuth server is correct.
All endpoints reachable from cloud infrastructure (verified via curl from multiple IPs).
All .well-known metadata documents return correct JSON with valid registration_endpoint, token_endpoint, code_challenge_methods_supported, etc.
What our audit log shows:
We have server-side audit logging on every OAuth event. When Cowork attempts to connect:
Without pre-registered credentials: Cowork's server IP hits our MCP endpoint, gets the expected 401 with WWW-Authenticate: Bearer resource_metadata="...". Then nothing. Zero metadata discovery requests. Zero DCR requests. Zero authorize requests. Immediate step=start_error in the Cowork callback URL.
With pre-registered credentials (client_id + client_secret in advanced settings): The flow gets further. Consent screen appears, user clicks Allow, auth code is issued, browser reaches claude.ai/api/mcp/auth_callback?code=XXX&state=YYY&iss=ZZZ. Then Cowork's backend never calls our token endpoint. Auth code stays used=0. Callback URL shows step=end_error&error_code=mcp_token_exchange_failed.
We can distinguish Cowork's server IP from our test traffic in the audit log. Cowork's IP produces only oauth.fail 401 events (the initial probe). Every DCR registration, token exchange, and successful auth in the log is from our manual testing.
Cowork flow IDs: ofid_27429fd45ba0de2c, ofid_3b8cd7caacc4eab9, ofid_a799fc9f773051a2, ofid_67d6f2f63977f127, ofid_756e0939199e36ab
What we ruled out: Safe Browsing, wp_safe_redirect, code TTL, missing iss parameter, public client auth method mismatch, short alias redirects losing POST body, WP Engine WAF, stale client state. We shipped 7 patch versions (v1.0.7 through v1.0.13) systematically eliminating server-side hypotheses. The server is not the problem.
This connector was previously working. The regression appeared without changes on our server side.AskOpus 4.6
GitHub Comment for anthropics/claude-code#5826
Copy/paste the content below the line into a comment on https://github.com/anthropics/claude-code/issues/5826*
---
We're hitting the same issue with a WordPress-based MCP server and Cowork connectors (not Claude Code CLI — that path works fine for us too).
Our setup: OAuth 2.1 with PKCE, DCR, RFC 9728 protected resource metadata, RFC 8414 AS metadata, RFC 9207
issparameter, public client support, Streamable HTTP transport. Server is on WP Engine staging.What we can confirm from our side:
.well-knownmetadata documents return correct JSON with validregistration_endpoint,token_endpoint,code_challenge_methods_supported, etc.We applied every fix mentioned in this thread (v1.0.14) — none resolved it:
Based on the comments here, we shipped a patch that includes ALL of the following:
WWW-Authenticateadded toAccess-Control-Expose-Headerson the MCP endpoint's 401 responseAccess-Control-Allow-Origin: *,Allow-Methods,Allow-Headers) on/.well-known/oauth-protected-resourceand/.well-known/oauth-authorization-server(these were served via WordPressparse_request, bypassing REST API CORS entirely)/.well-known/oauth-protected-resource/mcp, etc.) per the 2025-11-25 specMCP-Protocol-VersionandMcp-Session-Idadded toAccess-Control-Allow-Headersresource_metadataURL forced to HTTPS (guards against reverse-proxy HTTP leak)claude.aiandclaude.comcallback URLs accepted per Anthropic's docsCache-Control: private, no-store, no-cache, must-revalidate, max-age=0on well-known responses + Set-Cookie to bust WP Engine's edge cache (verified:x-cacheable: NO:Private)After deploying v1.0.14 with all of the above, the Cowork connector fails identically.
What our audit log shows:
We have server-side audit logging on every OAuth event. When Cowork attempts to connect:
WWW-Authenticate: Bearer resource_metadata="...". Then nothing. Zero metadata discovery requests. Zero DCR requests. Zero authorize requests. Immediatestep=start_errorin the Cowork callback URL.claude.ai/api/mcp/auth_callback?code=XXX&state=YYY&iss=ZZZ. Then Cowork's backend never calls our token endpoint. Auth code staysused=0. Callback URL showsstep=end_error&error_code=mcp_token_exchange_failed.We can distinguish Cowork's server IP from our test traffic in the audit log. Cowork's IP produces only
oauth.fail401 events (the initial probe). Every DCR registration, token exchange, and successful auth in the log is from our manual testing.Cowork flow IDs:
ofid_8dc382cbf72b9ab3,ofid_27429fd45ba0de2c,ofid_3b8cd7caacc4eab9,ofid_a799fc9f773051a2,ofid_67d6f2f63977f127,ofid_756e0939199e36abWhat we ruled out: Safe Browsing,
wp_safe_redirect, code TTL, missingissparameter, public client auth method mismatch, short alias redirects losing POST body, WP Engine WAF, stale client state, CORS on well-known endpoints, CORS onWWW-Authenticate, edge caching, path-specific well-known 404s, HTTP resource_metadata URL, missing MCP-Protocol-Version header allowance. We shipped 8 patch versions (v1.0.7 through v1.0.14) systematically eliminating server-side hypotheses. The server is not the problem.This connector was previously working. The regression appeared without changes on our server side.
Anthropic support ticket filed — conversation ID 215474060758866, same evidence included.
Still seeing Desktop-only failures with a custom OAuth 2.1 / Streamable HTTP MCP server (Memory Store, memory.store) as of May 2026. Same shape: works perfectly in Claude Code CLI (
claude mcp add --transport http ...) and on Claude.ai web; fails intermittently in Claude Desktop.Two recurring failure modes on Desktop:
tools/callthen fails withUnable to reach Memory Store.The key signal: during the failed
tools/call, zero traffic reaches our server — no auth attempt, no request, nothing in access logs. Theinitializeandtools/listhandshake at reconnect time does arrive normally. This points squarely at Desktop's client-side dispatch layer, not transport, OAuth, or our backend (which the CLI and web client exercise without issue against the same URL).Probably the same class as #22299 (closed COMPLETED, but our reproduction is on macOS not Windows and against an OAuth 2.1 / Streamable HTTP remote server, not a stdio filesystem server — the Feb fix may have only addressed the Windows/stdio path) and #23736 (closed COMPLETED, also Streamable HTTP, also Desktop-only).
Happy to provide Desktop logs, server-side request traces, or a test account if helpful.
Still occurring for Braintrust MCP
Issue is still occurring as of 5/28/26
New error reference: ofid_a41b6f8184f6d761
We traced the seven
ofid_reference IDs from this thread. They break into two distinct problems, and neither matches the original August 2025 report exactly.ofid_756e0939…,ofid_67d6f2f6…,ofid_3b8cd7ca…,ofid_a799fc9f…,ofid_27429fd4…,ofid_8dc382cb…(one reporter,stgfirstformat.wpenginepowered.com, Apr 24-25): the connector reached your server. Discovery and the authorize step succeeded; the failure is at your/tokenendpoint, which returned an error for the authorization code your server had just issued. Three of the six attempts also got a 401 on the pre-authorize probe. Our logs show two successful authentications against this server earlier on Apr 23, then 22 consecutive failures starting that evening, which points to a server-side configuration change around that time. Things to check on your side: your/tokenhandler's logs for these flows, whether the auth-code store or signing key rotated on Apr 23, and whether your WP staging environment was redeployed.ofid_a41b6f81…(Braintrust, May 28): the dynamic client registration response fromapi.braintrust.dev/oauth/registerreturnsclient_secret_expires_atas a floating-point number. RFC 7591 specifies this field as seconds since epoch, an integer, and our parser rejects non-integer values. Returning an integer there will unblock the flow.Original report (Aug 2025, Desktop opens a New Conversation page and the server is never contacted): there's no
ofid_reference for this one in the thread, so we can't trace it. If you can reproduce it now, the error card will show a reference ID; share that and we'll trace it.If you're seeing a connection failure that isn't one of the cases above, please open a new issue with your
ofid_reference rather than adding to this thread, so each report can be traced on its own. This repo tracks Claude Code (CLI) issues; for Claude Desktop or claude.ai MCP connector failures, file at anthropics/claude-ai-mcp instead.