evOo-local/packages/adapters/src/mcp-emulator.ts
cynarAI 6c7eed7580 Initial clean evOo-local from f00577b
Fresh history cut from cynarAI/evoo antigravity-handoff/project-timeline
(Voice First + project timeline). Brand docs/titles as evOo; keep @rakazo/*
packages as tech debt. Excludes node_modules, caches, secrets, voice blobs.
2026-09-20 17:15:16 +02:00

67 lines
2.1 KiB
TypeScript

import { createServer, type Server } from "node:http";
export interface McpCall {
method: string;
params: Record<string, unknown>;
}
export class McpEmulator {
private server: Server | undefined;
port = 0;
readonly writes: Array<{ path: string; text: string }> = [];
async start(port = 0): Promise<number> {
this.server = createServer((req, res) => {
if (req.method !== "POST") {
res.writeHead(404).end();
return;
}
const chunks: Buffer[] = [];
req.on("data", (c) => chunks.push(c as Buffer));
req.on("end", () => {
const body = JSON.parse(Buffer.concat(chunks).toString("utf8")) as McpCall;
if (body.method === "tools/list") {
res.writeHead(200, { "content-type": "application/json" }).end(
JSON.stringify({
tools: [
{
name: "notes.write",
description: "Write a note in the destination filesystem",
inputSchema: {
type: "object",
properties: { path: { type: "string" }, text: { type: "string" } },
},
},
],
}),
);
return;
}
if (body.method === "tools/call" && body.params.name === "notes.write") {
const args = (body.params.arguments ?? {}) as { path?: string; text?: string };
this.writes.push({ path: args.path ?? "note.md", text: args.text ?? "" });
res
.writeHead(200, { "content-type": "application/json" })
.end(JSON.stringify({ ok: true }));
return;
}
res.writeHead(400).end("unknown method");
});
});
await new Promise<void>((resolve) => this.server?.listen(port, "127.0.0.1", () => resolve()));
const addr = this.server.address();
this.port = typeof addr === "object" && addr ? addr.port : port;
return this.port;
}
async stop(): Promise<void> {
await new Promise<void>((resolve, reject) =>
this.server?.close((err) => (err ? reject(err) : resolve())),
);
}
inspect() {
return { writes: this.writes };
}
}