mcptocodemode
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.
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.
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"toargs. The code can then only call methods their servers mark read-only, andexecuteis 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:
searchfinds methods by keyword. The top hits include their TypeScript signature.describereturns the full signature of a server ("notes") or one method ("notes.get").executeruns JavaScript. Each server is a global:await notes.get({ id: "1" }). Only the return value comes back, plusconsole.logoutput 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)
Yorum birakmak icin giris yap.
Yorum birakSonuc bulunamadi