MCP Server
The programmatic tools generated by Agent Codemode (from MCP Servers and Skills) can be exposed as an MCP Server for any MCP-compatible client.
This allows you to:
- Use Agent Codemode's code-first tool composition from any MCP client
- Build meta-agents that discover and compose tools programmatically
- Create a unified interface to multiple MCP servers through code execution
Quick Start
Launcher Script
Create a launcher script to configure which MCP servers to compose:
#!/usr/bin/env python3
import sys
from pathlib import Path
from agent_codemode import ToolRegistry, MCPServerConfig, CodeModeConfig
from agent_codemode.server import configure, run
# Create registry and add MCP servers to compose
registry = ToolRegistry()
registry.add_server(MCPServerConfig(
name="my_tools",
command=sys.executable,
args=["/path/to/my_mcp_server.py"]
))
# Configure paths
config = CodeModeConfig(
workspace_path="./workspace",
generated_path="./generated",
skills_path="./skills",
)
configure(config=config, registry=registry)
run()
Then configure your MCP client to run the launcher script.
Exposed Tools
The Codemode MCP Server exposes the following tools:
Tool Discovery
| Tool | Description |
|---|---|
search_tools | Progressive tool discovery with natural language queries |
list_servers | List all connected MCP servers |
get_tool_details | Get full schema for a specific tool |
Code Execution
| Tool | Description |
|---|---|
execute_code | Execute Python code that composes tools |
call_tool | Direct tool invocation (when allow_direct_tool_calls=True) |
Skills Management
| Tool | Description |
|---|---|
list_skills | List available saved skills |
save_skill | Save a new skill |
run_skill | Execute a saved skill |
delete_skill | Remove a skill |
Server Management
| Tool | Description |
|---|---|
add_mcp_server | Dynamically add new MCP servers |
get_execution_history | View recent execution history |
Tool Details
search_tools
Search for available tools from all connected MCP servers:
result = await client.call_tool("search_tools", {
"query": "file operations",
"limit": 10,
"include_deferred": True
})
# Returns: {"tools": [...], "total": 15, "has_more": True}
execute_code
Execute Python code that composes MCP tools:
result = await client.call_tool("execute_code", {
"code": """
import asyncio
from generated.servers.filesystem import read_file, write_file
# Read multiple files in parallel
files = ["/data/a.txt", "/data/b.txt", "/data/c.txt"]
contents = await asyncio.gather(*[read_file({"path": f}) for f in files])
# Process and write results
for i, content in enumerate(contents):
await write_file({
"path": f"/output/processed_{i}.txt",
"content": content.upper()
})
print(f"Processed {len(files)} files")
""",
"timeout": 30.0
})
# Returns: {"success": True, "result": "...", "stdout": "Processed 3 files", ...}
save_skill
Save a reusable skill:
result = await client.call_tool("save_skill", {
"name": "batch_uppercase",
"description": "Convert all files in a directory to uppercase",
"code": '''
async def batch_uppercase(input_dir, output_dir):
from generated.servers.filesystem import list_directory, read_file, write_file
entries = await list_directory({"path": input_dir})
for entry in entries["entries"]:
content = await read_file({"path": f"{input_dir}/{entry}"})
await write_file({"path": f"{output_dir}/{entry}", "content": content.upper()})
return {"processed": len(entries["entries"])}
''',
"tags": ["file", "batch", "text"]
})
run_skill
Execute a saved skill:
result = await client.call_tool("run_skill", {
"name": "batch_uppercase",
"arguments": {
"input_dir": "/data/input",
"output_dir": "/data/output"
}
})
Connecting Clients
Python MCP Client
from mcp import Client
client = Client()
await client.connect("stdio://python -m agent_codemode.server")
# Search for tools
tools = await client.call_tool("search_tools", {"query": "read files"})
# Execute code
result = await client.call_tool("execute_code", {
"code": """
from generated.servers.filesystem import read_file
content = await read_file({"path": "/data/config.json"})
print(content)
"""
})
Claude Desktop Configuration
Add to your Claude Desktop config:
{
"mcpServers": {
"codemode": {
"command": "python",
"args": ["-m", "agent_codemode.server"],
"env": {
"CODEMODE_WORKSPACE": "/workspace"
}
}
}
}
From Another MCP Server
You can chain MCP servers - have one MCP server use Codemode as a client:
from mcp import Client
# In your MCP server, connect to Codemode
codemode = Client()
await codemode.connect("stdio://python -m agent_codemode.server")
# Use Codemode's code execution from your server
result = await codemode.call_tool("execute_code", {"code": "..."})
Architecture
┌─────────────────────────────────────────────────────────────────────┐
│ MCP Client │
│ (Claude, custom agent, another MCP server) │
└────────────────────────────────┬────────────────────────────────────┘
│ MCP Protocol
▼
┌─────────────────────────────────────────────────────────────────────┐
│ Codemode MCP Server │
│ ┌───────── ─────┐ ┌─────────────┐ ┌────────────────────────────┐ │
│ │ search_tools │ │execute_code │ │ save_skill / run_skill │ │
│ │ list_servers │ │ call_tool │ │ list_skills / delete_skill │ │
│ └──────────────┘ └─────────────┘ └────────────────────────────┘ │
├─────────────────────────────────────────────────────────────────────┤
│ Tool Registry │
│ (discovers tools from connected MCP servers) │
├─────────────────────────────────────────────────────────────────────┤
│ Code Executor (Sandbox) │
│ (runs Python code with generated tool bindings) │
└────────────────────────────────┬────────────────────────────────────┘
│ MCP Protocol
▼
┌─────────────────────────────────────────────────────────────────────┐
│ Connected MCP Servers │
│ filesystem, github, slack, database, web, custom servers... │
└─────────────────────────────────────────────────────────────────────┘
Use Cases
1. Meta-Agent for Tool Composition
Build an agent that uses Codemode to intelligently compose tools:
User: "Analyze all Python files in /project and create a summary report"
Agent:
1. Calls search_tools("python file analysis")
2. Discovers filesystem and analysis tools
3. Writes code that reads files, analyzes them, generates report
4. Calls execute_code with the generated code
2. Unified Interface to Multiple Services
Combine multiple MCP servers into one code-first interface:
# Connect multiple specialized MCP servers
registry.add_server(MCPServerConfig(name="filesystem", ...))
registry.add_server(MCPServerConfig(name="github", ...))
registry.add_server(MCPServerConfig(name="slack", ...))
registry.add_server(MCPServerConfig(name="database", ...))
# Execute code that orchestrates all of them
await execute_code("""
# Read config, fetch from GitHub, query DB, notify Slack
config = await filesystem__read_file({"path": "/config.json"})
issues = await github__list_issues({"repo": "myorg/myrepo"})
users = await database__query({"sql": "SELECT * FROM users"})
await slack__send_message({"channel": "#updates", "text": f"Found {len(issues)} issues"})
""")
3. Building Reusable Workflows
Save complex multi-tool workflows as skills:
# Save a workflow as a skill
await save_skill({
"name": "deploy_and_notify",
"description": "Deploy to production and notify team",
"code": '''
async def deploy_and_notify(version):
await github__create_release({"tag": version})
await kubernetes__deploy({"image": f"myapp:{version}"})
await slack__send_message({"text": f"Deployed {version} 🚀"})
'''
})
# Later, run it
await run_skill({"name": "deploy_and_notify", "arguments": {"version": "1.2.3"}})
See Also
- MCP Tools - Generating tools from MCP Servers
- Skills - Generating tools from Skills
- Programmatic Tools - Executing generated tools
- Integrations - Using with Pydantic AI