agentscope-ai / agentscope-ai/agentscope-java
[Bug]: AgentRun MCP initialize 创建新沙箱实例,不复用 CreateSandbox 创建的带 OSS/NAS 挂载的实例
- 主要語言
- Java
- 星號
- 5.6k
- 分支
- 1.3k
- 平均合併
- 4 天 12 小時
- 30 天內合併 PR
- 77
描述
## 版本
- agentscope-java: `2.0.0-RC5`(本地源码 2.0.0-SNAPSHOT,含 #1907/#1908 本地修复后同样复现)
- 沙箱后端: AgentRun(阿里云函数计算 FC 3.0 Sandbox API `2025-09-10`)
## 问题描述
AgentRun 沙箱后端通过 `CreateSandbox` API 创建带 `ossMountConfig` 的沙箱实例后,Java 客户端用 MCP URL(`AgentRunMcpChannel`)连接时,平台会**创建一个新的沙箱实例**(无 OSS 挂载),而不是复用 `CreateSandbox` 创建的那个。导致所有通过 MCP 执行的文件操作(`write_file`、`execute`、`read_file`)都在没有 OSS 挂载的容器里执行,文件不会落到 OSS。
### 核心矛盾
| 步骤 | 创建的实例 | OSS 挂载 |
|------|-----------|---------|
| `CreateSandbox` API(带 `ossMountConfig`) | 容器 A(`containerId=c-xxx`) | ✅ `/mnt/workspace` 是 ossfs FUSE 挂载 |
| MCP `initialize`(任何 URL 形式) | 容器 B(`containerId=c-yyy`,不同) | ❌ `/mnt/workspace` 不存在 |
两个实例共享同一个 `sandboxId`,但物理容器不同。`ossMountConfig` 只在 `CreateSandbox` 时生效,MCP `initialize` 创建的新容器不带挂载。
## 复现步骤
### 1. 创建带 OSS 挂载的沙箱
```bash
curl -s -X POST "https://{accountId}.agentrun-data.{region}.aliyuncs.com/sandboxes" \
-H "X-API-Key: Bearer {apiKey}" \
-H "X-Acs-Parent-Id: {accountId}" \
-H "Content-Type: application/json" \
-d '{
"sandboxId": "TESTSANDBOX1234567890123456",
"templateName": "{templateName}",
"sandboxIdleTimeoutSeconds": 3600,
"ossMountConfig": {
"mountPoints": [{
"bucketName": "my-bucket",
"bucketPath": "/data/files",
"endpoint": "http://oss-cn-hangzhou-internal.aliyuncs.com",
"mountDir": "/mnt/workspace",
"readOnly": false
}]
}
}'
```
API 返回 `status: READY`,`ossMountConfig` 在响应中确认存在。通过 AgentRun 控制台进入此沙箱,`/mnt/workspace` 是 ossfs FUSE 挂载,手动 `echo > /mnt/workspace/test.txt` 能在 OSS 桶里看到文件。
### 2. 通过 MCP 连接(模板级 URL)
```bash
MCP_URL="https://{accountId}.agentrun-data.{region}.aliyuncs.com/templates/{templateName}/mcp"
# MCP initialize → 返回 Mcp-Session-Id
# MCP tools/call process_exec_cmd: ls /mnt/workspace/
# → "No such file or directory"
```
### 3. 通过 MCP 连接(沙箱级 URL)
尝试了沙箱级 URL `/templates/{templateName}/sandboxes/{sandboxId}/mcp`,HTTP 200 + 返回 `Mcp-Session-Id`,但执行命令仍然连到了**没有 OSS 挂载的容器**:
```bash
SANDBOX_MCP_URL="https://{accountId}.agentrun-data.{region}.aliyuncs.com/templates/{templateName}/sandboxes/{sandboxId}/mcp"
# MCP initialize → 200 OK, Mcp-Session-Id 返回
# MCP tools/call process_exec_cmd: ls /mnt/workspace/
# → "No such file or directory"(仍然连到了错误容器)
```
### 4. 验证
对比 `containerId`:
- `GetSandbox` API 返回的 `metadata.fcSessionDetails.containerId` = `c-A`(有 OSS)
- MCP `initialize` 后执行命令所在容器的 `containerId` = `c-B`(无 OSS,不同)
控制台显示两个沙箱实例:
- 大写 ID(`sandboxId`)的沙箱:有 OSS 挂载 ✅
- UUID 格式的沙箱:无 OSS 挂载 ❌(MCP `initialize` 创建的)
## 影响
- **OSS/NAS 挂载功能完全不可用**:所有文件操作通过 MCP 执行,但 MCP 连到的容器没有挂载
- `write_file` 返回 "SUCCESS" 但文件不在 OSS(写到容器本地盘,idle timeout 后丢失)
- `workspaceOnNas=true` 的优化路径(跳过 tar 持久化)反而导致数据丢失——以为文件在 OSS 上,实际不在
- 此问题被 #1907(data 信封未解包)和 #1908(MCP 嵌套响应解析)两个 bug 遮盖,修复后才暴露
## 相关代码
- `AgentRunMcpChannel.resolveUrl()`(`AgentRunMcpChannel.java:191-208`):只用 `mcpServerUrl`(模板级 URL)+ `mcpEndpoint`(`/mcp`),不包含 `sandboxId`
- `AgentRunSandboxClient.create()`(`AgentRunSandboxClient.java:64-97`):调用 `CreateSandbox` 后不保存 `fcSessionId`,后续 MCP 连接无法关联
- `AgentRunSandbox.ensureSandbox()`(`AgentRunSandbox.java:211-231`):`createSandbox` 和 `mcp.connect()` 是两个独立步骤
## 尝试过的路由方式
以下 header 均无法让 MCP `initialize` 复用 CreateSandbox 的容器实例:
- `X-Sandbox-Id: {sandboxId}`
- `X-Session-Id: {fcSessionId}`
- `X-Agentrun-Session-Id: {fcSessionId}`
- `X-Fc-Session-Id: {fcSessionId}`
沙箱级 URL `/templates/{template}/sandboxes/{sandboxId}/mcp` 返回 200 但 MCP 仍创建新容器。
## 期望行为
`CreateSandbox` 创建的沙箱实例(带 OSS/NAS 挂载)应能被 MCP `initialize` 复用,或者 AgentRun 平台应提供一种方式将 MCP session 关联到指定的 `sandboxId`/`fcSessionId`。
## 环境
- AgentRun 模板: `sandbox-aio-o6XEzX`(AllInOne 类型)
- 区域: `cn-hangzhou`
- OSS: 标准存储,同地域,内网 endpoint
- RAM 角色: 已配置 `executionRoleArn`,OSS 权限已授予
貢獻指南
評估
這個 Issue 還沒有評估資料。