In September we did everything the guides tell you to do. We published a hosted MCP server, wrote a machine-readable discovery document, listed the endpoint in llms.txt, submitted to the directories and checked that the AI crawlers could reach all of it.
Then for three weeks we answered 1,041 connection attempts with an error, and had no idea.
What we published
Two different things live at two different addresses, and the distinction turns out to matter more than we thought.
The server is at mcp.chat.ethora.com/mcp. That is a real MCP endpoint speaking Streamable HTTP. An agent POSTs JSON-RPC to it, gets tools back, and does work.
The discovery document is at ethora.com/mcp. That is a small static JSON file describing the server: where it lives, how to authenticate, what the npm package is called, where the privacy policy is. It exists so that a crawler, a directory or an agent poking around our marketing site can find out that an MCP server exists and where to go next.
That felt tidy when we designed it. One address to read about the server, one address to use it.
What actually happened
We pulled eleven days of origin logs, 138,651 requests, mostly to check something unrelated. One line in the breakdown stopped us:
/mcp GET -> 200 (4,252)
/mcp POST -> 405 (1,041)
/mcp DELETE -> 405 (3)
POST and DELETE are not browser verbs. Nothing on a marketing site legitimately POSTs to a JSON file. But they are exactly the verbs the MCP Streamable HTTP transport uses: POST carries the JSON-RPC payload, DELETE terminates a session.
So those were not scanners. Those were MCP clients. They had found ethora.com/mcp, decided it was the server, tried to open a session, and been told 405 Method Not Allowed with no explanation at all.
About 130 of them a day. Every day. From precisely the audience the whole exercise was built to attract.
The user agents made it worse reading. Agent frameworks with browser-style strings, Lightpanda (a headless browser built for agents), python-httpx, node, curl, and one calling itself agent-evidence-scanner. These were not people idly clicking. These were automated systems trying to integrate with us and silently failing.
Why it happened
In hindsight it is obvious, which is the most annoying kind of bug.
An agent that learns an MCP server exists at a company does not always receive a carefully structured handoff. It often has one string: a URL ending in /mcp. And the overwhelmingly common convention is that a URL ending in /mcp is the endpoint. So it POSTs to it.
We had published a document at the exact path shape that, by convention, means "server here". We were technically correct and practically wrong. The convention beat our architecture diagram.
Nobody complained, because there is no one to complain. An agent that gets a 405 does not open a support ticket. It moves on, and you never learn it was there.
The fix is three lines
We did not have to choose between the document and the endpoint. HTTP already has the right tool.
@mcp_connect {
path /mcp /mcp/ /.well-known/mcp /.well-known/mcp/
method POST DELETE
}
redir @mcp_connect https://mcp.chat.ethora.com/mcp 308
GET and HEAD still serve the discovery JSON, so every crawler and directory that reads it is unaffected. POST and DELETE now redirect to the real server.
The status code is the part worth dwelling on. 308 preserves the method and the body. A 301 or 302 would let the client turn the POST into a GET and drop the JSON-RPC payload, which would fail just as surely as the 405 but more confusingly. 307 and 308 are the two that keep the request intact, and 308 says the move is permanent.
Tested from outside, as a client would:
POST https://ethora.com/mcp (initialize)
-> 308, one redirect, method and body preserved
-> 200 {"serverInfo":{"name":"Ethora MCP Server","version":"26.10.0"}}
The call that had failed 1,041 times now completes.
The part we nearly got wrong
Our server uses OAuth, and the MCP spec handles that through protected resource metadata: an unauthenticated call returns 401 with a WWW-Authenticate header pointing at a document that names the authorization server. The resource identifier in that document is the real host, not the marketing domain.
So before shipping, we checked whether a client that arrived by redirect still got a valid challenge, rather than assuming it. It does:
401 www-authenticate: Bearer realm="ethora",
resource_metadata="https://mcp.chat.ethora.com/.well-known/oauth-protected-resource/mcp/oauth"
Worth testing on your own setup if you redirect. A redirect that lands a client somewhere it cannot then authenticate is a worse failure than the one you started with, because it fails later and less obviously.
The general lesson
If you run an MCP server, go and look at what non-GET methods are hitting the paths around it. Specifically:
- Any path ending in
/mcpthat is not your endpoint. If anything POSTs there, agents think it is. /.well-known/mcp, if you serve one. We got POSTs there too.- Any subdomain that looks like it should be the server. We found
mcp.ethora.comresolving through a wildcard DNS record to an origin that did not answer, so it hung for twelve seconds and returned a Cloudflare 522. It is the most guessable hostname we own for this purpose, and it was broken. That got a 308 as well.
The wider point is that agent traffic fails silently. A human who cannot reach your signup page emails you, tweets about it, or shows up in a session recording rage-clicking. An agent returns an error to its own model, the model tells its user it could not connect, and that conversation happens somewhere you will never see.
Your server logs are the only place that failure is visible. For agent-facing infrastructure, reading them is not an ops chore. It is the entire feedback channel.
A number that surprised us
Once we started counting properly, /mcp turned out to be the single most-requested real page on our marketing site over those eleven days. More than the homepage.
We spent years optimising a homepage for humans. The best-trafficked thing we serve is now a 600-byte JSON file written for machines, and until last week a meaningful share of the machines reading it bounced straight off an error.
That is roughly where the whole industry is right now. The front door has moved and the signage has not caught up.