Stateless streamable http mcp
Skill kjuhwa/skills-hub/skills/architecture/stateless-streamable-http-mcp
Use StreamableHTTPServerTransport with sessionIdGenerator:undefined to serve MCP over HTTP without session affinity — multiple subprocess clients share one server, every request is independent.From its SKILL.md
npx -y skills add kjuhwa/skills-hub --skill stateless-streamable-http-mcpAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
3.1 KB, 592 tokens by cl100k_base, as published. Nobody here has run it
Stateless Streamable-HTTP MCP
When to use
- Building an MCP server meant to be consumed by MULTIPLE client subprocesses (Codex, Copilot, CLI).
- Don't want the complexity of MCP's session-aware SSE transport.
- Tools are stateless - any client can call any tool at any time.
How it works
- Instantiate the transport with
sessionIdGenerator: undefined:
This puts the transport in stateless mode - no session cookie, no server-side session registry, no sticky routing.new StreamableHTTPServerTransport({ sessionIdGenerator: undefined }) - Connect a single
Serverinstance to the transport. All clients share it. - Mount at a single path (
/mcp). Route every method (POST, GET, DELETE) totransport.handleRequest(req, res)- the transport does the JSON-RPC dispatch internally. - Each incoming request is fully processed before the socket closes; no long-polling session state.
- Clients use
StreamableHTTPClientTransport(new URL(serverUrl)). In stateless mode, they don't persist a session ID between calls.
Example
import { createServer } from 'node:http';
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined });
const mcp = new Server({ name: 'pool', version: '1.0.0' }, { capabilities: { tools: {} } });
mcp.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: await collectTools() }));
mcp.setRequestHandler(CallToolRequestSchema, async (req) => runTool(req.params.name, req.params.arguments));
await mcp.connect(transport);
createServer(async (req, res) => {
if (new URL(req.url!, 'http://127.0.0.1').pathname !== '/mcp') { res.writeHead(404).end(); return; }
await transport.handleRequest(req, res);
}).listen(0, '127.0.0.1');
Gotchas
- Resource subscriptions and server-initiated notifications DO require a session ID; stateless mode disables them.
- Bind to loopback if you don't have auth - the HTTP layer doesn't check anything.
handleRequestexpects a Nodehttp.IncomingMessage/ServerResponsepair, not FetchRequest/Response- wrap if you're in a Fetch-native framework.- When tools are expensive, add your own rate limiting upstream - stateless means no built-in coalescing.
- Random port (
listen(0)) works nicely - readserver.address()after listen to learn the port.
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.