Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Configure HTTP/SSE transport for web-based MCP servers with proper endpoints, authentication, and CORS.
.claude/skills/a5c-ai-mcp-transport-sse-setup/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-03 | ✗→✓ | ▲ Improved | 62% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 39% | 0% |
| case-13 | ✗→✓ | ▲ Improved | 25% | 0% |
| case-14 | ✗→✓ | ▲ Improved | 47% | 0% |
| case-15 | ✗→✓ | ▲ Improved | 16% | 0% |
Configure HTTP/SSE transport for web-based MCP servers.
Invoke this skill when you need to:
| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | language | string | Yes | Target language (typescript, python) | | framework | string | No | Web framework (express, fastify, fastapi) | | auth | object | No | Authentication configuration | | cors | object | No | CORS configuration |
typescriptimport express from 'express'; import cors from 'cors'; import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js'; const app = express(); // CORS configuration app.use(cors({ origin: process.env.ALLOWED_ORIGINS?.split(',') || '*', credentials: true, })); app.use(express.json()); // Store active connections const connections = new Map<string, SSEServerTransport>(); // SSE endpoint app.get('/sse', async (req, res) => { const connectionId = req.query.connectionId as string || crypto.randomUUID(); // Set SSE headers res.setHeader('Content-Type', 'text/event-stream'); res.setHeader('Cache-Control', 'no-cache'); res.setHeader('Connection', 'keep-alive'); res.setHeader('X-Accel-Buffering', 'no'); // Create transport const transport = new SSEServerTransport('/message', res); connections.set(connectionId, transport); // Create server instance for this connection const server = new Server( { name: 'my-mcp-server', version: '1.0.0' }, { capabilities: { tools: {}, resources: {} } } ); // Register handlers... registerToolHandlers(server); // Handle connection close req.on('close', () => { connections.delete(connectionId); transport.close(); }); // Connect transport await server.connect(transport); }); // Message endpoint app.post('/message', async (req, res) => { const connectionId = req.query.connectionId as string; const transport = connections.get(connectionId); if (!transport) { res.status(404).json({ error: 'Connection not found' }); return; } try { await transport.handlePostMessage(req, res); } catch (error) { res.status(500).json({ error: 'Failed to process message' }); } }); // Health check app.get('/health', (req, res) => { res.json({ status: 'healthy', connections: connections.size, timestamp: new Date().toISOString(), }); }); const PORT = process.env.PORT || 3000; app.listen(PORT, () => { console.log(`MCP Server listening on port ${PORT}`); });
pythonfrom fastapi import FastAPI, Request, Response from fastapi.middleware.cors import CORSMiddleware from sse_starlette.sse import EventSourceResponse from mcp.server import Server from mcp.server.sse import SseServerTransport import uuid import asyncio app = FastAPI() # CORS app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Store connections connections: dict[str, SseServerTransport] = {} @app.get("/sse") async def sse_endpoint(request: Request): connection_id = request.query_params.get("connectionId") or str(uuid.uuid4()) async def event_generator(): transport = SseServerTransport("/message") connections[connection_id] = transport server = Server("my-mcp-server") register_handlers(server) try: async for event in transport.events(): yield event finally: connections.pop(connection_id, None) return EventSourceResponse(event_generator()) @app.post("/message") async def message_endpoint(request: Request): connection_id = request.query_params.get("connectionId") transport = connections.get(connection_id) if not transport: return Response(status_code=404, content="Connection not found") body = await request.json() await transport.handle_message(body) return Response(status_code=200) @app.get("/health") async def health(): return { "status": "healthy", "connections": len(connections), }
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→fail | 17,954 | 13,548 | -25% | 1 | 1 | 0% | 3,748 | 4,282 | +14% | 0 | 0 | — |
case-02 | fail→fail | 14,585 | 8,657 | -41% | 1 | 1 | 0% | 2,899 | 3,254 | +12% | 0 | 0 | — |
case-03 | fail→pass | 7,637 | 5,681 | -26% | 1 | 1 | 0% | 1,569 | 2,538 | +62% | 0 | 0 | — |
case-04 | fail→fail | 16,640 | 8,286 | -50% | 1 | 1 | 0% | 2,669 | 2,992 | +12% | 0 | 0 | — |
case-05 | fail→fail | 7,258 | 7,303 | +1% | 1 | 1 | 0% | 1,445 | 2,960 | +105% | 0 | 0 | — |
case-06 | fail→fail | 15,367 | 11,063 | -28% | 1 | 1 | 0% | 2,820 | 3,513 | +25% | 0 | 0 | — |
case-07 | fail→fail | 12,983 | 16,074 | +24% | 1 | 1 | 0% | 2,372 | 4,553 | +92% | 0 | 0 | — |
case-08 | fail→fail | 17,010 | 11,465 | -33% | 1 | 1 | 0% | 2,757 | 3,735 | +35% | 0 | 0 | — |
case-09 | fail→fail | 10,086 | 8,132 | -19% | 1 | 1 | 0% | 2,117 | 3,016 | +42% | 0 | 0 | — |
case-10 | fail→pass | 9,644 | 6,744 | -30% | 1 | 1 | 0% | 1,981 | 2,760 | +39% | 0 | 0 | — |
case-11 | fail→fail | 10,696 | 4,055 | -62% | 1 | 1 | 0% | 1,940 | 2,022 | +4% | 0 | 0 | — |
case-12 | pass→pass | 14,237 | 7,551 | -47% | 1 | 1 | 0% | 2,753 | 2,787 | +1% | 0 | 0 | — |
case-13 | fail→pass | 12,992 | 8,706 | -33% | 1 | 1 | 0% | 2,470 | 3,078 | +25% | 0 | 0 | — |
case-14 | fail→pass | 12,648 | 10,210 | -19% | 1 | 1 | 0% | 2,338 | 3,437 | +47% | 0 | 0 | — |
case-15 | fail→pass | 9,077 | 3,071 | -66% | 1 | 1 | 0% | 1,581 | 1,837 | +16% | 0 | 0 | — |
case-16 | fail→pass | 8,174 | 3,607 | -56% | 1 | 1 | 0% | 1,560 | 1,857 | +19% | 0 | 0 | — |
case-17 | fail→pass | 12,323 | 14,254 | +16% | 1 | 1 | 0% | 2,541 | 3,819 | +50% | 0 | 0 | — |
case-18 | fail→fail | 6,605 | 3,913 | -41% | 1 | 1 | 0% | 1,396 | 2,114 | +51% | 0 | 0 | — |
case-19 | fail→fail | 5,984 | 5,352 | -11% | 1 | 1 | 0% | 1,382 | 2,522 | +82% | 0 | 0 | — |
case-20 | fail→pass | 11,321 | 7,411 | -35% | 1 | 1 | 0% | 2,740 | 3,084 | +13% | 0 | 0 | — |
case-21 | fail→fail | 9,782 | 10,736 | +10% | 1 | 1 | 0% | 2,006 | 3,399 | +69% | 0 | 0 | — |
case-22 | fail→fail | 7,555 | 2,958 | -61% | 1 | 1 | 0% | 1,592 | 1,852 | +16% | 0 | 0 | — |
case-23 | pass→pass | 8,312 | 2,642 | -68% | 1 | 1 | 0% | 1,750 | 1,744 | -0% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted. The headline lift of +35 percentage points is the difference between those two pass rates over the 23 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.