mirror of
https://github.com/Nezumi-2711/9router.git
synced 2026-09-22 13:38:31 +00:00
Restore Cowork feature while closing the RCE vector: drop user-defined stdio commands so only hard-coded preset plugins (browsermcp) may spawn. Custom MCP now accepts remote URL only. Routes stay gated to localhost. Co-authored-by: Cursor <cursoragent@cursor.com>
36 lines
1.0 KiB
JavaScript
36 lines
1.0 KiB
JavaScript
import { registerSession, unregisterSession, findPlugin } from "@/lib/mcp/stdioSseBridge";
|
|
|
|
export const runtime = "nodejs";
|
|
export const dynamic = "force-dynamic";
|
|
|
|
export async function GET(request, { params }) {
|
|
const { plugin } = await params;
|
|
if (!findPlugin(plugin)) {
|
|
return new Response(`Unknown plugin: ${plugin}`, { status: 404 });
|
|
}
|
|
|
|
const encoder = new TextEncoder();
|
|
let sid;
|
|
|
|
const stream = new ReadableStream({
|
|
start(controller) {
|
|
const send = (chunk) => controller.enqueue(encoder.encode(chunk));
|
|
sid = registerSession(plugin, send);
|
|
// MCP SSE handshake: tell client where to POST messages.
|
|
send(`event: endpoint\ndata: /api/mcp/${plugin}/message?sessionId=${sid}\n\n`);
|
|
},
|
|
cancel() {
|
|
if (sid) unregisterSession(plugin, sid);
|
|
},
|
|
});
|
|
|
|
return new Response(stream, {
|
|
headers: {
|
|
"Content-Type": "text/event-stream",
|
|
"Cache-Control": "no-cache, no-transform",
|
|
Connection: "keep-alive",
|
|
"X-Accel-Buffering": "no",
|
|
},
|
|
});
|
|
}
|