Agent Sandbox Registry

agent-sandbox

MCP Server Design

docs/en/design/mcp-server.md

MCP Server Design

Agent Sandbox MCP Server exposes sandbox capabilities as MCP (Model Context Protocol) Tools, allowing AI Agents (Cursor, Claude Desktop, VS Code, etc.) to directly operate cloud sandboxes.

Implemented surface (kept in sync with src/agent/):


1. Tools Definition

All 7 tools are defined in TOOL_SCHEMAS (agent/tools.ts). Omitting sandbox_id targets the default sandbox (see Section 2).

create_sandbox

{
  "name": "create_sandbox",
  "description": "Create a cloud sandbox and make it the session default. When template is omitted, use the MCP server's configured template (code-interpreter-v1 for abx mcp start).",
  "inputSchema": {
    "type": "object",
    "properties": {
      "template": {
        "type": "string",
        "description": "Sandbox template name; omitted means the server template"
      },
      "timeout": {
        "type": "integer",
        "description": "Sandbox timeout in seconds, default 300",
        "default": 300
      },
      "envs": {
        "type": "object",
        "description": "Environment variable key-value pairs",
        "additionalProperties": { "type": "string" }
      }
    }
  },
  "returns": {
    "sandbox_id": "string — Sandbox ID",
    "status": "string — Sandbox status",
    "url": "string — Sandbox access URL"
  }
}

run_code

{
  "name": "run_code",
  "description": "Execute code in the sandbox (via the code interpreter). Supports Python, JavaScript, and more. Uses the default sandbox when sandbox_id is omitted.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "code": { "type": "string", "description": "Code to execute" },
      "language": {
        "type": "string",
        "description": "Programming language, default python",
        "enum": ["python", "javascript", "shell", "typescript", "r"],
        "default": "python"
      },
      "sandbox_id": {
        "type": "string",
        "description": "Sandbox ID; uses the default sandbox when omitted"
      },
      "timeout": {
        "type": "integer",
        "description": "Execution timeout in seconds, default 30",
        "default": 30
      }
    },
    "required": ["code"]
  },
  "returns": {
    "stdout": "string",
    "stderr": "string",
    "exit_code": "integer",
    "output_files": "array — [{name, path, size}] generated files"
  }
}

run_command

{
  "name": "run_command",
  "description": "Execute a shell command in the sandbox. Uses the default sandbox when sandbox_id is omitted.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "command": { "type": "string", "description": "Shell command" },
      "sandbox_id": { "type": "string", "description": "Sandbox ID" },
      "cwd": {
        "type": "string",
        "description": "Working directory; omitted uses the image workdir",
        "default": "/app"
      },
      "timeout": {
        "type": "integer",
        "description": "Execution timeout in seconds, default 60",
        "default": 60
      }
    },
    "required": ["command"]
  },
  "returns": {
    "stdout": "string",
    "stderr": "string",
    "exit_code": "integer"
  }
}

read_file

{
  "name": "read_file",
  "description": "Read file content from the sandbox. Uses the default sandbox when sandbox_id is omitted.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "path": { "type": "string", "description": "Absolute file path" },
      "sandbox_id": { "type": "string", "description": "Sandbox ID" },
      "encoding": {
        "type": "string",
        "description": "File encoding, default utf-8",
        "default": "utf-8"
      }
    },
    "required": ["path"]
  },
  "returns": { "content": "string" }
}

write_file

{
  "name": "write_file",
  "description": "Create or overwrite a file in the sandbox. Uses the default sandbox when sandbox_id is omitted.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "path": { "type": "string", "description": "Absolute file path" },
      "content": { "type": "string", "description": "File content" },
      "sandbox_id": { "type": "string", "description": "Sandbox ID" }
    },
    "required": ["path", "content"]
  },
  "returns": { "success": "boolean", "bytes_written": "integer" }
}

list_files

{
  "name": "list_files",
  "description": "List files and subdirectories in a sandbox directory. Uses the default sandbox when sandbox_id is omitted.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "path": {
        "type": "string",
        "description": "Directory path, default /",
        "default": "/app"
      },
      "sandbox_id": { "type": "string", "description": "Sandbox ID" }
    }
  },
  "returns": {
    "files": "array — [{name, path, type, size}]"
  }
}

kill_sandbox

{
  "name": "kill_sandbox",
  "description": "Destroy the specified sandbox, or the default sandbox when sandbox_id is omitted.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "sandbox_id": {
        "type": "string",
        "description": "Sandbox ID to destroy; destroys the default sandbox when omitted"
      }
    }
  },
  "returns": { "success": "boolean" }
}

2. Session Binding Design

Default Sandbox Concept

The MCP Server introduces a "default sandbox" concept to simplify Agent operations:

graph TD
    A["Agent's first tool call (no sandbox_id)"] --> B[MCP Server automatically creates a default sandbox]
    B --> C["Subsequent calls without sandbox_id reuse the default sandbox"]

Behavior rules (implemented by SandboxManager in agent/mcp.ts):

  1. create_sandbox creates a sandbox and makes it the default. Later calls that omit sandbox_id use that sandbox. Earlier sandboxes stay alive until kill_sandbox or the session ends
  2. When there is no default yet, the first tool call that omits sandbox_id lazily creates one. Concurrent lazy creates share a single sandbox
  3. Default template: code-interpreter-v1 when started via abx mcp start (the CLI default); base when constructing SandboxMCPServer / the HTTP SessionStore programmatically without an explicit template. create_sandbox uses that server template when template is omitted
  4. kill_sandbox without sandbox_id destroys the default sandbox, and returns an error when there is no default. Session end destroys every sandbox in the session — STDIO EOF / server shutdown, or HTTP DELETE /mcp / idle session TTL expiry
  5. An explicit sandbox_id addresses that sandbox and does not change the default. Each use calls Sandbox.setTimeout with the timeout from create, extending the lifetime
sequenceDiagram
    participant Agent
    participant MCP as MCP Server
    participant SB1 as sb-001
    participant SB2 as sb-002

    Note over Agent,MCP: Session starts
    Agent->>MCP: run_code("print(1)")
    MCP->>SB1: Auto-create default sandbox sb-001
    Agent->>MCP: run_code("print(2)")
    MCP->>SB1: Reuse sb-001
    Agent->>MCP: create_sandbox(template=...)
    MCP->>SB2: Create sb-002 and make it the default
    Agent->>MCP: write_file / run_code (no sandbox_id)
    MCP->>SB2: Use sb-002
    Agent->>MCP: run_code("...", sandbox_id=sb-001)
    MCP->>SB1: Explicit id still addresses sb-001
    Note over Agent,MCP: Session ends
    MCP->>SB1: Destroy sb-001 and sb-002

3. Transport Methods

STDIO — Local IDE Integration

graph LR
    IDE["IDE / Agent<br/>Cursor, Claude, VS Code"] <-->|"STDIO stdin/stdout<br/>newline-delimited JSON-RPC 2.0"| MCP["MCP Server<br/>abx mcp start"]
    MCP --> SM[SandboxManager]
    SM --> FC[Alibaba Cloud FC]

Streamable HTTP — Remote Deployment

graph LR
    A["Client A - Cursor"] <-->|"Streamable HTTP<br/>POST /mcp"| MCP["MCP Server<br/>FC function / uvicorn"]
    B["Client B - Claude"] <-->|"Streamable HTTP<br/>POST /mcp"| MCP
    MCP --> SM["SessionStore<br/>routes by Mcp-Session-Id"]
    SM --> FC[Alibaba Cloud FC]

Authentication

Environment Variables

Variable Purpose
ABX_SANDBOX_API_KEY Sandbox backend API key
ABX_SANDBOX_BASE_URL Platform API URL
ABX_SANDBOX_DOMAIN Sandbox domain
ABX_DEFAULT_TEMPLATE Default sandbox template
ABX_MCP_AUTH_TOKEN Bearer token for client authentication (HTTP transport)

4. Server Architecture

graph TD
    subgraph MCP["MCP Server"]
        TL["Transport Layer\nSTDIO (mcp.ts) / Streamable HTTP (mcp_http.ts)"]
        TR["Tool Registry\n7 P0 tools (agent/tools.ts)"]
        SM["SandboxManager / SessionStore"]
        RR["JSON-RPC Router\ninitialize / tools/list / tools/call / ping"]
        SC["Sandbox Client\nsrc/api (Sandbox)"]
    end
    TL --> RR
    TR --> RR
    SM --> RR
    RR --> SC
    SC --> FC["Alibaba Cloud FC Sandbox Runtime"]

5. Installation and CLI

One-Click Installation

# Install to Cursor
abx mcp install --target cursor

# Install to Claude Desktop
abx mcp install --target claude

# Install to VS Code (Copilot)
abx mcp install --target vscode

install merges an agent-sandbox entry into the target IDE config: Cursor ~/.cursor/mcp.json, Claude Desktop claude_desktop_config.json (mcpServers), and the VS Code workspace .vscode/mcp.json (servers, type: stdio). The command is the absolute path of the running abx executable, or node <absolute path of abx.js> when abx cannot be found. Cursor and Claude receive ABX_SANDBOX_API_KEY in env when a key is available. The VS Code workspace file does not. A config that is not strict JSON is left untouched.

Installation Output

$ abx mcp install --target cursor

MCP Server config written to ~/.cursor/mcp.json

Registered tools:
  • create_sandbox     — Create a cloud sandbox
  • run_code           — Execute code
  • run_command        — Execute a command
  • read_file          — Read a file
  • write_file         — Write a file
  • list_files         — List files
  • kill_sandbox       — Destroy a sandbox

Please restart Cursor to apply changes.

status

abx mcp status            # table output
abx --json mcp status     # JSON output

Reports the server name, transport (stdio), tool count and names, whether an API key is configured, and whether agent-sandbox is installed in each supported IDE.


6. Configuration Examples

Claude Desktop

// ~/Library/Application Support/Claude/claude_desktop_config.json
{
  "mcpServers": {
    "agent-sandbox": {
      "command": "abx",
      "args": ["mcp", "start"],
      "env": {
        "ABX_SANDBOX_API_KEY": "your-api-key"
      }
    }
  }
}

Cursor

// ~/.cursor/mcp.json
{
  "mcpServers": {
    "agent-sandbox": {
      "command": "abx",
      "args": ["mcp", "start"],
      "env": {
        "ABX_SANDBOX_API_KEY": "your-api-key"
      }
    }
  }
}

VS Code

// .vscode/mcp.json
{
  "servers": {
    "agent-sandbox": {
      "type": "stdio",
      "command": "/path/to/abx",
      "args": ["mcp", "start"]
    }
  }
}

Remote (Streamable HTTP)

After deploying the HTTP app (Section 7), point clients at the endpoint; add a Bearer header when a token is configured:

{
  "mcpServers": {
    "agent-sandbox-remote": {
      "url": "https://<FC_HTTP_TRIGGER_URL>/mcp",
      "headers": {
        "Authorization": "Bearer <BEARER_TOKEN>"
      }
    }
  }
}

7. FC Deployment

Status: abx mcp deploy generates a deployment artifact; automatic FC API deployment is not implemented. Manual deployment steps are printed after generation.

Architecture

The MCP Server can be deployed to Alibaba Cloud Function Compute (FC) as a Streamable HTTP endpoint, leveraging FC's MCP session affinity routing.

graph TB
    CLI["abx mcp deploy → artifact directory"]
    FC["FC function: agent-sandbox-mcp (created manually)"]
    Sandbox["Envd sandbox (separate FC instance)"]

    CLI --> FC
    FC --> Sandbox

    subgraph FC_Function ["FC function"]
        ASGI["app.py → agent_sandbox.agent.mcp_http:asgi_app"]
        Trigger["HTTP trigger: POST/GET/DELETE /mcp"]
        Session["Session affinity: Mcp-Session-Id"]
        Env["Env vars: ABX_SANDBOX_API_KEY / ABX_MCP_AUTH_TOKEN / ABX_DEFAULT_TEMPLATE"]
    end

CLI Command

abx mcp deploy \
  --name agent-sandbox-mcp \
  --region cn-hangzhou \
  --template base \
  --memory 512 --timeout 600 \
  --generate-token \
  --api-key $ABX_SANDBOX_API_KEY \
  --output-dir ./mcp-artifact

Options: --name (default agent-sandbox-mcp), --region (command --region > ALIBABA_CLOUD_REGION_ID > abx config set region > cn-hangzhou), --template (default base), --memory (default 512), --timeout (default 600), --auth-token-file / --generate-token / ABX_MCP_AUTH_TOKEN env for the Bearer token, --enable-session-affinity/--no-session-affinity (default enabled), --sandbox-api-key (ABX_SANDBOX_API_KEY), --custom-domain, --output-dir.

Artifact Contents

File Content
requirements.txt agent-sandbox[mcp], uvicorn>=0.29
app.py ASGI entry point reading ABX_MCP_AUTH_TOKEN, ABX_SANDBOX_API_KEY, ABX_SANDBOX_BASE_URL, ABX_SANDBOX_DOMAIN, ABX_DEFAULT_TEMPLATE from the FC function environment
config.yaml YAML deployment manifest (not an FC API payload): function_name, region, runtime (python3.10), handler (app.app), memory, timeout, environment_variables, http_trigger (methods POST/GET/DELETE + enable_session_affinity), optional custom_domain

abx mcp deploy also prints manual deployment steps (package the artifact, create the function via the FC console or SDK, create an HTTP trigger, enable Mcp-Session-Id affinity if supported) and an IDE config template with the Bearer token masked.

Key Design Points

See CLI Design — mcp deploy for the full parameter reference and the MCP Integration guide for end-to-end usage.


The Python SDK ships its own python -m agent_sandbox.agent.mcp entry point and the create_mcp_app ASGI factory; see the SDK's MCP Server design and MCP Integration guide. This page covers the abx mcp commands and the Node.js implementation.