Skip to main content
Glama
Sonichigo

github-repo-stats

by Sonichigo
README.md
# mcp-transport-talk

Code companion for my MCP Dev Summit Bengaluru 2026 talk:
**"From SSE to Streamable HTTP: What Actually Changed in MCP's Transport Layer and Why Your Servers Need to Catch Up"**

— Animesh Pathak ([@sonichigo](https://github.com/sonichigo)), Developer Relations Engineer, Harness Inc

## A note on terminology (important — read this first)

The talk title uses community shorthand. People say "SSE → Streamable HTTP" when what they actually mean is *"the dual-endpoint HTTP+SSE architecture → the single-endpoint Streamable HTTP architecture."*

Three things people conflate:

| Term | What it is | Status |
|---|---|---|
| **HTTP+SSE transport** | The deprecated MCP transport. Two endpoints: `GET /sse` (persistent) + `POST /message`. Required sticky sessions. | **Deprecated** (spec 2025-03-26) |
| **Streamable HTTP transport** | The current MCP transport. Single endpoint that supports both POST and GET, with optional SSE streaming for responses. | **Current spec** |
| **SSE (the format)** | The W3C `text/event-stream` content type. Used *inside* Streamable HTTP for streaming server messages. | **Still alive — actively used** |

**The deprecation was architectural, not protocol-level.** Streamable HTTP still uses SSE format when it needs to stream multiple messages — it's just no longer a separate persistent endpoint. Throughout this repo, when I use the shorthand "SSE deprecated" I mean the two-endpoint architecture.

## What's in here

The same MCP server (a GitHub repo stats tool) implemented three ways. You can run them side by side and watch how each architecture behaves under different conditions.

```
src/
├── stdio-server/                       # Local-only transport (still recommended for Claude Desktop / Code)
├── http-sse-server-deprecated/         # The dual-endpoint HTTP+SSE pattern (deprecated March 2025)
└── streamable-http-server/             # The current spec (uses SSE format internally when streaming)

clients/                                # A minimal MCP client to test each server
scripts/
├── load-test-dual-endpoint.sh          # Watch the deprecated architecture break behind a load balancer
└── load-test-streamable.sh             # Watch Streamable HTTP scale horizontally
```

## The tool we're implementing

A single MCP tool — `github_repo_stats` — that fetches public stats for any GitHub repo. Picked deliberately:

- **Real I/O** (calls the GitHub API), so transport behavior is observable.
- **Stateless** (no auth, no session needed), so we can fairly compare architectures.
- **Small enough** to fit on a slide.

## Quick start

```bash
pnpm install

# Run all three servers in parallel
pnpm dev:all

# Or one at a time:
pnpm dev:stdio          # → connects via stdin/stdout
pnpm dev:http-sse       # → http://localhost:3001 (deprecated dual-endpoint pattern)
pnpm dev:streamable     # → http://localhost:3002 (current spec)
```

## The demo that lands the point

```bash
# Start the load-balancer simulator (round-robin across 3 instances of each server)
pnpm demo:lb

# Hit the dual-endpoint server through it — watch it fail intermittently
pnpm demo:lb:dual-endpoint

# Hit the Streamable HTTP server through it — watch it just work
pnpm demo:lb:streamable
```

The deprecated dual-endpoint server fails roughly 2 out of every 3 requests because the POST `/message` lands on a different process than the GET `/sse` that initiated the session. The Streamable HTTP server is stateless and doesn't care which instance handles each request.

This is the live version of the architectural contrast in the slides.

## The real-world failure I keep referencing

The intermittent-failure scenario in `scripts/load-test-dual-endpoint.sh` is a synthetic version of an actual incident from the Harness MCP Server's staging environment. We had a load balancer with default round-robin behavior in front of three pods. About 60% of MCP tool calls failed silently because the POST request landed on the wrong pod. Logs showed nothing because each pod treated it as a missing session and returned 404 to the SSE stream that wasn't there.

Three days of debugging produced a one-line architectural fix: switch transports. That experience is what this talk is built on.

## Where SSE format still lives in the current architecture

This is the bit that confuses people. The current Streamable HTTP transport **still uses SSE format** — but as a response mode, not a separate endpoint. When a client POSTs to the single `/mcp` endpoint, the server can respond with either:

1. **A plain JSON body** (`Content-Type: application/json`) — for simple one-shot requests
2. **An SSE stream** (`Content-Type: text/event-stream`) — when the server needs to stream progress, notifications, or multiple messages

See `src/streamable-http-server/index.ts` — the SDK's `handleRequest()` picks the response mode automatically based on what the server is doing.

## Migration cheat sheet

If you have an existing dual-endpoint server and want to migrate, the diff is roughly:

```diff
- import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
+ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";

- app.get("/sse", async (req, res) => {
-   const transport = new SSEServerTransport("/message", res);
-   await server.connect(transport);
- });
- app.post("/message", async (req, res) => {
-   await transport.handlePostMessage(req, res);
- });

+ app.post("/mcp", async (req, res) => {
+   const transport = new StreamableHTTPServerTransport({
+     sessionIdGenerator: () => randomUUID(),
+   });
+   await server.connect(transport);
+   await transport.handleRequest(req, res, req.body);
+ });
```

Plus a 405 shim for the old `/sse` endpoint — see `src/streamable-http-server/index.ts`.

## Real-world deprecation deadlines

This isn't theoretical — major MCP server providers are pulling the old endpoints:

| Vendor | Deadline | Notes |
|---|---|---|
| Keboola | April 1, 2026 | Removing dual-endpoint SSE |
| Atlassian Rovo | June 30, 2026 | `mcp.atlassian.com/v1/sse` → `/v1/mcp` |

If your server still uses the dual-endpoint pattern, your integrations will start breaking in 2026.

## Resources & References

- [Talk: From SSE to Streamable HTTP — MCP Dev Summit Bengaluru 2026](https://mcpbengaluru26.sched.com/event/2NLM1/from-sse-to-streamable-http-what-actually-changed-in-mcps-transport-layer-and-why-you-should-care-animesh-pathak-harness-inc)
- [Blog: Model Context Protocol — Stateless Architecture Explained](https://sonichigo.com/posts/model-context-protocol-stateless-architecture-explained)

## License

MIT