new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

MCP Server Development in Practice · all subjects

Transports and deployment

5 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

stdio, SSE, or streamable HTTP — which transport should I build on in 2026?

As of early 2026: streamable HTTP is the current remote transport, introduced in spec 2025-03-26 and hardened in 2025-06-18. It is a single endpoint accepting POST (JSON-RPC requests, optionally answered over an SSE stream) and GET (a server-pushed stream). The older 'HTTP+SSE' transport from 2024-11-05 — separate /sse and /messages endpoints — is deprecated; only support it if you must serve year-old clients. stdio remains the right choice for local servers a client launches as a subprocess (desktop extensions, CLI-installed tools): zero network surface, auth inherited from the environment. Rule of thumb: local and single-user → stdio; hosted, multi-user, or behind a URL → streamable HTTP.

Should my MCP server be stateless or stateful?

Prefer stateless unless you have a real reason not to. In streamable HTTP a stateful server issues an Mcp-Session-Id at initialize and expects it back on every request; that id pins the client to one process, which breaks naive horizontal scaling and serverless deployments where the next POST lands on a different instance. A stateless tools-only server — initialize, tools/list, tools/call, ping — needs no session id at all: treat each call as self-contained, carry auth in the bearer token, and return 200/202 per request. That is exactly what a production Next.js route handler can serve with no session store. If you genuinely need sessions (progress notifications, subscriptions), store session state in Redis or Postgres, never in process memory.

My client sends Mcp-Session-Id and MCP-Protocol-Version headers — do I need them?

MCP-Protocol-Version: since spec 2025-06-18, clients send this header on every request after initialize, carrying the negotiated version. A lenient server can ignore it, but a strict one should validate it and answer 400 on a version it cannot speak — silently assuming the version is how subtle incompatibilities ship. Mcp-Session-Id: only required if YOU issued one during initialize. If you never return a session id, a well-behaved client will not send one; if it does, ignoring it is fine for stateless operation. Where you do issue ids: return 404 for an unknown/expired session id so the client re-initializes, per the spec — do not invent a new session silently.

Why does the MCP SDK not fit my Next.js / edge route handler?

The official TypeScript SDK's StreamableHTTPServerTransport was written against Node's IncomingMessage/ServerResponse. Frameworks that hand you a Web Request/Response (Next.js App Router, Cloudflare Workers, Deno) need an adapter that shims both directions, and that shim is more moving parts than the protocol itself for a small tool surface. Hand-rolling is legitimate: the wire format is plain JSON-RPC 2.0 — a switch over method names handling initialize, notifications/initialized (return 202, no body), ping, tools/list, tools/call. Production servers do exactly this and gain full control over auth, batching, and metering. Reach for the SDK once you need SSE streaming, sessions, or client-side features — not for a request/response tools endpoint.

How do I protect a localhost MCP server from DNS rebinding?

A stdio server is safe by construction; an HTTP server listening on localhost is not. A malicious web page can make the victim's browser POST to http://localhost:PORT or rebind its domain's DNS to 127.0.0.1 and talk to your MCP server with the user's ambient privileges. The spec (2025-06-18, security section) requires servers bound to localhost to validate the Origin header on every request and reject anything that is not from the local client; also validate the Host header so rebinding to an attacker domain fails. Browsers send Origin on POST, MCP clients do not — so 'reject if Origin is present and not expected' plus 'only listen on 127.0.0.1, never 0.0.0.0' is the practical policy.

Give your agent this brain