diff --git a/src/index.tsx b/src/index.tsx index 6362415..5fca3e9 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -10,6 +10,14 @@ import CredentialRoute from "./server/routes/credential_route"; import DarmasabaRoute from "./server/routes/darmasaba_route"; import { convertOpenApiToMcp } from "./server/lib/mcp-converter"; +function encode(str: string) { + return new TextEncoder().encode(str); +} + +function sleep(ms: number) { + return new Promise((r) => setTimeout(r, ms)); +} + const Docs = new Elysia() .use(Swagger({ path: "/docs", @@ -47,23 +55,32 @@ const app = new Elysia() tags: ["MCP"], } }) - .get("/mcp", ({ set }) => { - set.headers["Content-Type"] = "text/event-stream" - set.headers["Cache-Control"] = "no-cache" - set.headers["Connection"] = "keep-alive" + .get("/mcp", () => { + // Buat stream SSE + const stream = new ReadableStream({ + async start(controller) { + // Kirim event pertama + controller.enqueue(encode("event: ready\ndata: " + JSON.stringify({ ok: true }) + "\n\n")); - return (send: (chunk: string) => void) => { - // kirim event awal - send(`event: ready\ndata: ${JSON.stringify({ ok: true })}\n\n`) + // Kirim event tiap 5 detik + while (true) { + controller.enqueue(encode("event: status\ndata: " + JSON.stringify({ timestamp: Date.now() }) + "\n\n")); + await sleep(5000); + } + }, + cancel() { + console.log("SSE client disconnected"); + } + }); - // kirim update tiap 5 detik - const interval = setInterval(() => { - send(`event: status\ndata: ${JSON.stringify({ timestamp: Date.now() })}\n\n`) - }, 5000) - - // stop interval saat client disconnect - return () => clearInterval(interval) - } + // Kembalikan Response manual + return new Response(stream, { + headers: { + "Content-Type": "text/event-stream", + "Cache-Control": "no-cache", + Connection: "keep-alive" + } + }); }) .get("*", html)