Advanced MCP Patterns

SSE Transport for Remote MCP

5 min read

While stdio works great for local servers, Server-Sent Events (SSE) and its successor Streamable HTTP enable remote MCP servers accessible over HTTP.

Important: As of the MCP spec update on 2025-03-26, HTTP+SSE has been deprecated in favor of Streamable HTTP, which consolidates the two-endpoint SSE model into a single HTTP endpoint that can optionally upgrade to SSE streaming. Legacy SSE servers still work, but new projects should use Streamable HTTP. The patterns in this lesson apply to both — the transport primitive in your SDK is the main thing that changes.

When to Use SSE

ScenarioTransport
Local CLI toolstdio
Desktop integrationstdio
Remote serverSSE
Cloud-hosted MCPSSE
Multi-user accessSSE

Setting Up an SSE Server

from mcp.server import Server
from mcp.server.sse import sse_server
import uvicorn
from starlette.applications import Starlette
from starlette.routing import Route

server = Server(name="remote-mcp")

# Register your tools and resources
@server.list_tools()
async def list_tools():
    return [...]

# Create the SSE handler
async def handle_sse(request):
    async with sse_server() as (read, write):
        await server.run(read, write)

# Create Starlette app
app = Starlette(
    routes=[Route("/mcp", handle_sse)],
    debug=True
)

# Run with uvicorn
if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000)

Client Configuration

Configure a remote MCP server in Claude Desktop:

{
  "mcpServers": {
    "remote-kb": {
      "transport": "sse",
      "url": "https://your-server.com/mcp"
    }
  }
}

SSE Message Flow

SSE provides a one-way stream from server to client, with client requests sent via POST:

Client                       Server
  │                            │
  │──GET /mcp (SSE stream)────▶│
  │◀───event: message──────────│
  │◀───event: message──────────│
  │                            │
  │──POST /mcp (request)──────▶│
  │◀───event: response─────────│

Handling Multiple Clients

SSE naturally supports multiple concurrent clients:

from contextlib import asynccontextmanager
from collections import defaultdict

class MultiClientServer:
    def __init__(self):
        self.clients = defaultdict(dict)

    @asynccontextmanager
    async def client_session(self, client_id: str):
        self.clients[client_id] = {"connected": True}
        try:
            yield
        finally:
            del self.clients[client_id]

    async def broadcast(self, message):
        for client_id in self.clients:
            await self.send_to_client(client_id, message)

CORS Configuration

For browser-based clients, configure CORS:

from starlette.middleware.cors import CORSMiddleware

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_methods=["GET", "POST"],
    allow_headers=["*"],
)

Next, we'll add authentication to protect your MCP endpoints. :::

Quiz

Module 4 Quiz: Advanced MCP Patterns

Take Quiz
Was this lesson helpful?

Sign in to rate

FREE WEEKLY NEWSLETTER

Stay on the Nerd Track

One email per week — courses, deep dives, tools, and AI experiments.

No spam. Unsubscribe anytime.