tamabahan

This commit is contained in:
bipproduction
2025-10-08 19:51:40 +08:00
parent f4e5bff621
commit 4bf052b15e

View File

@@ -8,22 +8,18 @@ import { isInitializeRequest } from '@modelcontextprotocol/sdk/types.js';
const transports: Record<string, StreamableHTTPServerTransport> = {};
const McpRoute = new Elysia()
// Middleware global untuk JSON parsing & header access
.onRequest(({ set }) => {
set.headers['Content-Type'] = 'application/json';
})
// Route utama untuk komunikasi client → server
.post(
'/mcp',
async ({ body, request, set }) => {
const sessionId = request.headers.get('mcp-session-id') ?? undefined;
let transport: StreamableHTTPServerTransport;
// Jika ada sessionId, pakai transport lama
// Jika ada sessionId lama, gunakan ulang transport-nya
if (sessionId && transports[sessionId]) {
transport = transports[sessionId];
} else if (!sessionId && isInitializeRequest(body)) {
// Jika belum ada session & ini request inisialisasi
}
// Jika request inisialisasi baru
else if (!sessionId && isInitializeRequest(body)) {
transport = new StreamableHTTPServerTransport({
sessionIdGenerator: () => randomUUID(),
onsessioninitialized: (sid) => {
@@ -31,22 +27,35 @@ const McpRoute = new Elysia()
},
});
// Cleanup transport jika ditutup
transport.onclose = () => {
if (transport.sessionId) {
delete transports[transport.sessionId];
}
if (transport.sessionId) delete transports[transport.sessionId];
};
// Inisialisasi MCP server
// Inisialisasi MCP Server
const server = new McpServer({
name: 'example-server',
version: '1.0.0',
});
// ... di sini bisa ditambahkan tools, prompts, dsb ...
// Tambahkan resource, tools, dsb di sini jika perlu
await server.connect(transport);
} else {
// Tunggu sampai session terbentuk
await new Promise<void>((resolve) => {
const check = () => {
if (transport.sessionId) return resolve();
setTimeout(check, 5);
};
check();
});
// Kirim sessionId kembali ke client
set.headers['mcp-session-id'] = transport.sessionId!;
set.status = 200;
return { sessionId: transport.sessionId };
}
// Jika request invalid
else {
set.status = 400;
return {
jsonrpc: '2.0',
@@ -59,36 +68,37 @@ const McpRoute = new Elysia()
}
// Jalankan handler HTTP MCP
return await transport.handleRequest(
request as any,
// Simulasi `Response` agar Elysia bisa mengembalikan hasil
new Response(null, { status: 200 }) as any,
body
);
return await transport.handleRequest(request, new Response(), body);
},
{
body: t.Any(), // fleksibel untuk JSON-RPC
body: t.Any(),
}
)
// Handler reusable untuk GET & DELETE
.derive(({ request, set }) => {
// Handler GET untuk SSE (server → client)
.get('/mcp', async ({ request, set }) => {
const sessionId = request.headers.get('mcp-session-id') ?? undefined;
const transport = sessionId ? transports[sessionId] : undefined;
if (!transport) {
set.status = 400;
throw new Error('Invalid or missing session ID');
return 'Invalid or missing session ID';
}
return { transport };
})
// GET untuk server → client via SSE
.get('/mcp', async ({ transport, request }) => {
return await transport.handleRequest(request as any, new Response() as any);
set.status = 200;
return await transport.handleRequest(request, new Response());
})
// DELETE untuk terminasi session
.delete('/mcp', async ({ transport, request }) => {
return await transport.handleRequest(request as any, new Response() as any);
.delete('/mcp', async ({ request, set }) => {
const sessionId = request.headers.get('mcp-session-id') ?? undefined;
const transport = sessionId ? transports[sessionId] : undefined;
if (!transport) {
set.status = 400;
return 'Invalid or missing session ID';
}
set.status = 200;
return await transport.handleRequest(request, new Response());
})
export default McpRoute