UNPKG

middy-mcp

Version:

Middy middleware for Model Context Protocol server

74 lines 3.09 kB
import { JSONRPCMessageSchema, } from "@modelcontextprotocol/sdk/types.js"; import createHttpError from "http-errors"; import { z } from "zod"; import { HttpServerTransport } from "./HttpServerTransport.js"; const createMcpError = (httpStatusCode, mcpError) => { const jsonRPCError = { jsonrpc: "2.0", error: mcpError, id: 123, }; return createHttpError(httpStatusCode, JSON.stringify(jsonRPCError)); }; const mcp = ({ server, }) => { const transport = new HttpServerTransport(); const serverReady = server.connect(transport); return { before: async ({ event: { headers, body, isBase64Encoded }, context }) => { const contentTypeHeaderValue = headers?.["content-type"] ?? headers?.["Content-Type"]; const acceptHeaderValue = headers?.["accept"] ?? headers?.["Accept"]; if (acceptHeaderValue === undefined || !acceptHeaderValue.includes("application/json")) { throw createMcpError(406, { code: -32000, message: "Not Acceptable: Client must accept application/json", }); } if (contentTypeHeaderValue === undefined || !contentTypeHeaderValue.includes("application/json")) { throw createMcpError(415, { code: -32000, message: "Unsupported Media Type: Content-Type must be application/json", }); } try { const jsonRPCMessages = z .string() .transform((body) => { const decodedBody = isBase64Encoded ? Buffer.from(body, "base64").toString() : body; const parsedJSONBody = JSON.parse(decodedBody); return Array.isArray(parsedJSONBody) ? parsedJSONBody : [parsedJSONBody]; }) .pipe(z.array(JSONRPCMessageSchema)) .parse(body); context.jsonRPCMessages = jsonRPCMessages; } catch (err) { throw createMcpError(422, { code: -32000, message: "Unprocessable Entity: Invalid or malformed JSON was provided", }); } }, after: async (request) => { await serverReady; if (request.response === null || typeof request.response === "string") { request.response = { statusCode: 202, body: "" }; } const responseMessages = await transport.handleJSONRPCMessages(request.context.jsonRPCMessages); if (responseMessages !== undefined) { request.response = { ...request.response, statusCode: 200, body: JSON.stringify(responseMessages), }; } }, }; }; export default mcp; //# sourceMappingURL=index.js.map