• 简体中文
  • MCP 调用

    支持 MCP 的 agent 可以直接调用沙箱内置工具,完成文件、命令、代码和浏览器操作。

    要求

    使用 MCP 客户端连接 POST /mcp 即可。每个工具都需要对应的 plane。

    可用能力见 GET /v2/sandbox 返回的 capabilities

    可用能力见 GET /v1/capabilities

    设置 AIO_API_KEY 后,需要在 Authorization: Bearer <key> 中携带 key。/mcp 不是公开路由,不带 key 会返回 401

    工具列表

    客户端可以通过 tools/list 获取当前可用的工具。

    curl
    curl -X POST "$BASE_URL/mcp" -H "Content-Type: application/json" \
      -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

    内置工具集编译进了二进制,顺序如下:

    工具作用
    sandbox_execute_bash在托管会话中执行 shell 命令
    sandbox_execute_code执行 Python 或 JavaScript
    sandbox_file_operationsread、write、replace、search、find、list、grep、glob
    sandbox_str_replace_editorview、create、str_replace、insert、undo_edit
    sandbox_get_context沙箱版本与 home 目录
    sandbox_get_packages已安装的 Python 或 Node 包
    sandbox_load_skill加载一个 skill,或列出全部
    browser_get_infoCDP url、视口大小等信息
    browser_gui_screenshot整个显示器的截图
    browser_gui_execute_action在显示器上执行一个 GUI 动作

    除此之外的工具都来自注册的 MCP server,所以以列表为准,不必记数量。每个条目都带自己的 JSON Schema:

    {
      "description": "Execute code in Python or JavaScript runtime.",
      "inputSchema": {
        "properties": {
          "code": {
            "description": "Code to execute",
            "type": "string"
          },
          "language": {
            "description": "Programming language ('python', 'javascript')",
            "type": "string"
          },
          "timeout": {
            "description": "Execution timeout in seconds",
            "type": "integer"
          }
        },
        "required": [
          "code"
        ],
        "type": "object"
      },
      "name": "sandbox_execute_code"
    }

    用四次工具调用完成一项任务

    下面用四个 JSON 请求完成一个小任务:把数字写入文件、统计行数、用 Python 求和,再读取结果。

    所有步骤共享同一个文件系统,因此命令和代码都能读取第 1 步写入的文件。

    1. 写入输入文件

    {
      "jsonrpc": "2.0",
      "id": 1,
      "method": "tools/call",
      "params": {
        "name": "sandbox_file_operations",
        "arguments": {
          "action": "write",
          "path": "/tmp/agent-data.txt",
          "content": "3\n7\n12\n5\n"
        }
      }
    }

    2. 执行命令

    {
      "jsonrpc": "2.0",
      "id": 2,
      "method": "tools/call",
      "params": {
        "name": "sandbox_execute_bash",
        "arguments": {
          "cmd": "wc -l /tmp/agent-data.txt",
          "cwd": "/tmp"
        }
      }
    }

    3. 执行 Python 代码

    {
      "jsonrpc": "2.0",
      "id": 3,
      "method": "tools/call",
      "params": {
        "name": "sandbox_execute_code",
        "arguments": {
          "language": "python",
          "code": "nums = [int(n) for n in open(\"/tmp/agent-data.txt\").read().split()]\nopen(\"/tmp/agent-result.txt\", \"w\").write(str(sum(nums)))\nprint(\"sum written\")"
        }
      }
    }

    4. 读取结果

    {
      "jsonrpc": "2.0",
      "id": 4,
      "method": "tools/call",
      "params": {
        "name": "sandbox_file_operations",
        "arguments": {
          "action": "read",
          "path": "/tmp/agent-result.txt"
        }
      }
    }

    每个结果都包含 content 列表;调用失败时,isErrortrue

    content 中的文本就是模型读到的内容,可以是文件工具返回的 JSON、命令输出或解释器的 stdout。第 1 步的完整响应如下:

    {
      "id": 1,
      "jsonrpc": "2.0",
      "result": {
        "content": [
          {
            "text": "{\"action\":\"write\",\"bytes_written\":9,\"path\":\"/tmp/agent-data.txt\",\"success\":true}",
            "type": "text"
          }
        ],
        "isError": false
      }
    }

    sandbox_execute_bash 默认在同一个共享会话中执行,除非传入 new_session

    结果中包含会话结束时的 cwd。在下一次调用中传回该值,agent 使用的工作目录就会与 shell 保持一致。

    调用失败时

    工具调用失败有两种情况,区别在于工具是否真正执行。下面分别是工具不存在和文件不存在时的请求:

    {
      "jsonrpc": "2.0",
      "id": 5,
      "method": "tools/call",
      "params": {
        "name": "sandbox_execute",
        "arguments": {}
      }
    }
    {
      "jsonrpc": "2.0",
      "id": 6,
      "method": "tools/call",
      "params": {
        "name": "sandbox_file_operations",
        "arguments": {
          "action": "read",
          "path": "/tmp/agent-missing.txt"
        }
      }
    }

    工具名不存在、未传工具名或方法不存在,都属于 JSON-RPC 错误。响应仍然是 HTTP 200,MCP 客户端解析的是 error 对象:

    {
      "error": {
        "code": -32602,
        "message": "unknown tool: sandbox_execute"
      },
      "id": 1,
      "jsonrpc": "2.0"
    }

    工具调用失败时,仍返回 result 对象,但会带有 isError: true。文本中包含失败原因,文件 API 的结构化错误会原样返回:

    {
      "id": 1,
      "jsonrpc": "2.0",
      "result": {
        "content": [
          {
            "text": "{\"action\":\"read\",\"error\":{\"errno\":2,\"errno_name\":\"ENOENT\",\"error_type\":\"not_found\",\"exception_type\":\"FileNotFoundError\",\"message\":\"Failed to read file: No such file or directory (os error 2)\",\"operation\":\"read\",\"path\":\"/tmp/agent-missing.txt\",\"retryable\":false},\"message\":\"Failed to read file: No such file or directory (os error 2)\",\"path\":\"/tmp/agent-missing.txt\",\"success\":false}",
            "type": "text"
          }
        ],
        "isError": true
      }
    }

    缺少参数也属于工具执行失败。例如,sandbox_execute_bash 不带 cmd 时返回 isError: true,文本为 cmd is required

    没有 computer-use worker 时调用 browser_gui_screenshotbrowser_gui_execute_action、CDP 端口不可达时调用 browser_get_info,以及调用已停止的上游 MCP server,也都属于这一类。

    接入其他 MCP server

    可通过 EXTRA_MCP_SERVERS(或 --mcp-servers)注册本机的无状态 MCP server;其工具会并入同一目录,调用会被转发。下面用第二个 daemon 演示这一点:

    EXTRA_MCP_SERVERS='{"peer":{"url":"http://127.0.0.1:18091/mcp","prefix":"peer"},"gone":{"url":"http://127.0.0.1:18111/mcp","prefix":"gone"}}' \
      aiod start --port 18092
    
    curl -X POST "http://127.0.0.1:18092/mcp" -H "Content-Type: application/json" \
      -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
    # → 20 tools: the 10 built-in ones, then peer_sandbox_execute_bash …
    #   peer_browser_gui_execute_action. An upstream that does not answer, like
    #   "gone" here, is simply absent from the list.
    
    curl -X POST "http://127.0.0.1:18092/mcp" -H "Content-Type: application/json" \
      -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"peer_sandbox_execute_bash","arguments":{"cmd":"echo hello","cwd":"/tmp"}}}'
    
    curl -X POST "http://127.0.0.1:18092/mcp" -H "Content-Type: application/json" \
      -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"gone_hello","arguments":{}}}'

    这次运行遵循的规则:

    • 只接受 127.0.0.1localhost[::1] 上的 http://。启动时会跳过远程地址和 command(stdio)条目,并记一条警告。
    • 没有握手也没有 session,一次调用一个 POST。因此上游可以晚于 daemon 启动,下次 tools/list 就会看到它。
    • prefix 时,工具以 <prefix>_<tool> 的形式暴露,转发时再去掉前缀。 不带 prefix 时,上游自己的工具名必须已经以 <name>_ 开头;其余工具会被丢弃,因为无法确定路由。
    • 名字冲突时内置工具优先;两个上游冲突时,保留先注册的名称。

    AIO 镜像里的 mcp-server-browser 就是这样注册的,该镜像工具列表中的页面级 browser_* 导航工具由此而来。

    连接客户端

    支持 streamable-HTTP MCP 的客户端可以连接 http://127.0.0.1:18091/mcp;使用预置镜像时,连接网关的 /mcp。设置 key 后,通过 bearer header 发送。

    相关页面