import { randomUUID } from 'node:crypto';
import type { IncomingMessage, ServerResponse } from 'node:http';
import { createMcpExpressApp } from '@modelcontextprotocol/sdk/server/express.js';
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
import { isInitializeRequest } from '@modelcontextprotocol/sdk/types.js';
import type { Resend } from 'resend';
import { createMcpServer } from '../server.js';
import type { ServerOptions } from '../types.js';
const sessions: Record<string, StreamableHTTPServerTransport> = {};
function sendJsonRpcError(res: ServerResponse, message: string): void {
res.statusCode = 400;
res.setHeader('Content-Type', 'application/json');
res.end(
JSON.stringify({
jsonrpc: '2.0',
error: { code: -32000, message },
id: null,
}),
);
}
export async function runHttp(
resend: Resend,
options: ServerOptions,
port: number,
): Promise<void> {
const getServer = (): McpServer => createMcpServer(resend, options);
const app = createMcpExpressApp();
app.all(
'/mcp',
async (req: IncomingMessage & { body?: unknown }, res: ServerResponse) => {
const sessionId = req.headers['mcp-session-id'] as string | undefined;
let transport: StreamableHTTPServerTransport | undefined;
if (sessionId && sessions[sessionId]) {
transport = sessions[sessionId];
} else if (
!sessionId &&
req.method === 'POST' &&
isInitializeRequest(req.body)
) {
transport = new StreamableHTTPServerTransport({
sessionIdGenerator: () => randomUUID(),
onsessioninitialized: (sid) => {
sessions[sid] = transport!;
},
});
transport.onclose = () => {
const sid = transport!.sessionId;
if (sid && sessions[sid]) delete sessions[sid];
};
const server = getServer();
await server.connect(transport);
} else if (sessionId && !sessions[sessionId]) {
res.statusCode = 404;
res.setHeader('Content-Type', 'application/json');
res.end(
JSON.stringify({
jsonrpc: '2.0',
error: { code: -32001, message: 'Session not found' },
id: null,
}),
);
return;
} else {
sendJsonRpcError(res, 'Bad Request: No valid session ID provided');
return;
}
await transport.handleRequest(req, res, req.body);
},
);
return new Promise((resolve, reject) => {
const server = app.listen(port, () => {
console.error(`Resend MCP server listening on http://127.0.0.1:${port}`);
console.error(' Streamable HTTP: POST/GET/DELETE /mcp');
resolve();
});
server.once('error', reject);
const shutdown = async () => {
for (const sid of Object.keys(sessions)) {
try {
await sessions[sid].close();
} catch {
// ignore
}
delete sessions[sid];
}
server.close();
process.exit(0);
};
process.on('SIGINT', shutdown);
process.on('SIGTERM', shutdown);
});
}