Claude cannot reach your MCP server, but curl can
By Nihar Ranjan Das · Sat Aug 22 2026 · 6 min read · 0 views
View as a Web StorySoftware#mcp#debugging#claude#connectors#oauth#dns

Claude shows one error for a lot of different problems: Couldn't reach the MCP server. Your server is up. You can curl it. MCP Inspector connects. Claude still refuses.
Three of the four documented causes are invisible from your own laptop. That is the whole trap. Your machine and Anthropic's servers do not see the same internet, so the test that matters is the one you run from outside your network.
Cause 1: your hostname resolves to a private address
Claude checks DNS before it sends a single HTTP request. A custom connector is a remote MCP server that Claude reaches from Anthropic's own infrastructure, not from your computer. If any address in the DNS answer is not globally routable, the request never leaves that infrastructure.
The connector troubleshooting guide from Anthropic lists what gets rejected: private ranges 10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16, carrier-grade NAT space 100.64.0.0/10, and loopback or link-local addresses. A mix counts as a failure too. Every address returned must be public.
Split-horizon DNS is a setup where the same name resolves differently inside and outside a network, and it is the first of three common traps. It gives one answer in your office and another on the public internet. Dynamic DNS hostnames often point at a home line behind carrier NAT. Internal corporate names resolve only on the VPN.
Run this from a network that is not yours:
dig +short your-server.example.com
If it returns nothing, or returns a 10.x address, Claude sees the same thing. Fix it with a public host, a public reverse proxy, or a tunnel. Anthropic's connector testing guide recommends cloudflared tunnel --url http://localhost:3000 or ngrok http 3000 for local work.
Cause 2: your server is IPv6-only
Connectors are IPv4-only. A hostname that publishes AAAA records and no A record cannot be reached, even though the server is healthy and public.
This is easy to miss in 2026. Several hosting stacks now hand out IPv6 by default and add IPv4 as a paid or optional extra. The server answers your test because your client speaks IPv6. Anthropic's side needs an A record.
The check is one flag away:
Advertisement
dig +short A your-server.example.com
dig +short AAAA your-server.example.com
An empty first line and a populated second line is the bug. Add an IPv4 address, or front the server with something that has one.
Cause 3: a redirect quietly drops your token
If your MCP URL answers with a 301, 302, 307 or 308 to a different host, the Authorization header is removed on the way. That is standard HTTP client behavior, described in RFC 9110 section 15.4, not a Claude quirk. The redirect target then gets an unauthenticated request, answers 401, and Claude reports that authorization failed.
This explains the most common complaint in the tracker: it works in MCP Inspector or Claude Code, but not on claude.ai. Local clients tend to stop at the redirect, so you see the misconfiguration straight away. Claude on the web follows it, loses the credential, and fails later and less clearly.
The usual culprits are apex-to-www canonicalization, regional routing, and a vanity domain pointing at a CDN. One command finds it:
curl -sI https://your-server.example.com/mcp
If the status is 3xx and the Location header names another host, register that target URL in Claude instead of the one you tried.
Cause 4: a WAF blocks Anthropic before your app sees it
A WAF is a web application firewall that filters traffic before it reaches your app. A WAF, CDN, bot rule or rate limiter in front of your server can reject the request before your application logs anything. You will see 403 or 429 in your edge logs and nothing at all in your app logs.
Anthropic's outbound traffic comes from 160.79.104.0/21, listed in the Claude IP address reference. Allowlist that range, or exempt your MCP and OAuth paths from the rule.
One detail catches teams with a separate identity provider. Claude does OAuth discovery from the same egress range, so a WAF in front of your sign-in host breaks the flow even when the MCP endpoint itself is open.
The five-minute checklist
Work in this order. Each step rules out one cause, and the whole run takes about five minutes.
- From outside your network, confirm
dig +short your-server.example.comreturns a public IPv4 address. - Confirm
curl -i https://your-server.example.com/mcpreturns something. A401or405is fine; a timeout is not. - Confirm the same URL does not answer with a
3xxto another host. - Check edge logs for
403or429during the connect attempt. - Confirm
/.well-known/oauth-protected-resourcereturns200with valid JSON.
| Symptom | Likely cause | The check |
|---|---|---|
| Server logs show nothing at all | Private or IPv6-only DNS answer | dig from outside |
Edge logs show 403 or 429 |
WAF or bot rule | Allowlist 160.79.104.0/21 |
| Works in Claude Code, fails on claude.ai | Cross-host redirect | curl -sI for a 3xx |
| OAuth server sees no traffic | Discovery failure | The .well-known probes |
When discovery is the real problem
If your server needs sign-in, Claude runs OAuth discovery before it connects. A discovery failure also surfaces as "Couldn't reach", even though the MCP endpoint is fine.
The reliable fix is to stop relying on well-known probing. Return a 401 with a pointer to your metadata:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://mcp.example.com/.well-known/oauth-protected-resource"
Protected resource metadata is a small JSON document, defined in RFC 9728, that names the OAuth server behind your MCP endpoint. The MCP authorization spec defines this handshake, and Claude does not honour a WWW-Authenticate header on a 200 response, so the status has to be 401. The lazy authentication guide shows the exact header and a working handler.
That pointer matters most on platforms that cannot serve /.well-known/* at the root, such as Supabase Edge Functions, Cloudflare Workers without a matching route, and Lambda function URLs with a path prefix. The metadata URL can live anywhere on HTTPS. Two more rules apply: the resource field must match your MCP URL exactly as users type it, and Claude uses only the first entry in authorization_servers.
Before you file a bug
Reproduce the failure and copy the reference ID. Every failed connection puts an ofid_ value in the error toast and in the page URL, for example flow_id=ofid_d32594c73257a651. That ID lets Anthropic trace the exact failure server-side, and it expires, so report it soon.
File it on the claude-ai-mcp issue tracker with three things: the ofid_ value, your server URL, and what your access logs show during the attempt. If the logs are empty, say so. That is evidence, not a gap, and it points straight at cause 1 or cause 4. For failures that happen after sign-in starts, our guide to when Claude cannot register with your OAuth server covers the registration side.
Advertisement
FAQ
Why does Claude say it can't reach my MCP server when curl works?
Your curl runs from your network. Claude connects from Anthropic's infrastructure. The usual gaps are split-horizon DNS, an IPv6-only hostname, a redirect to another host, or a WAF rule that blocks the request before your application sees it.
Can Claude connect to an MCP server on localhost?
No. Claude reaches custom connectors over the public internet, so loopback and private addresses are rejected before any request is sent. Expose the server through a tunnel such as ngrok or Cloudflare Tunnel and register the public HTTPS URL.
Which IP range should I allowlist for Claude connectors?
Allowlist `160.79.104.0/21`. That range covers requests to your MCP endpoint and the OAuth discovery requests, so apply it to your identity provider's host as well if it sits behind a different CDN.
Does Claude follow redirects for MCP server URLs?
Claude on the web follows them, but the `Authorization` header is dropped when the redirect points at a different host. Register the final URL your server listens on rather than an apex or vanity domain that redirects to it.
What is the ofid reference ID in the Claude connector error?
It is a trace identifier that appears in the failure toast and the page URL. Include it in any GitHub issue or support contact so Anthropic can look up the exact failure. The IDs are time-limited, so file the report soon after the failure.
Comments
Loading…
Sign in to join the conversation.
Related posts

Should your Claude connector draw its own UI?
A connector used to be text in, text out. Now it can draw. An MCP App is an MCP server that ships its own interface, and Claude renders it inline in the conversation.
Sat Aug 22 2026 · 5 min read · 0 views

Your MCP connector spends context before you type
The advice you have read about MCP context cost is out of date. The old rule was simple. Every tool you connect gets injected up front, so a big connector spends a chunk of the window before you type
Sat Aug 22 2026 · 6 min read · 0 views

What gets a Claude connector rejected from the directory
Most guides to the Claude Connectors Directory explain how to submit. This one covers what fails. The triggers are published, exact, and easy to hit by accident. The most common one is a design choice
Sat Aug 22 2026 · 6 min read · 0 views