mcptocodemode

mcp
Guvenlik Denetimi
Uyari
Health Uyari
  • License — License: MIT
  • Description — Repository has a description
  • Active repo — Last push 0 days ago
  • Low visibility — Only 5 GitHub stars
Code Uyari
  • fs module — File system access in package.json
Permissions Gecti
  • Permissions — No dangerous permissions requested

Bu listing icin henuz AI raporu yok.

SUMMARY

Stop flooding your agent's prompt with MCP tools: MCPtoCodeMode puts every MCP server behind 3 tools and a sandbox, for Codex, Claude Code, Cursor, Grok, OpenCode, Pi, or any MCP client.

README.md

MCPtoCodeMode

Specification · Benchmarks · CI · MIT License · Changelog

One MCP server in front of all the MCP servers you already use. Your model sees three tools instead of hundreds, and it writes one short program instead of making dozens of tool calls.

npx -y mcptocodemode list

That finds the MCP servers already configured on your machine (Claude Code, Codex, Cursor, Grok, OpenCode, Pi, VS Code), connects to them, and prints what the model will be able to call.

Why

Connect seven MCP servers and your client puts 55 tool definitions in every prompt. Then ask it something like "read these 25 order files and total the paid ones". That is 26 tool calls and 26 model turns, and each turn re-reads every file that came before it.

With MCPtoCodeMode the model writes this once, and only the answer comes back:

const listing = await filesystem.list_directory({ path: "/data/orders" });
const names = listing.content.split("\n").map((line) => line.replace("[FILE] ", ""));
const orders = await Promise.all(
  names.map(async (name) => JSON.parse((await filesystem.read_text_file({ path: `/data/orders/${name}` })).content)),
);
const paid = orders.filter((order) => order.status === "paid");
return { paid: paid.length, total: paid.reduce((sum, order) => sum + order.total, 0) };

The code runs in a sandbox with no network, no filesystem, and no credentials. Its only way out is the MCP servers you configured.

Benchmarks

Seven official reference servers, 55 tools. Method, raw data, and caveats are in REPORT.md.

With Claude Sonnet 5.5 on real tasks, through OpenRouter:

Plain MCP MCPtoCodeMode
Correct answers, three tasks × 3 runs 9 / 9 9 / 9
Input tokens for those 9 runs 531,480 94,002 (5.7× fewer)
Cost for those 9 runs $1.108 $0.222 (5× less)
Tokens to count errors in a 2,000-line log 102,282 8,197
Mail: page through threads, pass a 150 KB image to another tool (1 run) failed, $0.756, 79 s correct, $0.061, 10 s
Model turns, three tasks × 3 runs 21 29

Same answers for a fifth of the cost. On the mail task, which moves a file between tools, plain MCP failed for both Sonnet and Haiku and MCPtoCodeMode got it right, one run each. It takes a few more turns: the model usually searches once before it writes the program.

Without a model in the loop:

Plain MCP MCPtoCodeMode
Tool definitions in every prompt 31,179 bytes 2,996 bytes, however many servers you add
Count errors in a 2,000-line log: bytes back to the model 129,977 402
Mail: count unread across 3 pages, pass a 150 KB image to another tool 230,668 bytes back, 200,141 written out 362 bytes back
Startup: first search answered, tools cached 1,697 ms (v0.1.1) 320 ms

Use it

Add one server to your coding agent. It finds the servers you already configured for any of these agents, so you don't move them.

Claude Code

claude mcp add codemode -- npx -y mcptocodemode serve

Codex — ~/.codex/config.toml

[mcp_servers.codemode]
command = "npx"
args = ["-y", "mcptocodemode", "serve"]

search and describe are read-only, so Codex runs them without asking. execute can call any of your tools, so Codex asks before each run. Two ways to stop the prompts:

  • Add "--read-only" to args. The code can then only call methods their servers mark read-only, and execute is announced as read-only, so Codex approves it. See Read-only mode.
  • Add default_tools_approval_mode = "approve" to approve everything, writes included.

Grok — ~/.grok/config.toml, same table as Codex. Grok starts a server from a project's .grok/config.toml only in a trusted folder (grok --trust).

Cursor — ~/.cursor/mcp.json or .cursor/mcp.json

{ "mcpServers": { "codemode": { "command": "npx", "args": ["-y", "mcptocodemode", "serve"] } } }

OpenCode — ~/.config/opencode/opencode.json or opencode.json

{ "mcp": { "codemode": { "type": "local", "command": ["npx", "-y", "mcptocodemode", "serve"] } } }

OpenCode 2 has a code mode of its own and wraps MCP tools in it, so the model ends up calling execute through OpenCode's execute. It works, but it is slower than in agents without one.

Pi

pi mcp add codemode -- npx -y mcptocodemode serve

Any other agent or provider. MCPtoCodeMode is a stdio MCP server, so anything that speaks MCP can run it. The whole setup is one command:

npx -y mcptocodemode serve --config /path/to/servers.json

servers.json uses the standard mcpServers format above. Leave --config out to use the configs it discovers. If your agent has no MCP support, the library gives you the same three tools to wire into any model API.

MCPtoCodeMode skips its own entry when it reads these configs. Remove your other servers from the agent if you want the model to see only the three tools.

Tested end to end, each agent answering a question through the three tools while MCPtoCodeMode read that agent's config: Claude Code 2.1, Codex 0.163, OpenCode 2.1, Pi 1.3, and Grok 1.0. Cursor's config format is covered by tests; its agent was not run.

How it works

The model gets three tools:

  • search finds methods by keyword. The top hits include their TypeScript signature.
  • describe returns the full signature of a server ("notes") or one method ("notes.get").
  • execute runs JavaScript. Each server is a global: await notes.get({ id: "1" }). Only the return value comes back, plus console.log output and a list of which methods ran.

Every server also has resources.list, resources.read, resources.templates, prompts.list, and prompts.get. Inside execute, codemode.search and codemode.describe work too. The full contract is SPEC.md.

Configuration

With no flags, serve reads the MCP configs on your machine, in this order. A later server with the same name wins.

  • ~/.codex/config.toml, Claude Desktop, ~/.claude.json (including the servers Claude Code stores for this project), ~/.cursor/mcp.json, ~/.grok/config.toml, ~/.config/opencode/opencode.json[c], ~/.config/mcp/mcp.json, ~/.pi/agent/mcp.json
  • from the git root down to the current directory: .mcp.json, mcp.json, .cursor/mcp.json, .vscode/mcp.json, .grok/config.toml, .codex/config.toml, opencode.json[c], .pi/mcp.json
  • ./mcptocodemode.config.json

It accepts standard mcpServers JSON, VS Code servers JSON, OpenCode mcp JSON or JSONC, and Codex or Grok [mcp_servers.name] TOML, over stdio, streamable HTTP, or SSE. ${VAR} and ${VAR:-default} expand from the environment.

Option Effect
--config file Use only these files. Repeatable. CODEMODE_CONFIG sets one.
--lazy Don't launch a cached server until code calls it.
--read-only Refuse methods their server does not mark read-only. Same as CODEMODE_READ_ONLY=1.
--allow server.method With --read-only, permit one method, or a whole server with server.*. Repeatable.
--no-cache Don't read or write the tool cache. Same as CODEMODE_CACHE=0.
CODEMODE_CACHE_DIR Where tool lists are cached. Default ~/.cache/mcptocodemode.

Servers connect in parallel. One that fails, or doesn't answer within 60 seconds, is skipped and the rest load. Tool lists are cached after each connect, so the next start answers at once and the servers connect in the background. A cache entry is keyed by a hash of the server config, and credentials are never written. mcptocodemode list refreshes the cache. mcptocodemode sdk --out api.d.ts writes the TypeScript the sandbox implements.

Library

import { catalogFromServers, CodeMode } from "mcptocodemode";

const catalog = catalogFromServers([
  { name: "notes", tools: [{ name: "get", inputSchema: { type: "object", properties: { id: { type: "string" } } } }] },
]);
const mode = new CodeMode(catalog, async (call) => ({ id: call.input.id, title: "Buy milk" }));

await mode.execute(`return await notes.get({ id: "1" });`);

beforeCall can refuse a method before it runs. createCodeModeServer(mode) turns it into an MCP server, and UpstreamPool connects to real servers.

Limits and safety

The code runs in a QuickJS WebAssembly isolate that lasts for the session: let and const end with each run, but state carries over, so one run can store threads and the next can filter them. reset: true starts an empty session, and so does a run that times out. Each run gets 30 seconds, 100 tool calls, and 100,000 characters of code; the session gets 64 MiB. Tool results over 200,000 characters come back truncated. Images, audio, and binary resources stay in the host as { $handle, type, mimeType }, which the code can pass to another tool without the bytes ever entering the sandbox or the model's context.

The sandbox limits what the code can reach. It does not limit what a tool does: a tool that sends an email still sends it. Use read-only mode, or beforeCall in the library, to block methods that need a human.

Read-only mode

npx -y mcptocodemode serve --read-only --allow memory.create_entities

MCP servers mark each tool with hints such as readOnlyHint and destructiveHint. With --read-only, a call goes upstream only when its server marks the method read-only, or when --allow names it. Listing and reading resources and prompts always goes through. Anything else fails inside the program with a message that names the --allow flag, before it reaches the server. In return, execute is announced as read-only, so agents that approve read-only tools, like Codex, stop asking before each run.

Of the 55 tools in the seven reference servers, 36 are marked read-only, 12 write, and 7 are marked destructive. The hints come from each server, so read-only mode is as trustworthy as the servers you connect. In the library, readOnlyPolicy(catalog, { allow }) is the same check as a beforeCall.

Contributing

Setup and tests: CONTRIBUTING.md. Questions: SUPPORT.md. Vulnerabilities: SECURITY.md. Conduct: CODE_OF_CONDUCT.md. This repository follows and defines the minkaworks repository standard.

The idea comes from Cloudflare Code Mode. This project speaks plain MCP, so any MCP client can use it.

Yorumlar (0)

Sonuc bulunamadi