原始内容
Code Executor MCP
An MCP server that enables AI agents to execute TypeScript code that calls other MCP tools. This implements the "code execution with MCP" pattern described in Anthropic's engineering blog for building more efficient agents.
The Problem
As MCP usage scales, two patterns increase agent cost and latency:
- Tool definitions overload the context window - Loading all tool definitions upfront consumes hundreds of thousands of tokens
- Intermediate results consume additional tokens - Every tool result passes through the model, even when just piping data between tools
The Solution
Instead of calling MCP tools directly, agents write TypeScript code that imports generated wrapper files. This enables:
- Progressive disclosure - Load only the tools needed for the current task
- Context-efficient results - Filter and transform data in code before returning to the model
- Powerful control flow - Use loops, conditionals, and error handling with familiar patterns
- State persistence - Write intermediate results to files, build reusable skills
Token savings can reach 98%+ compared to direct tool calls for complex workflows (Anthropic's analysis). Our benchmarks measured 97.6% average savings (ranging from 93.6% to 99.9%). See benchmark details →
Architecture
Code Executor MCP acts as a meta-MCP server - it provides tools to execute TypeScript code that can call other MCP servers. This creates a powerful abstraction layer that dramatically reduces token usage.
flowchart TB
subgraph "AI Agent Layer"
AGENT[🤖 Agent / LLM]
end
subgraph "Code Executor MCP"
SERVER[📡 MCP Server<br/><code>src/server.ts</code>]
EXECUTOR[⚡ Code Executor<br/><code>src/run.ts</code>]
GENERATOR[🔧 Wrapper Generator<br/><code>src/generate.ts</code>]
end
subgraph "Generated Layer"
WRAPPERS[📦 Server Wrappers<br/><code>servers/<name>/index.ts</code>]
end
subgraph "Target MCP Servers"
MCP1[Context7 MCP]
MCP2[Filesystem MCP]
MCP3[Other MCPs...]
end
subgraph "Configuration"
CONFIG[⚙️ mcp.json]
SKILLS_CFG[📋 skills.json]
end
AGENT -->|"1. execute_code({ code })"| SERVER
SERVER -->|"2. Runs TypeScript"| EXECUTOR
EXECUTOR -->|"3. import from"| WRAPPERS
WRAPPERS -->|"4. MCP protocol"| MCP1
WRAPPERS -->|"4. MCP protocol"| MCP2
WRAPPERS -->|"4. MCP protocol"| MCP3
CONFIG -.->|"Defines servers"| GENERATOR
GENERATOR -.->|"pnpm run gen"| WRAPPERS
style SERVER fill:#4caf50,color:#fff
style EXECUTOR fill:#2196f3,color:#fff
style WRAPPERS fill:#ff9800,color:#fff
How It Works
| Step | Component | Description |
|---|---|---|
| 1 | Agent | Sends TypeScript code via execute_code tool |
| 2 | Server | Receives code and passes to executor |
| 3 | Executor | Compiles and runs TypeScript from workspace/ directory |
| 4 | Wrappers | Generated files that handle MCP client connections |
| 5 | Target MCPs | External MCP servers that perform actual work |
Data Flow
sequenceDiagram
participant A as Agent (LLM)
participant S as Code Executor Server
participant E as TypeScript Executor
participant W as Generated Wrapper
participant M as Target MCP Server
A->>S: execute_code({ code: "..." })
S->>E: Run TypeScript code
E->>W: import { tool } from '../servers/...'
W->>M: MCP tool call (JSON-RPC)
M-->>W: Tool result
W-->>E: Parsed result
Note over E: Filter/transform data in code
E-->>S: console.log output only
S-->>A: Minimal result (98%+ token savings)
Key insight: Only console.log output returns to the agent. All intermediate data stays in code, avoiding context window bloat.
Workspace Execution Context
Important: All code executed via
execute_coderuns from theworkspace/directory as the current working directory (cwd). This affects how imports and file paths work.
graph TB
subgraph "Project Root"
direction TB
SRC[src/server.ts<br/>MCP Server]
SERVERS[servers/<br/>Generated Wrappers]
SKILLS[skills/<br/>Knowledge Packages]
SCRIPTS[scripts/<br/>Reusable Scripts]
WS[workspace/<br/>Execution Context]
end
subgraph "Code Execution"
direction TB
CODE["execute_code({ code })"]
CWD["cwd = workspace/"]
end
AGENT[Agent/LLM] -->|"1. Sends code"| SRC
SRC -->|"2. Executes from workspace/"| CODE
CODE --> CWD
CWD -->|"3. Import '../servers/...'"| SERVERS
CWD -->|"4. Read '../skills/...'"| SKILLS
CWD -->|"5. fs operations use './' "| WS
style WS fill:#e1f5fe,stroke:#01579b
style CWD fill:#e1f5fe,stroke:#01579b
Key implications:
| Operation | Path | Why |
|---|---|---|
| Import server wrappers | ../servers/<name>/index.js |
Navigate up from workspace/ to project root |
| Import skills | ../skills/<name>/... |
Same reason |
File I/O (fs.readFile, etc.) |
./filename.txt |
Relative to workspace/ |
console.log output |
Returned to agent | Captured as execution result |
This design isolates executed code's file operations to the workspace/ directory while allowing imports from generated wrappers.
Installation
# Clone the repository
git clone https://github.com/nicobailon/Code-Executor-MCP.git
cd Code-Executor-MCP
# Install dependencies
pnpm install
# Generate wrapper files for configured MCP servers
pnpm run gen
Configuration
MCP Servers (mcp.json)
Configure the MCP servers you want to use:
{
"servers": {
"context7": {
"enabled": true,
"description": "Fetches up-to-date library documentation and code examples",
"transport": "stdio",
"command": "node",
"args": ["mcps/context7-mcp/dist/index.js"],
"env": {}
}
}
}
The description field is used by list_servers_metadata to provide a quick overview of available servers.
Note: Paths in the
argsarray (and other path-related fields) are resolved relative to the project root directory where the Code Executor MCP server is running.
Environment Variables
| Variable | Description |
|---|---|
CODE_EXECUTOR_MCP_CONFIG |
Path to custom mcp.json location |
CODE_EXECUTOR_SKILLS_CONFIG |
Path to custom skills.json location |
CODE_EXECUTOR_SKIP_GET_STARTED |
Skip the get_started blocking requirement (accepts "true", "1", or "yes") |
CLI Arguments
The server supports CLI arguments to override config paths:
# Override mcp.json location
node dist/server.js --mcp-config /path/to/custom/mcp.json
# Override skills.json location
node dist/server.js --skills-config /path/to/custom/skills.json
# Skip the get_started requirement
node dist/server.js --skip-get-started
# All can be combined
node dist/server.js --mcp-config ./my-mcp.json --skills-config ./my-skills.json --skip-get-started
Priority: CLI args > environment variables > defaults
Skills (skills.json)
Configure reusable skills (knowledge packages):
{
"skills": {
"context7-usage": {
"enabled": true,
"tags": ["mcp", "documentation"]
}
}
}
Usage
Basic Workflow
List available servers
Tool: list_available_serversList tools for a server
Tool: list_server_tools Args: { "server": "context7" }Execute code
import * as context7 from '../servers/context7/index.js'; const libs = await context7.resolveLibraryId.call({ libraryName: "react" }); console.log(JSON.stringify(libs, null, 2));
Import Patterns
Note: These import paths (like
../servers/) work because code is executed from theworkspace/directory context. The relative paths navigate fromworkspace/to the project root'sservers/directory.
// Pattern 1: Import entire server
import * as context7 from '../servers/context7/index.js';
await context7.resolveLibraryId.call({ libraryName: "react" });
// Pattern 2: Import specific tool
import { resolveLibraryId } from '../servers/context7/index.js';
await resolveLibraryId.call({ libraryName: "react" });
// Pattern 3: Direct file import
import * as tool from '../servers/context7/resolve-library-id.js';
await tool.call({ libraryName: "react" });
Example: Multi-Tool Workflow
import * as context7 from '../servers/context7/index.js';
// Step 1: Find library ID
const libs = await context7.resolveLibraryId.call({
libraryName: "react"
});
console.log("Libraries:", JSON.stringify(libs, null, 2));
// Step 2: Get docs (use ID from step 1)
const docs = await context7.getLibraryDocs.call({
context7CompatibleLibraryID: "/facebook/react",
topic: "hooks useState"
});
console.log("Docs:", docs);
Available Tools
| Tool | Description |
|---|---|
get_started |
Tutorial on using Code Executor MCP |
execute_code |
Run TypeScript code with MCP tool access |
run_script |
Run a TypeScript script from the scripts/ directory |
list_servers |
List available MCP server wrappers in servers/ directory |
list_available_servers |
List MCP servers that are enabled and have wrappers |
list_server_tools |
List tools and parameters for a specific server |
list_servers_metadata |
Get name and description of all configured servers |
get_tool_schema |
Get full parameter schema for a specific tool |
validate_code |
Check TypeScript syntax before execution |
list_skills |
List available skills in skills/ directory |
list_skills_metadata |
Get name and description of all enabled skills |
read_skill |
Read skill documentation |
list_workspace_files |
List files in workspace/ directory |
read_workspace_file |
Read a file from workspace/ |
list_scripts |
List available scripts in scripts/ directory |
check_server_health |
Diagnose server connection issues |
test_server_connection |
Test server connection with timing |
get_server_stderr |
Get stderr from server for debugging |
Project Structure
Code-Executor-MCP/
├── src/
│ ├── server.ts # MCP server implementation
│ ├── mcp.ts # MCP client for connecting to other servers
│ ├── config.ts # Configuration loading
│ ├── generate.ts # Wrapper file generator
│ └── run.ts # Script runner
├── benchmark/ # Token savings benchmark system
│ ├── src/ # Benchmark implementation
│ ├── scenarios/ # Benchmark test cases
│ └── results/ # Benchmark output
├── servers/ # Generated wrapper files (created by `pnpm run gen`)
├── scripts/ # Reusable TypeScript scripts
├── skills/ # Knowledge packages with documentation
├── workspace/ # Working directory for executed code
├── mcps/ # Bundled MCP servers
├── mcp.json # MCP server configuration
└── skills.json # Skills configuration
Documentation
This project includes comprehensive documentation across multiple files:
Core Documentation
| Document | Description |
|---|---|
| TOOLS.md | Complete reference for all 18 available tools with parameters, examples, and usage patterns |
| TESTING.md | Testing strategy and plan using Vitest, including test structure and coverage goals |
| REFERENCE.md | Background article from Anthropic Engineering on the code execution with MCP pattern |
Benchmark Documentation
| Document | Description |
|---|---|
| benchmark/README.md | Benchmark methodology and how to run token savings measurements |
| benchmark/results/RESULTS.md | Detailed benchmark results showing 97.6% average token savings |
Skills Documentation
Skills are knowledge packages that help with specific tasks. Each skill has a SKILL.md file:
| Skill | Description |
|---|---|
| skills/context7-usage/SKILL.md | Tips and best practices for using Context7 MCP server |
| skills/mcp-tool-discovery/SKILL.md | Guide for discovering MCP tool parameters and debugging |
| skills/time-helper/SKILL.md | Time and timezone conversion capabilities |
Additional References
| Document | Description |
|---|---|
| mcps/context7-mcp/README.md | Context7 MCP server documentation (bundled example) |
| skills/time-helper/references/iana_timezones.md | IANA timezone reference list |
Key Features
Auto-Cleanup
By default, executed code automatically cleans up MCP connections when done:
// autoExit: true (default) - connections close when event loop idles
const result = await execute_code({ code: "...", autoExit: true });
// autoExit: false - manage cleanup manually if needed
const result = await execute_code({ code: "...", autoExit: false });
Timeout Control
// Default timeout: 120 seconds
const result = await execute_code({
code: "...",
timeout: 60000 // 60 seconds
});
Skills System
Skills are knowledge packages that help with specific tasks:
// List available skills
Tool: list_skills
// Read a skill's documentation
Tool: read_skill
Args: { "skill": "context7-usage" }
Benchmarks
This project includes a benchmark system that validates the token savings claims. Our benchmarks use tiktoken to count tokens accurately.
Benchmark Results
| Scenario | Direct Tokens | Code Execution | Savings |
|---|---|---|---|
| Simple Tool Call | 1,181 | 76 | 93.6% |
| Multi-Tool Workflow | 11,763 | 198 | 98.3% |
| Data Filtering | 697,287 | 650 | 99.9% |
| Loop Operations | 15,970 | 226 | 98.6% |
Summary:
- Total tokens saved: 725,051 (99.8% reduction)
- Average savings: 97.6%
- Range: 93.6% - 99.9%
💡 Anthropic's engineering blog claims "98%+ token savings" - our benchmarks confirm this with measured results averaging 97.6% savings.
Running Benchmarks
cd benchmark
pnpm install
pnpm run benchmark
See benchmark/README.md for methodology and scenario details.
Development
# Run in development mode
pnpm run dev
# Build for production
pnpm run build
# Start production server
pnpm run start
# Regenerate wrapper files
pnpm run gen
Note: The server logs to stderr (visible in terminal or MCP client logs). This includes startup messages showing which config files are being used.
Testing
This project uses Vitest for testing with comprehensive coverage of all modules.
Running Tests
# Run all tests
pnpm test
# Run tests in watch mode
pnpm test:watch
# Run tests with coverage report
pnpm test:coverage
# Run specific test suites
pnpm test:unit # Unit tests only
pnpm test:integration # Integration tests only
pnpm test:e2e # End-to-end tests only
Test Structure
tests/
├── setup.ts # Global test setup
├── mocks/
│ ├── mcp-client.ts # Mock MCP client
│ └── fixtures/
│ ├── mcp.json # Test config fixture
│ ├── skills.json # Test skills config fixture
│ └── tool-schemas.ts # Sample tool schemas
├── unit/
│ ├── config.test.ts # Tests for config.ts
│ ├── mcp.test.ts # Tests for mcp.ts helpers
│ ├── helpers.test.ts # Tests for helpers.ts
│ ├── server.test.ts # Tests for server.ts
│ ├── generate.test.ts # Tests for generate.ts
│ └── run.test.ts # Tests for run.ts
├── integration/
│ ├── mcp-connection.test.ts # MCP server connection tests
│ └── tool-execution.test.ts # Tool execution tests
└── e2e/
├── generate-workflow.test.ts # Full generate workflow
└── execute-code-workflow.test.ts # Full execute_code workflow
Coverage
The project maintains 100% test coverage across all metrics (statements, branches, functions, lines) for core modules:
| Module | Coverage |
|---|---|
| config.ts | 100% |
| helpers.ts | 100% |
| mcp.ts | 100% |
Run pnpm test:coverage to generate detailed coverage reports in text, JSON, and HTML formats.
Common Issues
Import Errors
| Error | Solution |
|---|---|
Cannot find module |
Add /index.js to import path |
Missing .js extension |
ESM requires explicit .js extensions |
is not a function |
Use .call() - tools are objects, not functions |
Connection Issues
- Check server is enabled in
mcp.json - Run
check_server_healthto diagnose - Review stderr with
get_server_stderr - Verify command and args are correct
Wrapper Generation Failures (pnpm run gen)
If wrapper generation fails:
Server not responding: Ensure the target MCP server is working independently
# Test the server command directly node mcps/context7-mcp/dist/index.jsIncorrect command/args in mcp.json: Verify paths are correct and the command exists
{ "command": "node", "args": ["mcps/context7-mcp/dist/index.js"] }Missing dependencies: The target server may need to be built first
cd mcps/context7-mcp && pnpm install && pnpm buildCheck stderr output: The generator logs errors to stderr - check terminal output for details
Background
This project implements the code execution pattern described in Anthropic's engineering blog post on building efficient agents with MCP. The core insight is that LLMs are adept at writing code, and developers can leverage this to build agents that interact with MCP servers more efficiently.
Key concepts from the article:
- Progressive Disclosure: Present tools as a filesystem, load definitions on-demand
- Context-Efficient Results: Filter/transform data in code before returning to model
- Control Flow in Code: Loops, conditionals, error handling without agent loop overhead
- State Persistence: Save intermediate results, build reusable skills
Security Considerations
⚠️ Important security warnings:
- Unsandboxed code execution: The
execute_codetool runs arbitrary TypeScript code without sandboxing. Only use this in trusted environments. - Credential exposure: Server configurations in
mcp.jsonmay contain sensitive credentials in theenvfield. Protect this file appropriately. - Workspace directory: Contents of the
workspace/directory are accessible to executed code. Do not store sensitive data there.
Consider these risks when deploying Code Executor MCP, especially in shared or production environments.
Contributing
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
Acknowledgments
This project uses Context7 as the primary example MCP server for demonstrating the code execution pattern. Context7 provides up-to-date library documentation and code examples, making it an ideal candidate for showcasing how Code Executor MCP reduces token usage when fetching documentation.
The Context7 MCP server is bundled in mcps/context7-mcp/ and configured by default in mcp.json. See the Context7 usage skill for best practices on using it effectively.
Special thanks to:
- Anthropic for the code execution with MCP pattern that inspired this project
- Upstash for creating and maintaining the Context7 MCP server