MCP Forge

MCP transports: stdio vs streamable HTTP (and why to drop SSE)

A practical guide. Updated 2026.

An MCP server speaks the same JSON-RPC protocol no matter how it ships, but the transport you pick decides where the server runs, who can reach it, and how much of your attack surface is exposed to the network. There are two transports worth using in 2026: stdio and streamable HTTP. A third, the old HTTP+SSE transport, is deprecated and should not be in new code. Here is how to choose, and what each choice means for security.

stdio: the local subprocess

With stdio, the client (Claude Desktop, Cursor, the Claude CLI) launches your server as a child process and talks to it over standard input and standard output. Each JSON-RPC message is one line on the pipe. There is no port, no socket, and no network listener. The server lives and dies with the client session.

A stdio entry in a client config looks like this:

{
  "mcpServers": {
    "files": {
      "command": "node",
      "args": ["/abs/path/to/server.js"],
      "env": { "ROOT_DIR": "/Users/me/projects" }
    }
  }
}

Use stdio when:

The security model is the process boundary, not a login. There is no auth handshake because the client already trusts the binary it spawned. That puts the weight on two things: the secrets you hand the process through env, and what the tools are actually allowed to do. A stdio server that shells out to command built from tool input is still a command-injection bug, transport notwithstanding. Local does not mean safe.

Streamable HTTP: the remote server

Streamable HTTP is the current spec transport for servers that run somewhere else and are reached over the network. The client sends JSON-RPC requests by POST to a single endpoint (commonly /mcp). The server replies with a plain JSON response for simple calls, or upgrades to a Server-Sent Events stream on the same connection when it needs to push progress, logs, or multiple messages back. One endpoint, two response shapes, decided per request by the Accept header.

A minimal remote config points at a URL instead of a command:

{
  "mcpServers": {
    "search": {
      "url": "https://mcp.example.com/mcp",
      "headers": { "Authorization": "Bearer ${SEARCH_TOKEN}" }
    }
  }
}

Use streamable HTTP when:

The moment you bind a port, the threat model changes completely. The server is now reachable by anything that can route to it, so every request is potentially hostile. That means you own a real authentication story (the spec points at OAuth 2.1 for user-facing servers; a vetted bearer token is the floor), TLS so tokens are not sent in cleartext, and an Origin check plus binding to 127.0.0.1 if it is only meant to be local-but-HTTP. Skipping the Origin check is how DNS-rebinding attacks turn a "local" HTTP server into one a malicious web page can drive.

Because a remote MCP server is a normal web service, it inherits normal web bugs. A tool that fetches a URL needs SSRF protection, and any HTTP-exposed server should have rate limiting and input validation in front of it. If you are running one already, mcp-audit (github.com/alih552/mcp-audit) scans your client config and flags remote servers with no auth, cleartext http:// URLs, and similar issues, locally and with zero dependencies.

Why not SSE

The original remote transport used two endpoints: a long-lived GET /sse stream for server-to-client messages and a separate POST for client-to-server. It was deprecated in the 2025-03-26 spec revision and replaced by streamable HTTP. Avoid it in anything new for concrete reasons:

If you have an old /sse server, the migration is mechanical: collapse to a single POST /mcp endpoint and let the server choose between a JSON response and an SSE upgrade per request. Most SDKs ship a streamable-HTTP server helper that does this for you.

How to choose, quickly

The transport is not where most MCP bugs live, but it sets the rules. stdio keeps you off the network and puts the burden on tool behavior and secret handling. HTTP opens the door to the whole internet and demands that you defend it like any other public service.

Ship a hardened HTTP MCP server, not a starter snippet

MCP Forge Kit gives you a streamable-HTTP server with auth, TLS-ready config, Origin checks, rate limiting, SSRF-safe fetch, validation, tests, and CI already wired up.

Get MCP Forge Kit, €39

Related: Authentication · Deploy securely · Security checklist