Skip to main content
Glama
waityou-love

ima-mcp-server

by waityou-love
README.md
# IMA 多用户 MCP Server

腾讯 IMA OpenAPI(笔记 + 知识库)的多用户 MCP 代理。

- **请求头透传凭证**:每个请求自带用户自己的 Client ID + API Key,服务器零存储
- **无状态 Streamable HTTP**:多用户并发天然隔离,重启无感,可水平扩容
- **client_id 白名单准入**:只有登记的 Client ID 可用;改文件即时生效,无需重启
- **17 个工具**:笔记 6 + 知识库 9 + raw_call 兜底 + 连通性检查

## 设计来源

本项目不是凭空设计,而是对社区既有方案做了一次"多用户化重构",设计脉络如下:

**要解决的问题**:腾讯 IMA 的笔记/知识库能力,原本只能单人单实例使用。目标是把它变成一台服务器,同时服务多个用户——每人用自己的腾讯账号凭证接入,服务器不替任何人保管密钥,换设备、换用户零运维。

**调研过的三条路线**(多用户 MCP Server 的主流模式):

| 模式 | 代表 | 凭证位置 | 取舍 |
| --- | --- | --- | --- |
| 请求头透传(无状态) | [LRGEX/notion-mcp](https://github.com/LRGEX/notion-mcp) | HTTP 请求头 | ✅ 采用 |
| URL 参数选身份 | [ai_mcp_fastmcp_remote](https://github.com/sunnylabtv-crypto/ai_mcp_fastmcp_remote-public) | 服务器存储映射表 | ❌ 服务器要存密钥,违背零存储目标 |
| OAuth 2.1 资源服务器 | MCP SDK 内置 | Bearer JWT | ❌ 需要授权服务器,对个人/小团队过重 |

**三个关键参照物**:

1. **[amberpepper/ima-mcp](https://github.com/amberpepper/ima-mcp)**(TypeScript)——本项目 15 个 IMA OpenAPI 接口路径、请求体结构与上游请求头命名(`ima-openapi-clientid` / `ima-openapi-apikey` / `ima-openapi-ctx`)的**直接蓝本**,全部逐一核对过。本项目复刻其工具设计,但把它的"单用户 stdio + 环境变量凭证"架构替换为"多用户 Streamable HTTP + 请求头凭证"。它依赖服务器本地路径的文件上传工具因对远程用户无意义而被移除。
2. **[LRGEX/notion-mcp](https://github.com/LRGEX/notion-mcp)**——"每个工具第一步从请求头取凭证、每请求新建客户端用完即弃"的无状态多用户范式来源。
3. **[github/github-mcp-server](https://github.com/github/github-mcp-server)**——官方 MCP Server 的容器化、工具分组与工程形态参考;其多用户依赖 OAuth 的路线被有意舍弃,换取"用户自带 Key、零存储"的极简模式。

**认证设计的两次演进**:

- 初稿为两层认证(管理员准入令牌 + 用户 IMA 凭证),后简化为**凭证即身份**——用户的 IMA 凭证本身就是唯一身份凭据,腾讯接口的响应(401)即验证,不再单独发放准入令牌;
- 进一步演进出 **client_id 白名单**:本地判断"资格"(是否被允许),腾讯判断"真伪"(Key 是否有效),两道关卡各司其职。选择白名单 client_id 而非 api_key,是因为 IMA 的 API Key 会过期/可重置,而 client_id 是稳定身份标识。

**协议基础**:MCP Streamable HTTP 传输 + 无状态模式(`stateless_http=True`),每个请求独立、无会话表,天然支持并发与水平扩容。

## 快速部署(Docker Compose)

```bash
cd ~/ima-mcp-server
cp -n .env.example .env
# 编辑 config/allowed_clients.txt,把允许的 client_id 写进去(每行一个)
docker compose build
docker compose up -d
docker compose logs -f --tail=50   # 看到 "就绪" 与白名单条数即成功
```

服务监听 127.0.0.1:8044(仅同机反代/公网接入层可访问)。
若需直接对外暴露,把 docker-compose.yml 的 ports 改为 "0.0.0.0:8044:8044"(并确保链路有 TLS)。

## 白名单管理

- 编辑 config/allowed_clients.txt:每行一个 client_id,# 后为注释
- 修改即时生效(按文件修改时间热加载),无需重启容器
- 文件存在但没有有效条目 → 拒绝所有请求(fail-closed)
- 删除文件且 IMA_ALLOWED_CLIENTS 为空 → 开放模式

## 冒烟测试

```bash
bash tests/smoke.sh <你的client_id> <你的api_key>
```

预期:1) initialize 成功;2) tools/list 返回 17 个工具;3) 无凭证调用返回缺凭证错误;4) 真实凭证返回 status ok。

## 客户端配置(以 Chatbox 为例)

- 类型:远程 MCP / Streamable HTTP
- URL:`http://<服务器IP>:8044/mcp`(若上游接了 TLS 则用 https)
- 请求头:
  - `X-Ima-ClientId`:用户自己的 client_id
  - `X-Ima-ApiKey`:用户自己的 api_key

注意:IMA API Key 可能会过期;失效时到 https://ima.qq.com/agent-interface 重置,并更新客户端请求头。

## 升级

```bash
docker compose build && docker compose up -d
```

## 常见问题

| 现象 | 原因与处理 |
| --- | --- |
| 工具返回「凭证无效或已过期」 | API Key 过期或填错,到腾讯侧重置 |
| 工具返回「未获授权使用本 MCP 服务」 | client_id 不在白名单 |
| 所有请求都被拒绝 | 白名单文件没有任何有效条目 |
| Chatbox 加载不出工具 | 检查 URL 以 /mcp 结尾;查看 docker compose logs |

## 许可

[MIT](LICENSE)