117 lines · 3.5 KB · JavaScript
RawDownload
// A zero-dependency fake `codex app-server`, for the `local` e2e project.//// The curated Codex plugin presets no longer spawn a plugin's MCP client// directly — their service refuses tool calls from non-Codex hosts — so the// scanner emits `codex app-server` recipes and the connector bridges MCP to// the app-server protocol in process. This fixture stands in for the real// binary with the same wire shapes (newline-delimited JSON-RPC, v2 protocol):// `initialize`, the `initialized` notification, `thread/start`,// `mcpServerStatus/list`, and `mcpServer/tool/call` against one MCP server// named `messages`.//// Like stdio-mcp-server.mjs it gates a `saw_codex_home` tool on CODEX_HOME// being present in this process's env, so a scenario can prove the declared// env reached the spawned child through the bridge. import { createInterface } from "node:readline"; const send = (message) => {  process.stdout.write(`${JSON.stringify(message)}\n`);}; const THREAD_ID = "thread-e2e-1"; const TOOLS = {  echo_tool: {    name: "echo_tool",    description: "Echoes the provided text back",    inputSchema: {      type: "object",      properties: { text: { type: "string" } },      required: ["text"],    },  },}; if (process.env.CODEX_HOME !== undefined) {  TOOLS.saw_codex_home = {    name: "saw_codex_home",    description: "Present only because CODEX_HOME is set in this server's environment",    inputSchema: { type: "object", properties: {} },  };} const handle = (msg) => {  // Notifications (`initialized`) carry no id and expect no response.  if (msg.id === undefined || msg.id === null) return;   if (msg.method === "initialize") {    send({ jsonrpc: "2.0", id: msg.id, result: { userAgent: "codex-e2e-fixture/0.0.0" } });    return;  }   if (msg.method === "thread/start") {    send({ jsonrpc: "2.0", id: msg.id, result: { thread: { id: THREAD_ID } } });    return;  }   if (msg.method === "mcpServerStatus/list") {    send({      jsonrpc: "2.0",      id: msg.id,      result: {        data: [          {            name: "messages",            runtimeStatus: "connected",            pluginId: "messages",            serverInfo: null,            tools: TOOLS,            resources: [],            resourceTemplates: [],            authStatus: "unsupported",          },        ],        nextCursor: null,      },    });    return;  }   if (msg.method === "mcpServer/tool/call") {    const { server, tool } = msg.params ?? {};    if (server !== "messages" || TOOLS[tool] === undefined) {      send({        jsonrpc: "2.0",        id: msg.id,        error: { code: -32602, message: `unknown server or tool: ${server}/${tool}` },      });      return;    }    const text =      tool === "echo_tool" ? String(msg.params?.arguments?.text ?? "") : "codex-home-present";    send({ jsonrpc: "2.0", id: msg.id, result: { content: [{ type: "text", text }] } });    return;  }   send({    jsonrpc: "2.0",    id: msg.id,    error: { code: -32601, message: `Method not found: ${msg.method}` },  });}; const rl = createInterface({ input: process.stdin });rl.on("line", (line) => {  const trimmed = line.trim();  if (!trimmed) return;  let msg;  // oxlint-disable-next-line executor/no-try-catch-or-throw -- standalone zero-dep fixture: hand-rolled JSON-RPC framing, not product code  try {    // oxlint-disable-next-line executor/no-json-parse -- standalone zero-dep fixture: hand-rolled JSON-RPC framing, not product code    msg = JSON.parse(trimmed);  } catch {    return;  }  handle(msg);});