Skip to main content
RapidDev - Software Development Agency
mcp-tutorial

MCP transports compared: stdio vs SSE vs streamable HTTP

MCP supports three transport protocols: stdio for local subprocess communication, SSE (Server-Sent Events) for legacy HTTP streaming, and Streamable HTTP as the newest stateless-friendly standard. Stdio is best for local tools and IDE integrations, while Streamable HTTP is the recommended choice for remote deployments with its single-endpoint design and OAuth 2.1 support.

What you'll learn

  • The differences between stdio, SSE, and Streamable HTTP transports
  • When to use each transport type for your MCP server
  • How to configure each transport in Claude Desktop and Cursor
  • Migration path from SSE to Streamable HTTP
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate7 min read15-20 minMCP SDK 1.0+, all MCP hostsMarch 2026RapidDev Engineering Team
TL;DR

MCP supports three transport protocols: stdio for local subprocess communication, SSE (Server-Sent Events) for legacy HTTP streaming, and Streamable HTTP as the newest stateless-friendly standard. Stdio is best for local tools and IDE integrations, while Streamable HTTP is the recommended choice for remote deployments with its single-endpoint design and OAuth 2.1 support.

Understanding MCP Transport Protocols

The Model Context Protocol supports three transport mechanisms for communication between hosts (like Claude Desktop or Cursor) and MCP servers. Choosing the right transport determines how your server communicates, where it can run, and what authentication options are available. This tutorial breaks down each transport so you can make the right choice for your use case.

Prerequisites

  • Basic understanding of MCP architecture (hosts, clients, servers)
  • Node.js 18+ or Python 3.10+ installed
  • An MCP host such as Claude Desktop or Cursor installed
  • Familiarity with JSON configuration files

Step-by-step guide

1

Understand stdio transport fundamentals

Stdio (standard input/output) is the simplest and most widely supported MCP transport. The host spawns your MCP server as a child process and communicates via stdin and stdout pipes. No network is involved — everything runs locally. This makes stdio the default choice for local tools, file system access, and IDE integrations. Every MCP host supports stdio, making it the most compatible option. The downside is that the server must run on the same machine as the host.

typescript
1// claude_desktop_config.json — stdio transport example
2{
3 "mcpServers": {
4 "my-local-server": {
5 "command": "node",
6 "args": ["./dist/index.js"],
7 "env": {
8 "API_KEY": "your-key-here"
9 }
10 }
11 }
12}

Expected result: You understand that stdio uses subprocess communication via stdin/stdout with no network overhead.

2

Review SSE transport and its deprecation status

Server-Sent Events (SSE) was the first HTTP-based MCP transport. It uses two HTTP endpoints: one for the client to send messages (POST) and one for the server to stream responses (GET with SSE). While functional, SSE has limitations: it requires two connections, does not support resumability natively, and is being deprecated in favor of Streamable HTTP. If you have existing SSE servers, they will continue to work, but new projects should use Streamable HTTP instead.

typescript
1// SSE transport server setup (legacy — avoid for new projects)
2import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
4import express from "express";
5
6const app = express();
7const server = new McpServer({ name: "sse-server", version: "1.0.0" });
8
9app.get("/sse", async (req, res) => {
10 const transport = new SSEServerTransport("/messages", res);
11 await server.connect(transport);
12});
13
14app.post("/messages", async (req, res) => {
15 // Handle incoming messages
16});
17
18app.listen(3001);

Expected result: You understand that SSE is a legacy transport being replaced by Streamable HTTP.

3

Set up Streamable HTTP transport for remote servers

Streamable HTTP is the newest and recommended transport for remote MCP servers. It uses a single HTTP endpoint that supports both request-response and streaming patterns. Key advantages include stateless-friendly design (works behind load balancers), built-in session management via the Mcp-Session-Id header, and OAuth 2.1 authentication support. This is the transport to use when deploying MCP servers to cloud platforms like Vercel, Railway, or Render.

typescript
1// Streamable HTTP transport with Express
2import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3import { createMcpExpressApp } from "@modelcontextprotocol/sdk/server/express.js";
4
5const server = new McpServer({
6 name: "remote-server",
7 version: "1.0.0"
8});
9
10server.tool("hello", "Say hello", {}, async () => ({
11 content: [{ type: "text", text: "Hello from Streamable HTTP!" }]
12}));
13
14const app = createMcpExpressApp(server);
15app.listen(3000, () => {
16 console.error("MCP server running on http://localhost:3000");
17});

Expected result: A running MCP server accessible via a single HTTP endpoint that supports both streaming and request-response patterns.

4

Compare transports side by side

Here is a decision matrix to help you choose. Use stdio when your server runs locally and accesses local files, databases, or system tools. Use Streamable HTTP when your server needs to be accessed remotely, shared across teams, or deployed to the cloud. Avoid SSE for new projects — it is being deprecated. Stdio has zero latency overhead but is local-only. Streamable HTTP adds network latency but enables remote access, authentication, and horizontal scaling.

Expected result: You can confidently choose the right transport for any MCP server project.

5

Configure your MCP host to connect via each transport

Claude Desktop and Cursor configure transports differently. For stdio, you specify a command and args in the config. For Streamable HTTP, you provide a URL. Claude Desktop stores its config at ~/Library/Application Support/Claude/claude_desktop_config.json on macOS. Cursor uses .cursor/mcp.json in your project root or ~/.cursor/mcp.json globally. If your project involves complex multi-transport setups or you need help choosing the right architecture, the RapidDev team can help you design the optimal configuration.

typescript
1// Claude Desktop — stdio transport
2{
3 "mcpServers": {
4 "local-tools": {
5 "command": "node",
6 "args": ["./my-server/dist/index.js"]
7 }
8 }
9}
10
11// Cursor — Streamable HTTP transport (.cursor/mcp.json)
12{
13 "mcpServers": {
14 "remote-api": {
15 "url": "https://my-mcp-server.railway.app/mcp"
16 }
17 }
18}

Expected result: Your MCP host connects to servers using the appropriate transport configuration.

Complete working example

streamable-http-server.ts
1import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2import { createMcpExpressApp } from "@modelcontextprotocol/sdk/server/express.js";
3import { z } from "zod";
4
5// Create the MCP server
6const server = new McpServer({
7 name: "demo-transport-server",
8 version: "1.0.0",
9});
10
11// Register a simple tool
12server.tool(
13 "greet",
14 "Greet a user by name",
15 { name: z.string().describe("The name to greet") },
16 async ({ name }) => ({
17 content: [{ type: "text", text: `Hello, ${name}! Welcome to MCP.` }],
18 })
19);
20
21// Register a resource
22server.resource(
23 "server-info",
24 "info://server",
25 { description: "Server metadata" },
26 async () => ({
27 contents: [
28 {
29 uri: "info://server",
30 text: JSON.stringify({
31 transport: "Streamable HTTP",
32 version: "1.0.0",
33 capabilities: ["tools", "resources"],
34 }),
35 },
36 ],
37 })
38);
39
40// Create Express app with Streamable HTTP transport
41const app = createMcpExpressApp(server);
42
43const PORT = parseInt(process.env.PORT || "3000", 10);
44app.listen(PORT, () => {
45 console.error(`MCP server listening on port ${PORT}`);
46 console.error(`Transport: Streamable HTTP`);
47 console.error(`Endpoint: http://localhost:${PORT}/mcp`);
48});

Common mistakes

Why it's a problem: Using console.log() instead of console.error() for logging

How to avoid: Always use console.error() for logging in MCP servers. Stdout is reserved for protocol messages in stdio transport, and using console.log() will corrupt the JSON-RPC stream.

Why it's a problem: Choosing SSE for a new project

How to avoid: Use Streamable HTTP instead — SSE is being deprecated and Streamable HTTP offers better features including single-endpoint design and session management.

Why it's a problem: Deploying a stdio server to the cloud

How to avoid: Stdio requires a local subprocess — it cannot work over the network. Switch to Streamable HTTP transport for remote deployments.

Why it's a problem: Forgetting to set the Mcp-Session-Id header for stateful Streamable HTTP sessions

How to avoid: The SDK handles session management automatically. If building a custom client, capture the Mcp-Session-Id from the server response and include it in subsequent requests.

Best practices

  • Default to stdio for local MCP servers — it has zero configuration overhead and maximum compatibility
  • Use Streamable HTTP for any server that needs to be accessed remotely or shared across a team
  • Always log to stderr, regardless of transport type, to prevent protocol corruption
  • Set environment variables in the host config rather than hardcoding them in server code
  • Test your server with MCP Inspector before connecting it to a host application
  • Pin your @modelcontextprotocol/sdk version to avoid breaking changes across transport APIs
  • Include health check endpoints in HTTP-based servers for monitoring and load balancer compatibility

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

I am building an MCP server in TypeScript. Compare stdio, SSE, and Streamable HTTP transports. Which should I use for [local IDE tool / remote team API / cloud deployment]? Show me the server setup code and the host configuration for Claude Desktop.

MCP Prompt

Create an MCP server using Streamable HTTP transport with Express. Include a tool called [tool-name] that [description]. Show me the complete server code and the .cursor/mcp.json configuration to connect to it.

Frequently asked questions

Can I use both stdio and Streamable HTTP in the same MCP server?

Yes, but you need to run two separate instances of your server — one configured for each transport. A single server process can only use one transport at a time. You could also build your server as a library and wrap it with different transport layers.

Is SSE transport still supported in Claude Desktop?

Yes, Claude Desktop still supports SSE transport for backward compatibility. However, new servers should use Streamable HTTP, which is the recommended replacement. SSE support may be removed in a future update.

Does stdio work on Windows?

Yes, but you may need to wrap npx commands with cmd. Use {"command": "cmd", "args": ["/c", "npx", "-y", "your-server"]} in your host configuration on Windows.

What authentication does Streamable HTTP support?

Streamable HTTP supports OAuth 2.1 for authentication. The MCP specification defines a standard auth flow where the client obtains tokens from the server's authorization endpoint. Stdio transport does not need authentication since it runs locally.

Which transport has the lowest latency?

Stdio has the lowest latency because it communicates via in-process pipes with no network overhead. Streamable HTTP adds network round-trip time, which is typically 1-50ms for local servers and 50-500ms for remote servers depending on geographic distance.

Can Cursor connect to remote MCP servers?

Yes, Cursor supports Streamable HTTP transport. Add a url field to your server configuration in .cursor/mcp.json pointing to your remote server endpoint, for example https://your-server.railway.app/mcp.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.