import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'; import { sendDidNotAuthenticateMcpRequest, sendDidUseMcpServer, sendDidNotHandleMcpRequest, classifyMcpRequestFailure } from '../metrics/metrics.mjs'; import { sendJsonRpcError } from '../utils/sendJsonRpcError.mjs'; import { withTimeout } from '../utils/withTimeout.mjs'; // eslint-disable-next-line import/extensions const createPostHandler = (deps)=>{ const { strapi, authenticationStrategy, config, createServerWithRegistries, capabilityDefinitions } = deps; return async (ctx)=>{ // Opt out of Koa's response phase — the MCP SDK writes directly to ctx.res // (via res.writeHead / res.end / SSE streaming). Without this, Koa's respond() // would also try to write ctx.body to the socket after the handler returns. ctx.respond = false; const req = ctx.req; const res = ctx.res; let hadAuthenticatedMcpRequest = false; try { const authResult = await authenticationStrategy.authenticate(ctx); if (authResult.authenticated === false) { sendDidNotAuthenticateMcpRequest(strapi, authResult.reason); sendJsonRpcError(res, 'AUTHENTICATION_REQUIRED'); return; } hadAuthenticatedMcpRequest = true; sendDidUseMcpServer(strapi); const { mcpServer } = createServerWithRegistries({ strapi, definitions: capabilityDefinitions, isDevMode: config.isDevMode(), ability: authResult.ability, user: authResult.user }); const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined }); try { await withTimeout(mcpServer.connect(transport), config.connectTimeoutMs, 'mcpServer.connect'); const requestBody = ctx.request.body ?? null; await withTimeout(transport.handleRequest(req, res, requestBody), config.requestTimeoutMs, 'transport.handleRequest'); } finally{ await mcpServer.close(); } } catch (error) { strapi.log.error('[MCP] Error handling POST request', { error: error instanceof Error ? error.message : 'Unknown error', stack: error instanceof Error ? error.stack : undefined }); sendJsonRpcError(res, 'INTERNAL_ERROR'); if (hadAuthenticatedMcpRequest) { sendDidNotHandleMcpRequest(strapi, classifyMcpRequestFailure(error)); } } }; }; export { createPostHandler }; //# sourceMappingURL=handlePost.mjs.map