Skip to main content

Overview

SuperBox uses AWS Lambda to execute MCP servers in completely isolated sandbox environments, ensuring security, scalability, and reliability.

Complete Isolation

Each execution runs in its own container

Resource Limits

CPU, memory, and time constraints

Network Control

Restricted network access

Auto-Scaling

Handles 1000+ concurrent executions

Sandbox Architecture

Lambda Execution Flow

1

Client Connection

AI client connects through local proxy:
# User runs: superbox pull weather-mcp --client cursor
# This configures cursor to use:
python -m superbox.aws.proxy --url wss://api-gateway-url?server_name=weather-mcp
2

WebSocket Communication

Proxy bridges stdio to WebSocket:
# Local proxy reads JSON-RPC from AI client stdin
message = await read_stdin()

# Forward to WebSocket API Gateway
await websocket.send(json.dumps(message))

# Lambda receives WebSocket message
# event = {'requestContext': {'connectionId': '...'},
#          'body': message}
3

Sandbox Bootstrap

Lambda initializes execution environment:
  1. Fetch server metadata from S3
  2. Clone GitHub repository to /tmp
  3. Install Python/Node.js dependencies
  4. Start MCP server process
  5. Forward JSON-RPC messages
4

Tool Execution

Execute requested tools through MCP protocol:
# Inside Lambda handler
async def handle_message(event, context):
    # Clone repo and start MCP server
    server_process = await clone_and_start_server(
        repo_url=metadata['repository']['url'],
        entrypoint=metadata['entrypoint']
    )
    
    # Forward JSON-RPC messages
    await forward_jsonrpc(server_process, event['body'])
5

Response Streaming

Return execution result:
{
  "result": {
    "content": [
      {
        "type": "text",
        "text": "Weather in San Francisco: 18°C, clear skies"
      }
    ]
  },
  "duration_ms": 245,
  "logs": [
    "INFO: Server initialized",
    "INFO: Executing tool get_weather",
    "INFO: API call successful"
  ]
}

Security Isolation

Container Isolation

Each Lambda function runs in an isolated container:
  • Separate file system
  • Independent process tree
  • Isolated network namespace
  • No cross-container access
Containers are destroyed after execution, leaving no traces

Lambda Handler Implementation

Python Handler

import json
import os
import sys
import tempfile
import traceback
from pathlib import Path
import boto3
import zipfile
import subprocess

s3_client = boto3.client('s3')
S3_BUCKET = os.environ['S3_BUCKET']

def handler(event, context):
  """
  Main Lambda handler for MCP server execution
  """
  try:
      # Parse request
      server_id = event['server_id']
      tool_name = event['tool_name']
      parameters = event.get('parameters', {})
      timeout = event.get('timeout', 30)

      # Setup execution environment
      server_path = setup_server(server_id)

      # Execute tool
      start_time = time.time()
      result = execute_mcp_tool(server_path, tool_name, parameters, timeout)
      duration_ms = int((time.time() - start_time) * 1000)

      return {
          'statusCode': 200,
          'body': json.dumps({
              'result': result,
              'duration_ms': duration_ms,
              'server_id': server_id,
              'tool_name': tool_name
          })
      }

  except TimeoutError as e:
      return {
          'statusCode': 408,
          'body': json.dumps({
              'error': 'Execution timeout',
              'message': str(e)
          })
      }

  except Exception as e:
      return {
          'statusCode': 500,
          'body': json.dumps({
              'error': type(e).__name__,
              'message': str(e),
              'traceback': traceback.format_exc()
          })
      }

def setup_server(server_id):
  """
  Download and setup MCP server from S3
  """
  # Download from S3
  local_zip = f'/tmp/{server_id}.zip'
  server_dir = f'/tmp/{server_id}'

  s3_key = f'servers/{server_id}/latest.zip'
  s3_client.download_file(S3_BUCKET, s3_key, local_zip)

  # Extract
  with zipfile.ZipFile(local_zip, 'r') as zip_ref:
      zip_ref.extractall(server_dir)

  # Install dependencies
  requirements_file = Path(server_dir) / 'requirements.txt'
  if requirements_file.exists():
      subprocess.run([
          sys.executable, '-m', 'pip', 'install',
          '-r', str(requirements_file),
          '-t', server_dir,
          '--quiet'
      ], check=True)

  return server_dir

def execute_mcp_tool(server_path, tool_name, parameters, timeout):
  """
  Execute MCP tool in subprocess with timeout
  """
  # Add server path to sys.path
  sys.path.insert(0, server_path)

  # Import and run server
  import asyncio
  from mcp_server import server

  async def run_tool():
      # Call tool
      result = await server.call_tool(
          name=tool_name,
          arguments=parameters
      )
      return result

  # Run with timeout
  loop = asyncio.get_event_loop()
  task = loop.create_task(run_tool())

  try:
      result = loop.run_until_complete(
          asyncio.wait_for(task, timeout=timeout)
      )
      return result
  except asyncio.TimeoutError:
      task.cancel()
      raise TimeoutError(f'Execution exceeded {timeout}s timeout')

Runtime Environment

Pre-installed packages:
boto3==1.34.0
botocore==1.34.0
urllib3==2.0.7
requests==2.31.0
certifi==2023.11.17
Custom packages installed per-execution from requirements.txt
Pre-installed packages:
{
  "dependencies": {
    "aws-sdk": "^2.1500.0",
    "@aws-sdk/client-s3": "^3.450.0"
  }
}
Custom packages from package.json installed during cold start
Available to MCP servers:
AWS_REGION=ap-south-1
AWS_EXECUTION_ENV=AWS_Lambda_python3.11 
LAMBDA_TASK_ROOT=/var/task
LAMBDA_RUNTIME_DIR=/var/runtime 
# Custom variables 
SERVER_ID=weather-mcp-123
SUPERBOX_ENV=production 
LOG_LEVEL=info
Shared dependencies via Lambda Layers:
  • MCP SDK Layer - Model Context Protocol SDK
  • Common Libraries Layer - httpx, aiohttp, etc.
  • ML Libraries Layer - numpy, pandas (optional)
/opt/python/lib/python3.11/site-packages/
├── mcp/
├── httpx/
├── aiohttp/
└── ...

Cold Start Optimization

Cold starts occur when Lambda creates a new container:
  • Container initialization: ~500ms
  • Runtime bootstrap: ~200ms
  • Dependency installation: ~2-5s
  • Total: 3-6 seconds
Cold starts impact user experience for first requests

Monitoring & Observability

CloudWatch Logs

All execution logs captured:
  • Server initialization
  • Tool invocations
  • Error stack traces
  • Performance metrics

CloudWatch Metrics

Lambda metrics: - Invocations - Duration - Errors - Throttles - Concurrent executions

X-Ray Tracing

Distributed tracing: - End-to-end latency - Service dependencies - Bottleneck identification

Custom Metrics

Business metrics:
  • Tool execution counts
  • Success/error rates
  • Average duration per tool

Example CloudWatch Dashboard

{
  "widgets": [
    {
      "type": "metric",
      "properties": {
        "metrics": [
          ["AWS/Lambda", "Invocations", { "stat": "Sum" }],
          [".", "Errors", { "stat": "Sum" }],
          [".", "Throttles", { "stat": "Sum" }]
        ],
        "period": 300,
        "stat": "Sum",
        "region": "us-east-1",
        "title": "Lambda Executions"
      }
    },
    {
      "type": "metric",
      "properties": {
        "metrics": [
          ["AWS/Lambda", "Duration", { "stat": "Average" }],
          ["...", { "stat": "p99" }]
        ],
        "period": 300,
        "region": "us-east-1",
        "title": "Execution Duration"
      }
    }
  ]
}

Cost Optimization

AWS Lambda pricing:
  • Requests: $0.20 per 1M requests
  • Duration: $0.0000166667 per GB-second
  • Free tier: 1M requests, 400,000 GB-seconds/month
Example cost calculation:
Monthly executions: 10,000,000
Average duration: 250ms
Memory: 1024 MB

Request cost: (10M - 1M) × $0.20 / 1M = $1.80
Duration cost: 10M × 0.25s × 1GB × $0.0000166667 = $41.67

Total: $43.47/month

Error Handling

Handle execution timeouts gracefully:
try:
    result = await asyncio.wait_for(
        execute_tool(tool_name, params),
        timeout=30
    )
except asyncio.TimeoutError:
    return {
        'statusCode': 408,
        'body': {
            'error': 'Execution timeout',
            'message': 'Tool execution exceeded 30s limit'
        }
    }
Monitor memory usage:
import psutil

def check_memory():
    process = psutil.Process()
    memory_mb = process.memory_info().rss / 1024 / 1024
    
    if memory_mb > 900:  # 1024 MB limit
        raise MemoryError(f'Memory usage: {memory_mb:.0f}MB')
Handle missing dependencies:
try:
    import required_package
except ImportError as e:
    return {
        'statusCode': 500,
        'body': {
            'error': 'Missing dependency',
            'message': str(e),
            'hint': 'Add package to requirements.txt'
        }
    }

Next Steps