MCP Server for Claude Desktop
The Model Context Protocol (MCP) server allows Claude Desktop to execute code directly through ERA Agent. Claude can write, test, and debug code in multiple languages using natural language.
Quick Start
Section titled “Quick Start”1. Build ERA Agent
Section titled “1. Build ERA Agent”cd era-agentgo build -o agent2. Get the Full Path
Section titled “2. Get the Full Path”pwdYour agent path: /Users/yourname/era-agent/agent
Important: You need the absolute path (starting with /), not a relative path.
3. Configure Claude Desktop
Section titled “3. Configure Claude Desktop”Open the config file:
code ~/Library/Application\ Support/Claude/claude_desktop_config.jsonAdd this configuration (update the path!):
{ "mcpServers": { "era-agent": { "command": "/Users/yourname/era-agent/agent", "args": ["mcp"], "env": { "AGENT_LOG_LEVEL": "info" } } }}Open the config file:
code ~/.config/Claude/claude_desktop_config.jsonAdd this configuration (update the path!):
{ "mcpServers": { "era-agent": { "command": "/home/yourname/era-agent/agent", "args": ["mcp"], "env": { "AGENT_LOG_LEVEL": "info" } } }}Open the config file:
notepad %APPDATA%\Claude\claude_desktop_config.jsonAdd this configuration (update the path!):
{ "mcpServers": { "era-agent": { "command": "C:\\Users\\yourname\\era-agent\\agent.exe", "args": ["mcp"], "env": { "AGENT_LOG_LEVEL": "info" } } }}4. Restart Claude Desktop
Section titled “4. Restart Claude Desktop”Completely quit Claude Desktop (not just close):
- macOS: Cmd+Q or Claude → Quit
- Linux: File → Quit
- Windows: File → Exit
Then restart Claude Desktop.
5. Test It
Section titled “5. Test It”Try these prompts in Claude Desktop:
Execute this Python code:print("Hello from ERA Agent!")print(f"2 + 2 = {2 + 2}")Claude should use the era_execute_code tool and show you the output.
Available Tools
Section titled “Available Tools”Once configured, Claude has access to 14 ERA Agent tools:
Language-Specific Quick Execution Tools
Section titled “Language-Specific Quick Execution Tools”These tools provide the easiest way to run code in a specific language without managing sessions:
era_python
Section titled “era_python”Execute Python code with a single command.
Claude Usage:
Run this Python FizzBuzz:for i in range(1, 16): if i % 15 == 0: print(f'{i}: FizzBuzz') elif i % 3 == 0: print(f'{i}: Fizz') elif i % 5 == 0: print(f'{i}: Buzz') else: print(f'{i}: {i}')Features:
- Automatic Python 3 execution
- Handles complex code (f-strings, loops, classes)
- Clean output capture
- No manual language specification needed
era_node
Section titled “era_node”Execute Node.js/JavaScript code.
Claude Usage:
Run this in Node.js:const data = [1, 2, 3, 4, 5];console.log('Sum:', data.reduce((a, b) => a + b));console.log('Average:', data.reduce((a, b) => a + b) / data.length);era_typescript
Section titled “era_typescript”Execute TypeScript with ts-node.
Claude Usage:
Run this TypeScript code:interface User { name: string; age: number;}
const user: User = { name: 'Alice', age: 30 };console.log(`${user.name} is ${user.age} years old`);Note: Requires ts-node in the VM environment.
era_deno
Section titled “era_deno”Execute code with Deno runtime.
Claude Usage:
Run this with Deno:const text = await Deno.readTextFile('/etc/hosts');console.log('First 5 lines:', text.split('\\n').slice(0, 5));Note: Requires Deno in the VM environment.
era_shell
Section titled “era_shell”Execute shell commands for system operations.
Claude Usage:
Run these shell commands:- Check Python version: python3 --version- Install packages: pip install pandas numpy- List directory: ls -laCommon Uses:
- Package installation:
pip install requests,npm install lodash - Environment setup:
apt-get update && apt-get install -y git - File operations:
mkdir data && cd data && wget [url] - System info:
uname -a,df -h,free -m
Security Note: Shell commands run with the same isolation as code execution.
Core Execution Tools
Section titled “Core Execution Tools”1. era_execute_code
Section titled “1. era_execute_code”Execute code in an ephemeral sandbox.
Claude Usage:
Execute this Python code:import mathprint(f"π ≈ {math.pi:.5f}")What It Does:
- Creates temporary VM
- Executes code
- Returns output
- Cleans up automatically
2. era_create_session
Section titled “2. era_create_session”Create a persistent execution environment.
Claude Usage:
Create a Python session with 2 CPUs and 512MB memoryWhat It Does:
- Creates named session
- Configures resources
- Returns session ID
- State persists between runs
3. era_run_in_session
Section titled “3. era_run_in_session”Execute code in an existing session.
Claude Usage:
In session abc-123, run:counter = 0print(f"Counter: {counter}")
Then run:counter += 1print(f"Counter: {counter}")What It Does:
- Executes in existing VM
- Maintains state/variables
- Faster than new VM each time
4. era_list_sessions
Section titled “4. era_list_sessions”List all active sessions.
Claude Usage:
Show me all ERA Agent sessions5. era_get_session
Section titled “5. era_get_session”Get session details.
Claude Usage:
What's the status of session abc-123?6. era_delete_session
Section titled “6. era_delete_session”Delete a session.
Claude Usage:
Delete session abc-1237. era_upload_file
Section titled “7. era_upload_file”Upload a file to session workspace.
Claude Usage:
Upload a file called data.csv to session abc-123 with this content:name,ageAlice,30Bob,258. era_read_file
Section titled “8. era_read_file”Read a file from session workspace.
Claude Usage:
Read the output.txt file from session abc-1239. era_list_files
Section titled “9. era_list_files”List files in session workspace.
Claude Usage:
What files are in session abc-123?Example Workflows
Section titled “Example Workflows”Quick Python Execution
Section titled “Quick Python Execution”You: “Run this Python code: print([x**2 for x in range(10)])”
Claude: Uses era_python (automatically)
Result:
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]Why it works: Language-specific tool makes execution straightforward.
FizzBuzz with Logging
Section titled “FizzBuzz with Logging”You: “Write a FizzBuzz in Python and log each step”
Claude: Uses era_python with:
print("Starting FizzBuzz for numbers 1 to 15")print()
for i in range(1, 16): if i % 15 == 0: print(f'{i}: FizzBuzz') elif i % 3 == 0: print(f'{i}: Fizz') elif i % 5 == 0: print(f'{i}: Buzz') else: print(f'{i}: {i}')
print()print('FizzBuzz complete!')Result: Full output with logging at each step.
Installing Packages
Section titled “Installing Packages”You: “Create a Python session, install pandas, and analyze some data”
Claude:
- Uses
era_create_session→ Gets session ID (e.g.,abc-123) - Uses
era_shellwith session:pip install pandas - Uses
era_run_in_session:import pandas as pddata = {'name': ['Alice', 'Bob'], 'age': [30, 25]}df = pd.DataFrame(data)print(df.describe())
Result: Statistics on the data.
Data Processing Pipeline
Section titled “Data Processing Pipeline”You: “Create a Python session, upload this CSV, and analyze it”
Claude:
- Uses
era_create_session - Uses
era_upload_filewith CSV data - Uses
era_shell:pip install pandas - Uses
era_run_in_session:import pandas as pddf = pd.read_csv('data.csv')print(df.describe())df['processed'] = df['value'] * 2df.to_csv('output.csv', index=False) - Uses
era_read_fileto readoutput.csv
Result: Processed data returned.
Multi-Language Testing
Section titled “Multi-Language Testing”You: “Test this algorithm in Python and Node.js”
Claude:
-
Uses
era_python:def quicksort(arr):if len(arr) <= 1:return arrpivot = arr[len(arr) // 2]left = [x for x in arr if x < pivot]middle = [x for x in arr if x == pivot]right = [x for x in arr if x > pivot]return quicksort(left) + middle + quicksort(right)print(quicksort([3,6,8,10,1,2,1])) -
Uses
era_node:function quicksort(arr) {if (arr.length <= 1) return arr;const pivot = arr[Math.floor(arr.length / 2)];const left = arr.filter(x => x < pivot);const middle = arr.filter(x => x === pivot);const right = arr.filter(x => x > pivot);return [...quicksort(left), ...middle, ...quicksort(right)];}console.log(quicksort([3,6,8,10,1,2,1])); -
Compares results
Result: Both implementations produce [1, 1, 2, 3, 6, 8, 10]
TypeScript with Type Checking
Section titled “TypeScript with Type Checking”You: “Test this TypeScript interface”
Claude: Uses era_typescript:
interface User { name: string; age: number; email?: string;}
const user: User = { name: 'Alice', age: 30};
console.log(`User: ${user.name}, Age: ${user.age}`);
// Type error would be caught:// const badUser: User = { name: 'Bob' }; // Missing 'age'Result: Type-safe execution with TypeScript compiler.
Web Scraping with Packages
Section titled “Web Scraping with Packages”You: “Scrape the top stories from Hacker News”
Claude:
- Uses
era_create_sessionwith network access - Uses
era_shell:pip install requests beautifulsoup4 - Uses
era_run_in_session:import requestsfrom bs4 import BeautifulSoupresponse = requests.get('https://news.ycombinator.com')soup = BeautifulSoup(response.text, 'html.parser')stories = soup.find_all('span', class_='titleline')for i, story in enumerate(stories[:5], 1):print(f"{i}. {story.get_text()}")
Result: Top 5 Hacker News stories.
Configuration Options
Section titled “Configuration Options”Basic Configuration
Section titled “Basic Configuration”Minimal setup:
{ "mcpServers": { "era-agent": { "command": "/path/to/agent", "args": ["mcp"] } }}With Logging
Section titled “With Logging”Enable debug logs:
{ "mcpServers": { "era-agent": { "command": "/path/to/agent", "args": ["mcp"], "env": { "AGENT_LOG_LEVEL": "debug" } } }}Custom State Directory
Section titled “Custom State Directory”Store sessions in custom location:
{ "mcpServers": { "era-agent": { "command": "/path/to/agent", "args": ["mcp"], "env": { "AGENT_STATE_DIR": "/custom/path/to/state", "AGENT_LOG_LEVEL": "info" } } }}Multiple Instances
Section titled “Multiple Instances”Run multiple ERA Agent configurations:
{ "mcpServers": { "era-agent-default": { "command": "/path/to/agent", "args": ["mcp"] }, "era-agent-debug": { "command": "/path/to/agent", "args": ["mcp"], "env": { "AGENT_LOG_LEVEL": "debug" } } }}Troubleshooting
Section titled “Troubleshooting”Claude Doesn’t Show ERA Tools
Section titled “Claude Doesn’t Show ERA Tools”Problem: Configuration not loaded or server failed to start.
Solutions:
-
Check config file syntax:
Terminal window # Validate JSONcat ~/Library/Application\ Support/Claude/claude_desktop_config.json | jq '.' -
Verify agent path:
Terminal window # Test the path/your/path/to/agent --help -
Check permissions:
Terminal window chmod +x /path/to/agent -
Restart Claude Desktop completely (Cmd+Q, not just close window)
-
Check logs:
Terminal window # macOStail -f ~/Library/Logs/Claude/mcp*.log# Linuxtail -f ~/.config/Claude/logs/mcp*.log
Code Execution Fails
Section titled “Code Execution Fails”Problem: VM service error or Docker/Firecracker not running.
Solutions:
- Open Docker Desktop
- Verify Docker is running:
Terminal window docker ps - Restart Claude Desktop
-
Check Firecracker:
Terminal window which firecracker -
Verify KVM access:
Terminal window ls -l /dev/kvm -
Add user to kvm group:
Terminal window sudo usermod -aG kvm $USER# Log out and back in
Timeout Errors
Section titled “Timeout Errors”Problem: Code takes too long to execute.
Solution: Ask Claude to increase timeout:
Execute this code with a 60 second timeout:[long-running code]Or create session with higher default:
Create a Python session with a 120 second default timeout“Command not found”
Section titled ““Command not found””Problem: Incorrect agent path in config.
Solutions:
-
Use absolute path (starting with
/):"command": "/Users/name/era-agent/agent" // ✅ Good"command": "~/era-agent/agent" // ❌ Bad"command": "./agent" // ❌ Bad -
Verify path exists:
Terminal window ls -l /your/path/to/agent
Agent Works in Terminal, Not in Claude
Section titled “Agent Works in Terminal, Not in Claude”Problem: Environment variables or PATH not set.
Solution: Add environment variables to config:
{ "mcpServers": { "era-agent": { "command": "/path/to/agent", "args": ["mcp"], "env": { "AGENT_LOG_LEVEL": "info", "PATH": "/usr/local/bin:/usr/bin:/bin", "HOME": "/Users/yourname" } } }}Historical Issues (Now Fixed)
Section titled “Historical Issues (Now Fixed)”“Shell Escaping Errors” (Fixed in Latest Version)
Section titled ““Shell Escaping Errors” (Fixed in Latest Version)”Previous Problem: Python code with f-strings or complex syntax failed with errors like:
sh: -c: line 0: syntax error near unexpected token '('nprint("Starting...") # Literal 'n' instead of newlineCause: Double-escaping bug—JSON newlines were being escaped twice by shell commands.
Fix: Code is now written directly to files using os.WriteFile() in Go, completely bypassing shell escaping. Update to the latest version if you’re experiencing this.
How to Check: Run FizzBuzz with f-strings. If it works, you have the fix:
for i in range(1, 16): print(f'{i}: FizzBuzz' if i % 15 == 0 else f'{i}: Fizz' if i % 3 == 0 else i)Code Execution Gotchas & Best Practices
Section titled “Code Execution Gotchas & Best Practices”✅ What Works Well
Section titled “✅ What Works Well”Complex Python Code
Section titled “Complex Python Code”The system handles complex Python features correctly:
# F-strings, loops, and formatting all work perfectlyfor i in range(1, 16): if i % 15 == 0: print(f'{i}: FizzBuzz') elif i % 3 == 0: print(f'{i}: Fizz')Why it works: Code is written directly to files by the Go process, bypassing all shell escaping issues.
Multi-line Code
Section titled “Multi-line Code”Newlines and indentation are preserved exactly:
def factorial(n): """Calculate factorial recursively""" if n <= 1: return 1 return n * factorial(n - 1)
print(f"10! = {factorial(10)}")Special Characters
Section titled “Special Characters”Single quotes, double quotes, backticks, and other special characters work:
const message = `He said, "It's working!"`;console.log(message);⚠️ Common Pitfalls
Section titled “⚠️ Common Pitfalls”Pitfall 1: Using era_execute_code Without Language
Section titled “Pitfall 1: Using era_execute_code Without Language”Problem:
Execute this code: print("Hello")Claude might not know which language to use.
Solution: Use language-specific tools:
Use era_python to run: print("Hello")Or be explicit:
Execute this Python code: print("Hello")Pitfall 2: Installing Packages Mid-Session
Section titled “Pitfall 2: Installing Packages Mid-Session”Problem:
# This will fail if pandas isn't installedimport pandas as pddf = pd.read_csv('data.csv')Solution: Install packages first with era_shell:
1. Create a Python session2. Use era_shell: pip install pandas3. Then run your pandas codeOr create session with packages parameter:
Create a Python session and install pandas and numpyPitfall 3: Assuming Persistent State in Ephemeral Execution
Section titled “Pitfall 3: Assuming Persistent State in Ephemeral Execution”Problem:
Run: x = 42Then run: print(x) # This will fail!Solution: Use sessions for stateful execution:
1. Create a Python session (remember the ID)2. In that session, run: x = 423. In that same session, run: print(x) # ✅ Works!Pitfall 4: File Paths Outside Session
Section titled “Pitfall 4: File Paths Outside Session”Problem:
# This might failwith open('/home/user/myfile.txt') as f: data = f.read()Solution: Use session workspace:
1. Upload file to session: era_upload_file2. Use relative path: with open('myfile.txt') as f:🔧 Technical Details: How Code Execution Works
Section titled “🔧 Technical Details: How Code Execution Works”Understanding the internals helps debug issues:
Execution Flow
Section titled “Execution Flow”- Code Submission: Claude sends code to ERA Agent via MCP
- File Writing: ERA Agent writes code directly to a file (e.g.,
era_script_123456789.py) - VM Setup: Creates or uses existing VM with proper runtime
- Command Execution: Runs simple command (e.g.,
python3 era_script_123456789.py) - Output Capture: Stdout and stderr captured to files
- Result Return: Output returned to Claude via MCP
Key Insight: No shell escaping is involved—files are written directly from Go using os.WriteFile(). This is why complex code with special characters works reliably.
Why This Approach?
Section titled “Why This Approach?”Previous Approach (Had Issues):
# Used heredoc with shell escaping - caused double-escapingcat > script.py << 'EOF'print("Hello")EOFpython3 script.pyProblem: JSON newlines (\n) → Go unescapes → Shell %q re-escapes → Syntax errors
Current Approach (Fixed):
// Write file directly in Goos.WriteFile("/vm/workdir/era_script_123.py", []byte(code), 0644)// Execute simple commandexec.Command("python3", "era_script_123.py")Result: No escaping issues, all special characters preserved.
📋 Shell Execution Best Practices
Section titled “📋 Shell Execution Best Practices”Use era_shell for System Operations
Section titled “Use era_shell for System Operations”Good Use Cases:
# Package managementpip install requests beautifulsoup4npm install lodash axios
# Environment setupapt-get update && apt-get install -y postgresql-client
# File operationsmkdir -p data/processedwget https://example.com/data.csv -O data/input.csv
# System informationpython3 --versionnode --versiondf -hWhat NOT to Use era_shell For:
- Running Python/JavaScript code (use
era_python,era_nodeinstead) - Complex multi-line scripts (create a file and execute it)
Chaining Commands
Section titled “Chaining Commands”Good:
# Use && for dependent commandspip install pandas && python -c "import pandas; print(pandas.__version__)"Bad:
# Don't rely on shell state between callscd /some/dirls # Won't be in /some/dir anymore!Environment Variables
Section titled “Environment Variables”Set them in the command:
PYTHONPATH=/custom/path python3 script.pyOr use session environment:
Create a Python session with environment variable PYTHONPATH=/custom/path🎯 Performance Optimization
Section titled “🎯 Performance Optimization”Choose the Right Tool
Section titled “Choose the Right Tool”| Scenario | Tool | Reason |
|---|---|---|
| Single Python script | era_python | Fast, no session overhead |
| Multiple related runs | Session + era_run_in_session | VM reuse, state persistence |
| Package installation | era_shell | System-level operations |
| Quick calculation | era_python / era_node | Minimal setup |
| Long-running task | Session with higher timeout | Configurable limits |
Session vs Ephemeral
Section titled “Session vs Ephemeral”Use Ephemeral (era_python, etc.) when:
- Single, independent execution
- No package installation needed
- Quick tests or calculations
Use Sessions when:
- Multiple related operations
- Installing packages
- Building on previous state
- Large data loading (load once, use multiple times)
🛡️ Security Considerations
Section titled “🛡️ Security Considerations”Network Isolation
Section titled “Network Isolation”By default, network is disabled:
import requestsrequests.get('https://example.com') # Will fail!Enable when needed:
Create a Python session with network accessOnly enable network for:
- API calls
- Package downloads
- Web scraping
- External data fetching
File System Isolation
Section titled “File System Isolation”Each session has isolated filesystem:
- Session A cannot access Session B’s files
- Ephemeral VMs cleaned up after execution
- No access to host filesystem
Resource Limits
Section titled “Resource Limits”Default limits prevent resource exhaustion:
- CPU: 1 core (prevents runaway processes)
- Memory: 256 MiB (prevents OOM)
- Timeout: 30 seconds (prevents infinite loops)
Request higher limits when needed:
Create a Python session with 4 CPUs, 2GB memory, and 120 second timeoutUsage Tips
Section titled “Usage Tips”Effective Prompts
Section titled “Effective Prompts”Good Prompts:
"Execute this Python code: print('Hello')""Create a Node.js session with network access""In session abc-123, run: x = 42""List all active sessions"Less Effective:
"Can you run code?" (too vague)"Execute: print(x)" (no context about language or session)Working with Sessions
Section titled “Working with Sessions”Create once, use multiple times:
1. "Create a Python session"2. "In that session, import pandas and load data.csv"3. "Now calculate the mean of column 'age'"4. "Create a visualization and save it"5. "Read the output file"File Operations
Section titled “File Operations”Upload, process, read:
1. "Create a Python session"2. "Upload requirements.txt with content: pandas numpy"3. "Install the requirements"4. "Upload data.csv with [data]"5. "Process the data and save results"6. "Read the results file"Security
Section titled “Security”Isolation
Section titled “Isolation”- All code runs in isolated Firecracker VMs
- Network access disabled by default
- Filesystem isolation per session
- Resource limits enforced
Network Access
Section titled “Network Access”Network is disabled by default. Enable only when needed:
Create a Python session with network access enabledClaude will use network_mode: "allow_all".
State Storage
Section titled “State Storage”Sessions stored locally:
- macOS:
~/Library/Application Support/era-agent - Linux:
~/.local/share/era-agent - Custom: Set
AGENT_STATE_DIR
Data never leaves your machine.
Performance
Section titled “Performance”VM Startup
Section titled “VM Startup”First execution in a session is slower (VM startup):
- First run: ~2-3 seconds
- Subsequent runs: ~0.5-1 second
Tip: Use persistent sessions for multiple operations.
Resource Limits
Section titled “Resource Limits”Default limits:
- CPU: 1 core
- Memory: 256 MiB
- Timeout: 30 seconds
Request higher resources when needed:
Create a Python session with 4 CPUs and 2GB memoryWhat Claude Can Build
Section titled “What Claude Can Build”With ERA Agent, Claude can:
Data Analysis
Section titled “Data Analysis”"Analyze this CSV data and create summary statistics"API Integration
Section titled “API Integration”"Create a Python session with network access, fetch data from this API, and process it"Multi-File Projects
Section titled “Multi-File Projects”"Create a Node.js project with multiple files, install dependencies, and run tests"Algorithm Development
Section titled “Algorithm Development”"Implement quicksort in Python, test it with random data, and measure performance"Web Scraping
Section titled “Web Scraping”"Create a Python session, install BeautifulSoup, scrape this URL, and extract data"Code Testing
Section titled “Code Testing”"Test this function with various inputs and edge cases"Next Steps
Section titled “Next Steps”- Try Example Prompts: Test the workflows above
- Explore Languages: Python, Node.js, TypeScript, Go, Deno
- Read API Docs: API Reference
- CLI Usage: Command Line Guide
- HTTP Server: Self-Hosted API