{"slug": "mcp-connection-errors-explained-404-on-sse-406-not-acceptable-session-400s-402", "title": "MCP connection errors explained: 404 on /sse, 406 Not Acceptable, session 400s, 402", "summary": "A developer at Tanod documented the common failure modes of MCP Streamable HTTP connections, explaining that most errors stem from clients targeting the wrong URL or sending incorrect headers. The writeup maps each HTTP status — 404 on /sse, 406 Not Acceptable, session 400s, and 402 — to its cause and fix, and notes that Tanod's servers are stateless, requiring no session header and accepting tools/list as the first request.", "body_md": "MCP Streamable HTTP is one URL. The client POSTs JSON-RPC to it and may open a GET stream on the same URL; nothing else is part of the address. Most connection failures we see in our own server log are a client talking to a different address than the one it was given, or sending the wrong headers. Here is what each status means and the fix, with the exact messages the official TypeScript and Python SDKs send.\n\n`/sse`, or with `/mcp` appended\nThe earlier HTTP+SSE transport (protocol revision 2024-11-05) opened a GET to an SSE URL and read an `endpoint` event that named a second URL for POSTs. Streamable HTTP (2025-03-26 and later) replaced both with a single URL. A client that still speaks SSE-only, or a bridge that guesses, appends `/sse` and gets a 404 from any Streamable HTTP server. Some clients also append `/mcp` to a URL that already ends in the server path.\n\nFix: use the URL exactly as published. For a client that only speaks stdio, run a bridge such as `npx mcp-remote https://tanod.dev/mcp --transport http-only` so it does not fall back to SSE. For Tanod, every server is Streamable HTTP: `https://tanod.dev/mcp` and the focused servers such as `https://tanod.dev/mcp/docs`; `/mcp/docs/sse`, `/mcp/docs/mcp` and `/api/mcp` are all 404.\n\nA POST must carry `Accept: application/json, text/event-stream`, because the server may answer a request either with one JSON body or with an SSE stream. Both SDKs reject anything else with this message. A GET (the optional server-to-client stream) must accept `text/event-stream`. Curl and most HTTP libraries send `Accept: */*`, which some servers take and others do not; set the header explicitly.\n\nThe request body is JSON-RPC and must be sent as `Content-Type: application/json`. Form encoding, a missing header, or `text/plain` from a quick script all produce this.\n\nA stateful server expects an `initialize` request first. Its response carries an `Mcp-Session-Id` header, and the client must send that header on every later request. Calling `tools/list` before `initialize`, or dropping the header, gives one of these two 400s. After the server restarts, the old session is gone and the server answers `404 Session not found`: the client has to start a new session with a fresh `initialize`, which well-behaved clients do on their own.\n\nTanod's servers are stateless: no session header is needed, and `tools/list` works as the first request, so a shell check is one command:\n\n```\ncurl -s -X POST https://tanod.dev/mcp/docs \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Accept: application/json, text/event-stream\" \\\n  -d '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tools/list\"}'\n```\n\nThe specification lets a server decline the standalone GET stream. A client that opens it and gets 405 should carry on with POSTs; this is not a failure of the connection, and tool calls still work.\n\nA GET with `Accept: text/html` is a person, not an MCP client. Many servers, Tanod included, send that request to a human page (here, the [server overview](https://dev.to/mcp-servers/)). The MCP client, which POSTs, is unaffected.\n\nOn a pay-per-call server the price quote travels inside MCP: the tool result has `isError: true` and its `structuredContent` is an x402 `PaymentRequired` object (scheme, network, amount, pay-to address). An x402-aware client signs the payment and repeats the call with the payload in `params._meta[\"x402/payment\"]`; the receipt comes back in `_meta[\"x402/payment-response\"]`. A client without x402 support sees a tool error with the price in it, which is the intended reading. On Tanod the free daily allowance is spent before any quote is issued, and the plain HTTP routes return a classic `402` with the same object as JSON.\n\nLong tools (OCR of a large PDF, a full contract scan) can take tens of seconds, and clients ship with their own timeouts; Claude Code, for example, has an `MCP_TIMEOUT` setting in milliseconds. Tanod answers every call inside 90 seconds and returns a structured error rather than hanging, so a client timeout shorter than that is the thing to raise. If the server sends SSE progress notifications, the stream also keeps the connection alive through proxies.\n\n`Content-Type: application/json` and `Accept: application/json, text/event-stream`.` initialize` first, then echo `Mcp-Session-Id`; on 404 start over.` PaymentRequired` tool errors as price quotes.\nTanod's hosted MCP servers ([https://tanod.dev/mcp-servers/](https://tanod.dev/mcp-servers/)) are the worked example; the checks apply to any Streamable HTTP server. The guide version, kept current: [https://tanod.dev/learn/mcp-server-connection-errors.html](https://tanod.dev/learn/mcp-server-connection-errors.html)", "url": "https://wpnews.pro/news/mcp-connection-errors-explained-404-on-sse-406-not-acceptable-session-400s-402", "canonical_source": "https://dev.to/tanod/mcp-connection-errors-explained-404-on-sse-406-not-acceptable-session-400s-402-dik", "published_at": "2026-10-08 23:01:40+00:00", "updated_at": "2026-10-08 23:18:20.415335+00:00", "lang": "en", "topics": ["ai-agents", "agent-protocols", "developer-tools", "ai-tools"], "entities": ["Tanod", "MCP", "Claude Code", "x402"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/mcp-connection-errors-explained-404-on-sse-406-not-acceptable-session-400s-402", "markdown": "https://wpnews.pro/news/mcp-connection-errors-explained-404-on-sse-406-not-acceptable-session-400s-402.md", "text": "https://wpnews.pro/news/mcp-connection-errors-explained-404-on-sse-406-not-acceptable-session-400s-402.txt", "jsonld": "https://wpnews.pro/news/mcp-connection-errors-explained-404-on-sse-406-not-acceptable-session-400s-402.jsonld"}}