SSE or Streamable HTTP transport implemented correctly if offered
Why it matters
Servers offering HTTP/SSE transport must produce strictly formatted SSE events with data: prefixes and proper Content-Type: text/event-stream. Omitting the data: prefix causes clients to receive unparseable chunks. Missing CORS headers (CWE-942) block browser-based MCP clients entirely via same-origin policy. Broken session ID management means concurrent clients corrupt each other's message streams. These are protocol-level failures that make the HTTP transport path non-functional for any client not on localhost.
Severity rationale
Medium because SSE format errors and missing CORS headers break HTTP transport for specific client types without affecting stdio-connected clients.
Remediation
Use the SDK's SSEServerTransport or StreamableHTTPServerTransport rather than implementing SSE manually.
// src/transport/http.ts
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'
import { randomUUID } from 'crypto'
app.post('/mcp', async (req, res) => {
const transport = new StreamableHTTPServerTransport({
sessionIdGenerator: () => randomUUID(),
})
await server.connect(transport)
await transport.handleRequest(req, res)
})
If you need custom CORS for browser clients, add Access-Control-Allow-Origin before the SSE response headers. Never implement the data: prefix manually — use the SDK transport.
DetectionPro
The detection method for this pattern is part of AuditBuffet Pro.
The full method (what to look for, pass and fail conditions, and how results get reported) ships inside the MCP Server Audit. The pattern definition, severity rationale, and remediation remain openly licensed under CC-BY-4.0.
External references
- cwe · CWE-942 — Permissive Cross-domain Policy with Untrusted Domains (missing CORS headers)
- external · mcp-spec-http-transport — MCP Specification — Streamable HTTP and SSE transport
Taxons
History
- 2026-04-18·v1.0.0·Initial import from mcp-server·automated