Skip to content

Latest commit

 

History

History
797 lines (611 loc) · 15.4 KB

File metadata and controls

797 lines (611 loc) · 15.4 KB

JavaScript Code Execution - Troubleshooting

Common issues, error messages, and solutions for the code_execution tool.

Table of Contents

  1. Configuration Issues
  2. Syntax Errors
  3. Runtime Errors
  4. Timeout Issues
  5. Tool Call Errors
  6. Serialization Errors
  7. Performance Issues
  8. Debugging Tips

Configuration Issues

Error: "code_execution is disabled in configuration"

Symptom:

Error: code_execution is disabled in configuration. Set 'enable_code_execution: true' in config file.

Cause: The code_execution feature is disabled by default for security.

Solution:

  1. Edit your configuration file (~/.mcpproxy/mcp_config.json)
  2. Add or update: "enable_code_execution": true
  3. Restart mcpproxy: pkill mcpproxy && mcpproxy serve

Example Configuration:

{
  "enable_code_execution": true,
  "code_execution_timeout_ms": 120000,
  "code_execution_max_tool_calls": 0,
  "code_execution_pool_size": 10,
  "mcpServers": [...]
}

Error: "code_execution tool not found in tools list"

Symptom: LLM agent lists available tools but code_execution is missing.

Cause: Feature is not enabled or server didn't restart after configuration change.

Solution:

  1. Verify configuration has "enable_code_execution": true
  2. Restart mcpproxy server
  3. Reconnect LLM client
  4. List tools again

Verification:

# Check if code_execution tool is registered
mcpproxy call tool --tool-name=retrieve_tools --json_args='{"query":"code execution"}'

Error: "timeout must be between 1 and 600000 milliseconds"

Symptom:

{
  "ok": false,
  "error": {
    "message": "timeout_ms must be between 1 and 600000 milliseconds"
  }
}

Cause: Invalid timeout_ms value in request options.

Solution: Use a timeout between 1ms and 600000ms (10 minutes):

{
  "code": "...",
  "options": {
    "timeout_ms": 120000  // 2 minutes (valid)
  }
}

Syntax Errors

Error: "SyntaxError: Unexpected token"

Symptom:

{
  "ok": false,
  "error": {
    "code": "SYNTAX_ERROR",
    "message": "SyntaxError: Unexpected token '{'",
    "stack": ""
  }
}

Common Causes:

  1. Missing closing brackets/braces
  2. Invalid JavaScript syntax

Solutions:

Problem: Missing brackets

// Bad
const x = { value: 1, missing: 2

// Good
const x = { value: 1, missing: 2 };

Problem: Incomplete expressions

// Bad
const msg = `Hello, ${

// Good
const msg = `Hello, ${name}!`;

Error: "SyntaxError: Unexpected end of input"

Symptom: Code execution fails with "end of input" error.

Cause: Incomplete JavaScript expression or statement.

Solution: Ensure all blocks are properly closed:

// Bad
var x = function() {
  return 42;
// Missing closing brace

// Good
var x = function() {
  return 42;
};

Runtime Errors

Error: "TypeError: Cannot read property 'X' of undefined/null"

Symptom:

{
  "ok": false,
  "error": {
    "code": "RUNTIME_ERROR",
    "message": "TypeError: Cannot read property 'name' of undefined",
    "stack": "..."
  }
}

Cause: Accessing properties on undefined or null values.

Solution: Always check values before accessing properties:

// Bad
var name = input.user.name;  // Crashes if input.user is undefined

// Good
var name = input.user ? input.user.name : 'Unknown';

// Better
var name = 'Unknown';
if (input && input.user && input.user.name) {
  name = input.user.name;
}

For Tool Calls:

// Bad
var user = call_tool('github', 'get_user', {username: input.username});
var name = user.result.name;  // Crashes if user.ok is false

// Good
var user = call_tool('github', 'get_user', {username: input.username});
if (!user.ok) {
  return {error: user.error.message};
}
var name = user.result.name;

Error: "ReferenceError: X is not defined"

Symptom:

{
  "ok": false,
  "error": {
    "code": "RUNTIME_ERROR",
    "message": "ReferenceError: myVariable is not defined",
    "stack": "..."
  }
}

Cause: Using variables or functions that don't exist.

Common Mistakes:

Problem: Undefined variables

// Bad
return result;  // 'result' was never declared

// Good
var result = 42;
return result;

Problem: Using unavailable functions

// Bad
var data = require('fs').readFileSync('file.txt');  // require() not available

// Bad
setTimeout(function() { doWork(); }, 1000);  // setTimeout() not available

// Good
var data = call_tool('filesystem', 'read_file', {path: 'file.txt'});

Error: "RangeError: Maximum call stack size exceeded"

Symptom: Execution fails with stack overflow.

Cause: Infinite recursion or very deep recursion.

Solution: Check for infinite loops or recursive calls:

// Bad
function factorial(n) {
  return n * factorial(n - 1);  // No base case!
}

// Good
function factorial(n) {
  if (n <= 1) return 1;  // Base case
  return n * factorial(n - 1);
}

// Better (iterative)
function factorial(n) {
  var result = 1;
  for (var i = 2; i <= n; i++) {
    result *= i;
  }
  return result;
}

Timeout Issues

Error: "JavaScript execution timed out"

Symptom:

{
  "ok": false,
  "error": {
    "code": "TIMEOUT",
    "message": "JavaScript execution timed out",
    "stack": ""
  }
}

Common Causes:

  1. Infinite loops
  2. Too many tool calls
  3. Slow upstream servers
  4. Heavy computation

Solutions:

Problem: Infinite loop

// Bad
while (true) {
  // This will timeout
}

// Bad
for (var i = 0; i < 1000000000; i++) {
  // This takes too long
}

// Good
for (var i = 0; i < input.items.length; i++) {
  // Bounded loop
}

Problem: Insufficient timeout for workload

// Bad: Default 2-minute timeout for 100 tool calls
{
  "code": "for(var i=0;i<100;i++){call_tool(...)}",
  "options": {"timeout_ms": 120000}  // Might not be enough
}

// Good: Increase timeout for heavy workloads
{
  "code": "for(var i=0;i<100;i++){call_tool(...)}",
  "options": {"timeout_ms": 300000}  // 5 minutes
}

Problem: Slow upstream tools

// Solution: Reduce number of calls or increase timeout
{
  "code": "...",
  "options": {
    "timeout_ms": 300000,      // Increase timeout
    "max_tool_calls": 50       // Limit calls to prevent runaway
  }
}

Tool Call Errors

Error: "Exceeded maximum tool calls limit"

Symptom:

{
  "ok": false,
  "error": {
    "code": "MAX_TOOL_CALLS_EXCEEDED",
    "message": "Exceeded maximum tool calls limit (10)",
    "stack": ""
  }
}

Cause: Code called call_tool() more times than max_tool_calls allows.

Solution:

Option 1: Increase limit

{
  "code": "for(var i=0;i<20;i++){call_tool(...)}",
  "options": {"max_tool_calls": 25}  // Set higher than needed
}

Option 2: Reduce tool calls

// Bad: Call tool for every item
for (var i = 0; i < 1000; i++) {
  call_tool('api', 'process', {id: items[i]});
}

// Good: Batch items if tool supports it
var batchSize = 100;
for (var i = 0; i < items.length; i += batchSize) {
  var batch = items.slice(i, i + batchSize);
  call_tool('api', 'process_batch', {items: batch});
}

Error: "Server 'X' is not in the allowed servers list"

Symptom:

{
  "ok": false,
  "error": {
    "code": "SERVER_NOT_ALLOWED",
    "message": "Server 'gitlab' is not in the allowed servers list",
    "stack": ""
  }
}

Cause: Attempted to call a server not in allowed_servers option.

Solution:

Option 1: Add server to allowed list

{
  "code": "call_tool('gitlab', 'get_user', {username: 'test'})",
  "options": {
    "allowed_servers": ["github", "gitlab"]  // Add gitlab
  }
}

Option 2: Remove restriction (allow all servers)

{
  "code": "call_tool('gitlab', 'get_user', {username: 'test'})",
  "options": {
    "allowed_servers": []  // Empty array = all servers allowed
  }
}

Error: "server not found: X"

Symptom: call_tool() returns error saying server doesn't exist.

Cause: Server name is incorrect or server is not configured.

Solution:

  1. Check server name: Verify spelling and case
// Bad
call_tool('GitHub', 'get_user', {});  // Wrong case

// Good
call_tool('github', 'get_user', {});  // Correct name
  1. List available servers:
mcpproxy call tool --tool-name=upstream_servers --json_args='{"operation":"list"}'
  1. Add server if missing:
mcpproxy call tool --tool-name=upstream_servers \
  --json_args='{"operation":"add","name":"github","url":"https://api.github.com/mcp","protocol":"http","enabled":true}'

Serialization Errors

Error: "Result contains non-JSON-serializable values"

Symptom:

{
  "ok": false,
  "error": {
    "code": "SERIALIZATION_ERROR",
    "message": "Result contains non-JSON-serializable values (functions, circular references, etc.)",
    "stack": ""
  }
}

Cause: JavaScript return value contains functions, circular references, or other non-JSON types.

Solutions:

Problem: Returning functions

// Bad
return {
  calculate: function() { return 42; }
};

// Good
return {
  result: 42
};

Problem: Returning undefined

// Bad
return undefined;  // Not JSON-serializable

// Good
return null;  // JSON-serializable

Problem: Circular references

// Bad
var obj = {value: 42};
obj.self = obj;  // Circular reference
return obj;

// Good
return {value: 42};

Problem: Special objects (Date, RegExp)

// Bad
return {
  created: new Date()  // Date object not JSON-serializable
};

// Good
return {
  created: new Date().toISOString()  // String is JSON-serializable
};

Performance Issues

Issue: Slow execution times

Symptom: Code takes longer than expected to execute.

Diagnosis:

  1. Check number of tool calls
  2. Measure upstream tool latency
  3. Look for inefficient loops
  4. Check for excessive data processing

Solutions:

Reduce tool calls:

// Bad: N tool calls
for (var i = 0; i < items.length; i++) {
  call_tool('api', 'get', {id: items[i]});
}

// Good: 1 batch tool call
call_tool('api', 'get_batch', {ids: items});

Cache repeated calls:

// Bad: Call same tool multiple times
for (var i = 0; i < items.length; i++) {
  var config = call_tool('api', 'get_config', {});  // Repeated call
  process(items[i], config);
}

// Good: Call once, reuse result
var config = call_tool('api', 'get_config', {});
if (!config.ok) return config;

for (var i = 0; i < items.length; i++) {
  process(items[i], config.result);
}

Optimize loops:

// Bad: Inefficient nested loops
for (var i = 0; i < arr1.length; i++) {
  for (var j = 0; j < arr2.length; j++) {
    if (arr1[i] === arr2[j]) {
      results.push(arr1[i]);
    }
  }
}

// Good: Use object for O(1) lookup
var set = {};
for (var i = 0; i < arr2.length; i++) {
  set[arr2[i]] = true;
}
for (var i = 0; i < arr1.length; i++) {
  if (set[arr1[i]]) {
    results.push(arr1[i]);
  }
}

Issue: Pool exhaustion (all VMs busy)

Symptom: Requests take longer to start, or you see "waiting for VM" logs.

Cause: More concurrent executions than pool size allows.

Solution: Increase pool size in configuration:

{
  "code_execution_pool_size": 20  // Increase from default 10
}

Trade-offs:

  • Larger pool = more concurrency, more memory usage
  • Smaller pool = less concurrency, less memory usage

Recommendation: Monitor pool usage and adjust based on load.


Debugging Tips

Enable Debug Logging

CLI:

mcpproxy code exec --code="..." --log-level=debug

Server: Edit config to set log level:

{
  "log_level": "debug"
}

What you'll see:

  • Tool call details (server, tool name, arguments)
  • Execution timing
  • Pool acquisition/release
  • Detailed error messages

Use console.log() for Debugging

var user = call_tool('github', 'get_user', {username: input.username});
console.log('User response:', JSON.stringify(user));  // Logs to server logs

if (!user.ok) {
  console.log('Error occurred:', user.error);
  return {error: user.error.message};
}

console.log('User name:', user.result.name);
return {name: user.result.name};

Where to find logs: ~/.mcpproxy/logs/main.log (or platform-specific log directory)


Test Code Incrementally

Start simple and build up:

// Step 1: Verify input access
return input;

// Step 2: Test tool call
var res = call_tool('github', 'get_user', {username: 'octocat'});
return res;

// Step 3: Add error handling
var res = call_tool('github', 'get_user', {username: 'octocat'});
if (!res.ok) return {error: res.error.message};
return res.result;

// Step 4: Add data transformation
var res = call_tool('github', 'get_user', {username: 'octocat'});
if (!res.ok) return {error: res.error.message};
return {
  name: res.result.name,
  repos: res.result.public_repos
};

Validate JSON Serialization

Test that your return value is JSON-serializable:

var result = {/* your data */};

// This will throw if result is not serializable
var json = JSON.stringify(result);

// If it succeeds, return it
return result;

Use Error Boundaries

Wrap risky operations in try-catch or use checks:

// Check before accessing
if (res && res.ok && res.result && res.result.name) {
  return {name: res.result.name};
} else {
  return {error: 'Invalid response structure'};
}

// For loops, check each iteration
for (var i = 0; i < items.length; i++) {
  if (!items[i]) {
    console.log('Skipping null item at index', i);
    continue;
  }
  // Process items[i]
}

Reproduce Issues Locally

Use the CLI to reproduce issues quickly:

# Save problematic code to file
cat > /tmp/debug.js << 'EOF'
var user = call_tool('github', 'get_user', {username: input.username});
console.log('Response:', JSON.stringify(user));
return user;
EOF

# Run with debug logging
mcpproxy code exec \
  --file=/tmp/debug.js \
  --input='{"username":"octocat"}' \
  --log-level=debug

Getting Help

If you're still stuck after trying these solutions:

  1. Check the examples: examples.md has 10+ working patterns
  2. Review API reference: api-reference.md has complete schema
  3. Read the overview: overview.md explains architecture
  4. Check server logs: ~/.mcpproxy/logs/main.log for detailed error messages
  5. File an issue: GitHub Issues

What to Include in Bug Reports

**Environment**:
- MCPProxy version: (run `mcpproxy --version`)
- OS: (macOS/Linux/Windows)
- Configuration: (relevant config fields)

**Code**:
```javascript
// Your JavaScript code here

Input:

{
  "input": {...}
}

Expected: What you expected to happen

Actual: What actually happened (include full error message)

Logs: Relevant lines from ~/.mcpproxy/logs/main.log


---

## Next Steps

- **Examples**: See [examples.md](examples.md) for working code samples
- **API Reference**: See [api-reference.md](api-reference.md) for complete schema
- **Overview**: See [overview.md](overview.md) for architecture and best practices