n8n MCP Authorization Failure with Claude.ai - Self-hosted Elestio 2.26.4

We’re running n8n 2.26.4 self-hosted on Elestio and are unable to connect Claude.ai to our instance via MCP. Instance-level MCP is enabled and the OAuth/Access token is configured.

We’ve tried both the official n8n partner connector on Claude.ai and a custom connector using the direct MCP server URL (format: https://your-instance.vm.elestio.app/mcp-server/http). Both fail with the same error on the Claude side:

“Authorization with the MCP server failed. You can check your credentials and permissions.”

Interestingly, on the n8n side the Connected Clients tab does show new Claude entries appearing each time we attempt to connect, so n8n is receiving the connection attempt. The auth handshake just isn’t completing successfully on Claude’s end.

Reference codes from the three failed attempts:

  • ofid_ccb9a1fd230c7285
  • ofid_757ab36960e137e7
  • ofid_a02cf908ec28723f

Can anyone help us identify what’s blocking the authorization from completing?

1 Like

Those Connected Clients rows are useful: Claude is reaching n8n, so the next split is URL discovery vs token exchange. Try one clean reconnect with the direct MCP URL, then check the n8n log for that same ofid_...; if it fails during token exchange, paste that one log line with hostnames/secrets redacted and the OAuth credential type you used.

1 Like

Update: We’ve dug deeper into the logs and found the root cause.

Every connection attempt shows:

ValidationError: An invalid 'request.ip' was detected

followed immediately by “Deleting OAuth client” and “OAuth client deleted successfully”. The OAuth session is being created and then immediately torn down because n8n’s rate limiter is rejecting the malformed IP coming from the nginx reverse proxy in front of our instance.

We’ve set N8N_TRUST_PROXY=true and N8N_PROXY_HOPS=1 but the issue is at the nginx layer. Nginx is forwarding X-Forwarded-For headers but is missing real_ip_header and set_real_ip_from directives, so n8n receives a malformed IP and kills the OAuth session before the token exchange can complete.

We’ve escalated to Elestio (our hosting provider) to add the nginx real_ip directives. Is there anything on the n8n side we can do to bypass or disable the rate limiter IP validation as a workaround while we wait?

One thing worth trying while you wait on Elestio: set N8N_PROXY_HOPS=0 temporarily. This tells n8n it’s not behind any proxy, so it stops trying to parse X-Forwarded-For headers entirely and uses the raw connection IP instead - which gets around the malformed IP validation that’s killing the OAuth handshake. The trade-off is that rate limiting will apply to the proxy’s IP rather than real client IPs, but for an MCP server that’s generally fine. Once Elestio applies the real_ip_header and set_real_ip_from nginx directives, switch back to N8N_PROXY_HOPS=1 so rate limiting works correctly again.

1 Like

Meesam, treat the N8N_PROXY_HOPS=0 idea above as a temporary isolation test, not the fix. It makes n8n rate-limit against the proxy IP, so keep it short-lived and switch back once Elestio sets the real-IP chain.

Do not disable the limiter itself in n8n for this. The durable fix is still upstream: nginx needs to pass a valid trusted client IP chain before the OAuth/rate-limit path behaves normally.

1 Like

Update: Progress made. The OAuth deletion loop is fixed. Logs now show “Consent approved” and “Refresh token rotated and new access token issued” on every attempt, so the OAuth flow is completing successfully on the n8n side. However Claude.ai still shows “Authorization with the MCP server failed”. The failure is now happening after OAuth completes, during the MCP session initialization. Any idea what could cause the MCP session to fail after a successful OAuth handshake?

Meesam, if n8n now shows consent approved and token rotation, stop looking at the proxy/IP path for this part. The next check is whether Claude is reaching the MCP endpoint after OAuth: in that same attempt, do the n8n logs show a request to /mcp-server/http after the token line, or does it go quiet?

If it goes quiet, the connector is likely failing before session init reaches n8n. If a request lands, paste the first MCP-session error line with hostnames/tokens redacted; the status code there matters more than the OAuth lines now.

Checked the logs immediately after a connection attempt. After “Consent approved” and token rotation, the logs go completely quiet. No requests to /mcp-server/http appear at all. So Claude is completing OAuth successfully but never reaching the MCP session init endpoint. What would cause Claude.ai to stop before hitting /mcp-server/http after a successful token exchange?

That narrows it a lot: if n8n goes quiet after token rotation, the failed step is probably no longer n8n accepting the OAuth result. Claude is getting past that, then not starting the MCP session request.

The next clue is the client-side MCP URL Claude saved. Is it exactly the public https://.../mcp-server/http URL, with no trailing slash/path rewrite from Elestio? If that URL is exact and n8n still sees nothing after token rotation, this is likely on the Claude remote-MCP client side rather than an n8n workflow setting.

Hey @Meesam_Raza

Instead of

why not just use this?

It’s simpler

1 Like

Tried the API key approach by embedding it in the URL as a query parameter. Still getting “Authorization with the MCP server failed” on Claude’s side.

The query parameter approach won’t work - Claude.ai’s MCP client sends the token as Authorization: Bearer <key> in the request header, not as a URL param. The issue is almost certainly that Elestio’s nginx is stripping the Authorization header before it reaches n8n.

In your Elestio nginx config, make sure this is present in the location block handling MCP:

proxy_set_header Authorization $http_authorization;

Without this, nginx passes through cookies and custom headers but drops the Authorization header by default, so n8n’s MCP server never sees the token and rejects the connection. Once that header passthrough is in place, use the n8n API key directly in the Claude connector - no URL embedding needed.

1 Like

Update: Tested the MCP endpoint directly with curl. The endpoint advertises Bearer auth via WWW-Authenticate: Bearer realm="n8n MCP Server" but returns "Missing Bearer prefix" even when sending a valid Authorization: Bearer <token> header. The token is reaching n8n (confirmed nginx passes Authorization headers through). Using both the MCP Access token and the n8n API key both return HTTP 401. Is there a specific token format or endpoint the MCP server expects for direct Bearer auth in 2.26.4?

Resolved - here’s what actually fixed it for anyone on Elestio:

The root cause was the Elestio nginx configuration missing specific MCP-related proxy directives. Even though nginx was passing Authorization headers for other routes, the location block handling the n8n MCP endpoint (/mcp-server/http) was not properly configured to pass through the headers and handle the MCP session initialization.

The fix was Elestio updating the nginx config for the n8n service with the correct proxy directives for the MCP endpoint. We didn’t get the exact lines they changed but the symptom was:

  • OAuth completed successfully (consent approved, tokens issued in n8n logs)
  • Claude never hit /mcp-server/http after token exchange, logs went quiet
  • Direct curl to /mcp-server/http with a Bearer token returned 401 with the contradictory error “Missing Bearer prefix” even when Bearer prefix was present
  • After Elestio updated the nginx MCP config, the connection worked immediately

Other things we fixed along the way that weren’t the root cause but were real issues:

  • n8n was on 1.121.3, upgraded to 2.26.4 (required for stable MCP support)
  • Added N8N_TRUST_PROXY: "true" to docker-compose.yml (good practice behind a reverse proxy)
  • The N8N_PROXY_HOPS=1 was already set correctly, don’t change this

If you’re on Elestio and hitting the same wall, open a support ticket and ask them to update the nginx MCP config for your n8n service. They fixed it quickly once we gave them the specific error.

1 Like