MCPcopy
hub / github.com/inkeep/open-knowledge / createMcpHttpHandler

Function createMcpHttpHandler

packages/server/src/mcp-http.ts:107–223  ·  view source on GitHub ↗
(opts: McpHttpHandlerOptions)

Source from the content-addressed store, hash-verified

105}
106
107export function createMcpHttpHandler(opts: McpHttpHandlerOptions): McpHttpHandler {
108 const sessions = new Map<string, McpHttpSession>();
109 const sessionTtlMs = opts.sessionTtlMs ?? 30 * 60 * 1000;
110 const maxSessions = opts.maxSessions ?? 100;
111
112 async function closeSession(sessionId: string, reason: string): Promise<void> {
113 const session = sessions.get(sessionId);
114 if (!session) return;
115 sessions.delete(sessionId);
116 if (session.ttlTimer !== undefined) clearTimeout(session.ttlTimer);
117 const results = await Promise.allSettled([session.server.close(), session.transport.close()]);
118 for (const result of results) {
119 if (result.status === 'rejected') {
120 opts.log?.warn?.(
121 { err: result.reason, sessionId, reason },
122 'MCP HTTP session close failed',
123 );
124 }
125 }
126 opts.log?.info?.({ sessionId, reason }, 'MCP HTTP session closed');
127 }
128
129 function touchSession(sessionId: string, session: McpHttpSession): void {
130 if (session.ttlTimer !== undefined) clearTimeout(session.ttlTimer);
131 session.ttlTimer = setTimeout(() => {
132 void closeSession(sessionId, 'ttl-expired').catch((err) => {
133 opts.log?.warn?.({ err, sessionId }, 'MCP HTTP session TTL cleanup failed');
134 });
135 }, sessionTtlMs);
136 session.ttlTimer.unref?.();
137 }
138
139 return {
140 async handle(req, res): Promise<void> {
141 const sessionId = firstHeader(req.headers['mcp-session-id']);
142 if (sessionId) {
143 const session = sessions.get(sessionId);
144 if (!session) {
145 writePlain(res, 404, 'MCP session not found');
146 return;
147 }
148 touchSession(sessionId, session);
149 await session.transport.handleRequest(req, res);
150 return;
151 }
152
153 if (req.method !== 'POST') {
154 writePlain(res, 400, 'Missing MCP session. Initialize with POST /mcp first.');
155 return;
156 }
157 if (sessions.size >= maxSessions) {
158 opts.log?.warn?.(
159 { activeSessions: sessions.size, maxSessions },
160 'MCP HTTP session cap reached',
161 );
162 writePlain(res, 503, 'Too many active MCP sessions');
163 return;
164 }

Callers 5

bootServerInnerFunction · 0.90
bootHandlerFunction · 0.90
mcp-http.test.tsFile · 0.90
startHttpMcpServerFunction · 0.85
createTestServerFunction · 0.85

Calls

no outgoing calls

Tested by 2

bootHandlerFunction · 0.72
startHttpMcpServerFunction · 0.68