# OpenAaaS MCP Adapter
中文 | English
OpenAaaS 的 MCP(Model Context Protocol)适配器,让 Claude Desktop、Cursor、Cline 等支持 MCP 的 AI 客户端能够连接 OpenAaaS Server,发现远程服务、提交任务并获取结果。
基于 [MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk) 构建,提供 14 个核心 Tool,覆盖完整的客户端能力:服务发现、注册认证、任务提交、结果下载及多服务器管理。
---
## 快速开始
### 推荐:uvx(零安装,无需下载到本地)
安装 [uv](https://docs.astral.sh/uv/) 后,直接运行,无需把包下载到本地:
```bash
uvx openaaas-mcp-adapter
```
`uv` 会自动从 PyPI 拉取并创建临时虚拟环境运行,用完即走,不会在系统中留下任何文件。
这是**最推荐的方式**,适合所有用户。
---
### 客户端配置
配置 Claude Desktop、Cursor 或 Cline:
```json
{
"mcpServers": {
"openaaas": {
"command": "uvx",
"args": ["openaaas-mcp-adapter"],
"toolTimeoutMs": 600000
}
}
}
```
- `toolTimeoutMs` 设置 MCP 工具调用的最大等待时间(毫秒),适合长任务轮询场景。
- ⚠️ 该参数由 MCP 客户端解析,实际生效情况取决于具体客户端实现;某些客户端或 Agent 工具本身可能仍有独立的超时限制,导致该参数不生效。
配置修改后,重启客户端即可生效。
---
### 其他安装方式(可选)
点击查看其他安装方式
#### pipx(全局安装)
```bash
pipx install openaaas-mcp-adapter
```
MCP 配置改为:
```json
{
"mcpServers": {
"openaaas": {
"command": "openaaas-mcp-adapter"
}
}
}
```
#### pip 安装
```bash
pip install openaaas-mcp-adapter
```
#### 本地源码运行(开发)
```bash
cd openaaas-mcp-adapter
uv sync
uv run openaaas-mcp-adapter
```
---
## 配置文件
配置文件保存在用户主目录下:
```
~/.openaaas-mcp-adapter/config.json
```
首次运行时若不存在,会自动创建默认配置:
```json
{
"servers": {
"default": {
"server_url": "https://api.open-aaas.com",
"api_key": "",
"client_id": "",
"name": ""
}
},
"default_server": "default"
}
```
注册成功后的配置示例:
```json
{
"servers": {
"default": {
"server_url": "https://api.open-aaas.com",
"api_key": "ak_client_xxx",
"client_id": "xxx",
"name": "my-client"
}
},
"default_server": "default"
}
```
运行 `register` 成功后会自动写入 `api_key`、`client_id` 和 `name`。
---
## 多服务器配置
支持同时配置多个服务器,通过 `server` 参数指定目标服务器。
### 为多个服务器分别注册
每个服务器别名有独立的注册信息:
```
register(name: "my-prod-client", server: "prod")
register(name: "my-local-client", server: "local")
```
两个服务器会分别保存各自的 api_key,互不干扰。
### 设置服务器地址
```
set_server_url(server_url: "https://api.open-aaas.com", server: "prod")
set_server_url(server_url: "http://127.0.0.1:8080", server: "local")
```
### 切换默认服务器
```
set_default_server(server: "prod")
```
### 列出所有配置的服务器
```
list_servers()
```
---
## 可用工具
| 工具名 | 功能描述 |
|--------|----------|
| `discover` | 发现服务端 API 信息(返回服务端版本、支持的 API 端点、可用服务列表、认证方式等。建议在首次连接新服务器时调用) |
| `set_server_url` | 设置服务器地址并保存到 config.json。已有注册信息(api_key)的服务器不会被覆盖 |
| `register` | 注册客户端,自动保存 api_key(仅需一次) |
| `update_profile` | 修改用户名 |
| `list_services` | 列出可用服务(返回轻量摘要:id/name/description/agent_status/access_type/has_permission/registration_status,不含 usage 长文本) |
| `get_service_usage` | 获取指定服务的详细 usage(能力范围、调用规范、返回格式、限制条件) |
| `submit_task` | 提交任务到远程 Agent(支持文件上传,支持 `session_id` 保持对话上下文) |
| `get_task` | 查询任务状态和最终结果(仅在用户明确要求时调用,不要主动轮询) |
| `poll_task` | 轮询任务直到获得最终结果。每 20 秒查询一次,默认无超时,可传入 `timeout_seconds` 限制最大轮询时长。Agent 禁止主动调用,仅在用户明确说"帮我等结果"/"轮询任务"时才使用 |
| `cancel_task` | 取消执行中的任务 |
| `list_files` | 列出任务的结果文件列表 |
| `download_result` | 下载任务结果文件并返回每个文件的完整路径(支持 file_id 单选或 download_all 全选)。未指定 file_id 且 download_all=false 时默认优先下载 .zip 文件,否则下载第一个文件。自动检测并解压 .zip 文件。读取文件时请使用返回结果中列出的完整路径,不要推测子目录 |
| `list_servers` | 列出所有已配置的服务器 |
| `set_default_server` | 切换默认服务器 |
| `remove_server` | 删除指定服务器的配置(不能删除默认服务器) |
### 参数说明
| 工具名 | 参数 | 必填 | 说明 |
|--------|------|------|------|
| `discover` | `server_url` | ✅ | 目标服务器地址 |
| `set_server_url` | `server_url` | ✅ | 服务器地址(以 http:// 或 https:// 开头) |
| | `server` | ❌ | 服务器别名,默认 `"default"` |
| `register` | `name` | ✅ | 客户端名称(长度 ≤64,不含 ASCII 控制字符、Unicode 控制字符及 `\/<>|&;$`) |
| | `server` | ❌ | 服务器别名,默认 `"default"` |
| `update_profile` | `name` | ✅ | 新用户名(同上约束) |
| | `server` | ❌ | 服务器别名,默认 `"default"` |
| `list_services` | `server` | ❌ | 服务器别名,默认 `"default"` |
| `get_service_usage` | `service_id` | ✅ | 目标服务 ID |
| | `server` | ❌ | 服务器别名,默认 `"default"` |
| `submit_task` | `service_id` | ✅ | 目标服务 ID |
| | `task_prompt` | ✅ | 任务描述 prompt |
| | `output_prompt` | ❌ | 输出格式要求,默认 `""` |
| | `input_files` | ❌ | 本地文件路径列表(最多 10 个,单文件 ≤100MB,仅限当前工作目录) |
| | `session_id` | ❌ | 会话 ID,用于保持对话上下文 |
| | `server` | ❌ | 服务器别名,默认 `"default"` |
| `get_task` | `task_id` | ✅ | 任务 ID |
| | `server` | ❌ | 服务器别名,默认 `"default"` |
| `poll_task` | `task_id` | ✅ | 任务 ID |
| | `timeout_seconds` | ❌ | 最大轮询时长(秒),默认不限制 |
| | `server` | ❌ | 服务器别名,默认 `"default"` |
| `cancel_task` | `task_id` | ✅ | 任务 ID |
| | `server` | ❌ | 服务器别名,默认 `"default"` |
| `list_files` | `task_id` | ✅ | 任务 ID |
| | `server` | ❌ | 服务器别名,默认 `"default"` |
| `download_result` | `task_id` | ✅ | 任务 ID |
| | `file_id` | ❌ | 指定文件 ID,默认 `""` |
| | `download_all` | ❌ | 是否下载所有文件,默认 `false` |
| | `server` | ❌ | 服务器别名,默认 `"default"` |
| `list_servers` | — | — | 无参数 |
| `set_default_server` | `server` | ✅ | 要设为默认的服务器别名 |
| `remove_server` | `server` | ✅ | 要删除的服务器别名 |
---
## 渐进式信息获取
本插件遵循"信息渐进式披露"原则:不要一次性获取所有服务的完整信息。
### 标准使用流程
1. `set_server_url` — 设置服务端地址(如未设置,默认连接 https://api.open-aaas.com)
2. `register` — 注册获取 api_key(仅需一次)
3. `list_services` — 获取轻量服务列表(id/name/description/agent_status/access_type/has_permission/registration_status),浏览并筛选候选服务
4. `get_service_usage` — 对筛选出的候选服务,按需获取详细 usage(能力范围、调用规范、返回格式、限制条件)
5. 根据 usage 内容,构造正确的 `task_prompt` 和 `output_prompt`
6. `submit_task` — 提交任务(可附带文件),保存返回的 `task_id`。提交后应询问用户是否需要等待结果,不要主动轮询
7. `get_task` — 仅在用户明确要求查询任务状态时调用(不要主动轮询)
8. `poll_task` — 仅在用户明确说"帮我等结果"/"轮询任务"时使用,每 20 秒查询一次,默认无超时
9. `download_result` — 任务完成后,用户要求下载结果文件时调用
### 为什么这样设计
- `list_services` 返回轻量摘要,不占用 LLM 上下文
- `usage` 通常包含大量文本(能力说明、调用规范、示例等),只应在确定使用该服务时获取
- 避免一次性加载所有服务的完整文档导致上下文溢出
---
## MCP 传输说明
- **MCP Transport**:`stdio`(标准输入输出),适配器作为子进程由 MCP 客户端启动,所有 tool 调用通过 JSON-RPC 在 stdio 上通信
- **文件传输**:文件上传和下载不走 MCP 协议,而是通过独立的 **HTTP(multipart/form-data)** 直连 OpenAaaS Server:
- `submit_task` 中的 `input_files` 通过 HTTP multipart 上传
- `download_result` 通过 HTTP GET 下载文件
- 这样设计避免了通过 MCP stdio 传输大体积二进制数据,保证性能和稳定性
---
## 注册约束
- 每个服务器别名可以独立注册。如果**当前服务器**已有 `api_key`,说明已完成注册,**请勿重复调用 `register`**
- 如需修改用户名,请使用 `update_profile`(示例:`update_profile(name: "new-name")`)
- **`name` 参数约束**:长度不超过 64 个字符,不含 ASCII 控制字符、Unicode 控制字符及 `\ / < > | & ; $`
- **服务器地址保护**:`set_server_url` 不会自动覆盖已有注册信息的服务器。如果该服务器已有 `api_key`,修改地址会被阻止,防止意外丢失注册信息
- 如需切换到新服务器地址,请使用新的 `server` 别名(多服务器配置),或先用 `remove_server` 删除旧配置
- **跨别名重复注册检查**:如果某个 `server_url` 已被其他 `server` 别名注册过(即该 URL 已有 api_key),则新别名无法再次注册或设置该地址,防止同一服务器被多个别名重复记录
- **删除服务器**:如需删除某个服务器配置,使用 `remove_server`。注意不能删除默认服务器,删除前需先用 `set_default_server` 切换默认服务器
---
## 使用示例
### 基础流程
1. **设置服务器地址**(可选,默认 https://api.open-aaas.com):
```
set_server_url(server_url: "https://api.open-aaas.com")
```
可选:发现服务端信息:
```
discover(server_url: "https://api.open-aaas.com")
```
2. **注册客户端**:
```
register(name: "my-client")
```
3. **列出服务并筛选候选**:
```
list_services()
```
4. **对目标服务获取详细 usage**:
```
get_service_usage(service_id: "my-service")
```
5. **提交任务**:
```
submit_task(
service_id: "my-service",
task_prompt: "分析数据并生成报告",
output_prompt: "返回 Markdown 格式的分析报告"
)
```
6. **查询任务**(仅在用户要求时调用):
```
get_task(task_id: "xxx")
```
7. **下载结果**:
```
download_result(task_id: "xxx")
```
### 带文件上传的任务
```
submit_task(
service_id: "data-analysis-agent",
task_prompt: "分析附件中的销售数据,找出增长趋势",
output_prompt: "返回 JSON 格式的分析结果,包含 trend 和 insights 字段",
input_files: ["./sales_data.csv", "./notes.txt"],
session_id: "可选,用于保持对话上下文"
)
```
文件上传限制:最多支持 10 个文件,单文件不超过 100MB;只能上传当前工作目录下的文件,不支持符号链接。
### 多服务器切换
```
list_services(server: "prod")
submit_task(server: "local", service_id: "my-service", task_prompt: "...")
```
### 删除服务器配置
```
remove_server(server: "old-server")
```
---
## 安全特性
- **路径遍历防护**:文件上传仅限当前工作目录下;zip 解压逐文件验证路径,防止 `../` 路径穿越
- **zip 炸弹防护**:最大压缩比 500、解压后总大小 100MB、最大文件数 1000、单文件最大 50MB
- **符号链接拒绝**:上传文件和 zip 中的符号链接均被直接拒绝
- **原子写入**:配置文件使用临时文件 + `replace` 保证写入过程不损坏
- **下载限制**:单文件下载不超过 100MB
---
## 开发
本地开发运行方式:
```bash
cd openaaas-mcp-adapter
uv sync
uv run openaaas-mcp-adapter
```
或使用 Python 模块方式:
```bash
uv run python -m openaaas_mcp_adapter
```
---
## 链接
- GitHub: [https://github.com/Wolido/OpenAaaS](https://github.com/Wolido/OpenAaaS)
- 官网: [https://www.open-aaas.com](https://www.open-aaas.com)
---
## 许可证
MIT License