{"record":{"id":"bc55a13121d2d3ba","repo":"mastra-ai/mastra","slug":"sse-connection-not-established","errorCode":null,"errorMessage":"SSE connection not established","messagePattern":"SSE connection not established","errorType":"http","errorClass":null,"httpStatus":503,"severity":"error","filePath":"packages/mcp/src/server/server.ts","lineNumber":1847,"sourceCode":"   *   });\n   * });\n   *\n   * httpServer.listen(1234, () => {\n   *   console.log('MCP server listening on http://localhost:1234/sse');\n   * });\n   * ```\n   */\n  public async startSSE({ url, ssePath, messagePath, req, res }: MCPServerSSEOptions): Promise<void> {\n    try {\n      if (url.pathname === ssePath) {\n        await this.connectSSE({\n          messagePath,\n          res,\n        });\n      } else if (url.pathname === messagePath) {\n        this.logger.debug('Received message');\n        if (!this.sseTransport) {\n          res.writeHead(503);\n          res.end('SSE connection not established');\n          return;\n        }\n        // Check for pre-parsed body from middleware like express.json()\n        // If not available, let the SDK's handlePostMessage read from the stream\n        // (which has built-in size limits and charset handling)\n        const parsedBody = await this.readJsonBody(req, { preParsedOnly: true });\n        await this.sseTransport.handlePostMessage(req, res, parsedBody);\n      } else {\n        this.logger.debug('Unknown path:', { path: url.pathname });\n        res.writeHead(404);\n        res.end();\n      }\n    } catch (e) {\n      const mastraError = new MastraError(\n        {\n          id: 'MCP_SERVER_SSE_START_FAILED',\n          domain: ErrorDomain.MCP,","sourceCodeStart":1829,"sourceCodeEnd":1865,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/mcp/src/server/server.ts#L1829-L1865","documentation":"In the SSE (legacy) transport integration, POSTs to the messagePath are handled by the stored sseTransport instance, which only exists after a client opened the SSE endpoint. If a POST arrives before any SSE connection was established, the server responds 503 with the plain-text body 'SSE connection not established' instead of processing the message.","triggerScenarios":"POSTing a JSON-RPC message to the messagePath endpoint when no GET request to the ssePath has completed; race where a client sends its initialize message before the SSE stream is connected; load balancer routing the POST to a different instance than the one holding the SSE connection.","commonSituations":"curl-based testing that POSTs to /message without first opening the SSE stream; clients constructed with the wrong SSE URL so the stream never opens; multi-instance deployments without sticky sessions; SSE connection dropped (proxy timeout) while the client keeps POSTing.","solutions":["Establish the SSE connection (GET on ssePath) and wait for the endpoint/event message before POSTing to messagePath","Ensure both SSE and message paths are routed to the same server instance (sticky sessions / single instance)","Fix client configuration so the MCP SDK's SSE client (which sequences SSE then POST) is used instead of hand-rolled requests","Check proxies/load balancers for SSE timeouts or buffering that kill the connection"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"async function postMessage(url, body, retries = 3) {\n  for (let i = 0; i < retries; i++) {\n    const res = await fetch(url, { method: 'POST', body });\n    if (res.status !== 503) return res;\n    await new Promise(r => setTimeout(r, 500 * (i + 1))); // SSE may not be open yet\n  }\n  throw new Error('SSE connection never established; check client transport setup');\n}","preventionTips":["Use the official MCP SDK SSE client, which opens the SSE stream before sending messages","Verify the SSE GET endpoint returns 200 and an endpoint event before POSTing","Configure sticky sessions in multi-instance deployments so SSE and POST hit the same instance","Monitor for proxy/LB configurations that terminate idle SSE connections"],"tags":["mcp","sse","transport","connection-state"],"backgroundTag":"connection-not-established","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}