Skip to main content
Glama
README.md
# 简道云 MCP 服务

基于 [FastMCP](https://github.com/jlowin/fastmcp) 3.x,通过 SSE 协议将简道云表单操作封装为 9 个 MCP Tools,供 Claude Code 或其他 MCP 客户端调用。

## 特性

- **API Key 一次配置,处处生效** — 在客户端连接时通过 `Authorization` header 传入,后续调用自动携带,无需每次传参
- **9 个 Tools** — 覆盖应用发现 → 表单探索 → 数据读写全流程
- **Docker 一键部署** — 开箱即用,易于自托管
- **HTTPS 支持** — 提供 Nginx 反向代理配置示例

## 目录结构

```
jiandaoyun-mcp/
├── server.py              # MCP 主服务(含 ApiKeyMiddleware)
├── client.py              # 简道云 HTTP 客户端封装
├── Dockerfile
├── docker-compose.yml
├── requirements.txt
├── nginx/
│   └── jiandaoyun-mcp.conf    # Nginx 反向代理示例配置
└── README.md
```

---

## 快速开始

### 前置条件

- **Docker**(推荐)或 Python 3.12+
- 简道云账号及 **API Key**(在简道云后台「设置」→「API 管理」获取)

### 1. 克隆仓库

```bash
git clone https://github.com/your-username/jiandaoyun-mcp.git
cd jiandaoyun-mcp
```

### 2. 启动服务

**方式一:Docker(推荐)**

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

服务默认绑定在 `127.0.0.1:8765`,仅本机可访问。

**方式二:直接运行(Python 3.12+)**

```bash
pip install -r requirements.txt
python server.py
```

### 3. 验证服务

```bash
curl -i http://localhost:8765/sse
# 期望响应:HTTP/1.1 200 OK,Content-Type: text/event-stream
```

### 4. 配置 MCP 客户端

**Claude Code CLI:**

```bash
claude mcp add --transport sse jiandaoyun http://localhost:8765/sse \
  --header "Authorization: Bearer <your_api_key>"
```

**手动编辑 `~/.claude.json`:**

```json
{
  "mcpServers": {
    "jiandaoyun": {
      "type": "sse",
      "url": "http://localhost:8765/sse",
      "headers": {
        "Authorization": "Bearer <your_api_key>"
      }
    }
  }
}
```

配置完成后重启 Claude Code 即可使用。

---

## 远程部署(公网 / 局域网)

如需将服务部署在远程服务器供多端共用,推荐用 Nginx

### 开放端口绑定(跳过 Nginx 时)

将 `docker-compose.yml` 中的端口绑定改为监听所有网卡:

```yaml
ports:
  - "0.0.0.0:8765:8765"
```

然后客户端使用 `http://<server-ip>:8765/sse` 连接(明文,仅内网推荐)。

### 配置 Nginx HTTPS(推荐用于公网)

1. 将 `nginx/jiandaoyun-mcp.conf` 复制到 `/etc/nginx/conf.d/`
2. 按注释修改以下三项:

   | 占位符 | 说明 |
   |--------|------|
   | `your.domain.com` | 你的域名 |
   | `/path/to/your/cert.crt` | SSL 证书路径 |
   | `/path/to/your/cert.key` | SSL 私钥路径 |

3. 重载 Nginx:

   ```bash
   nginx -t && nginx -s reload
   ```

4. 客户端连接地址改为:

   ```bash
   claude mcp add --transport sse jiandaoyun https://your.domain.com:9444/sse \
     --header "Authorization: Bearer <your_api_key>"
   ```

**SSE 关键配置说明(已写入模板,勿删):**

| 配置项 | 说明 |
|--------|------|
| `proxy_buffering off` | 禁用响应缓冲,保证事件实时推送 |
| `proxy_cache off` | 禁用缓存 |
| `proxy_read_timeout 86400` | 超时设为 24h,维持长连接 |
| `proxy_set_header Connection ""` | 关闭 keep-alive 改写 |

### 测试用自签名证书

```bash
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout cert.key -out cert.crt \
  -subj "/CN=localhost"
```

---

## API Key 传递方式

服务端支持以下三种方式(优先级从高到低):

| 优先级 | 方式 |
|--------|------|
| 1 | `Authorization: Bearer <key>` header(推荐) |
| 2 | `X-Api-Key: <key>` header |
| 3 | `?api_key=<key>` query 参数(仅 SSE 握手请求有效) |

---

## 可用 Tools(共 9 个)

### 推荐使用流程

```
list_apps → list_forms → get_form_fields → 读写操作
```

先了解有哪些应用和表单,再获取字段结构(字段 `name`、`label`、`type`),最后进行数据操作。

---

### 应用 / 表单发现

#### `list_apps` — 列出所有应用

```
limit:  100    # 可选,每页返回数量,默认 100
skip:   0      # 可选,跳过条数,用于分页
```

返回:`apps[]`,每项包含 `app_id`、`name`

---

#### `list_forms` — 列出应用下所有表单

```
app_id: "5e3b1234abcd5678ef901234"
```

返回:`forms[]`,每项包含 `entry_id`、`name`

---

#### `get_form_fields` — 获取表单字段结构

```
app_id:   "5e3b1234abcd5678ef901234"
entry_id: "5e3b5678abcd1234ef901234"
```

返回:`widgets[]`,每项包含 `name`(字段 ID,如 `_widget_1234`)、`label`(显示名)、`type`

> **常见字段类型:** `text`(单行文本)、`textarea`(多行文本)、`number`(数字)、`datetime`(日期时间)、`combo`(下拉框)、`radio`(单选)、`checkbox`(多选)

---

### 数据读取

#### `get_record` — 查询单条记录

```
app_id:   "5e3b..."
entry_id: "5e3b..."
data_id:  "66a1234567890abc12345678"    # 记录的 _id 字段
```

---

#### `query_records` — 查询多条记录

**基础用法:**

```
app_id:   "5e3b..."
entry_id: "5e3b..."
limit:    100
fields:   ["_widget_xxx", "_widget_yyy"]    # 可选,指定返回字段
```

**简单筛选(filters)— 精确匹配:**

```
filters: {"_widget_xxx": "张三", "_widget_yyy": "已完成"}
```

**复杂筛选(filter)— 支持 gt/lt/like/range 等:**

```
filter: {
  "rel": "and",
  "cond": [
    {"field": "_widget_xxx", "type": "gt",   "value": ["100"]},
    {"field": "_widget_yyy", "type": "like", "value": ["张"]}
  ]
}
```

> `filter` 和 `filters` 同时传入时,`filter` 优先生效。

**翻页(游标分页):**

```python
# 第一页
query_records(app_id=..., entry_id=..., limit=100)

# 取最后一条记录的 _id,作为下一页的 data_id
query_records(app_id=..., entry_id=..., limit=100, data_id="上一页最后一条的_id")
```

---

### 数据写入

#### data 字段格式

```python
data = {
    "_widget_1234567890ab": {"value": "文本内容"},    # 文本字段
    "_widget_abcdef123456": {"value": 123},            # 数字字段
    "_widget_fedcba654321": {"value": "2024-06-01"},   # 日期字段
}
```

字段的 `name`(如 `_widget_1234`)通过 `get_form_fields` 获取。

---

#### `create_record` — 新建单条记录

```
app_id:       "5e3b..."
entry_id:     "5e3b..."
data:         {...}
data_creator: "username"    # 可选,指定创建者用户名
```

返回:`{"data": {"_id": "新记录ID", ...}}`

---

#### `create_records_batch` — 批量新建(≤ 100 条)

```
app_id:    "5e3b..."
entry_id:  "5e3b..."
data_list: [
  {"_widget_xxx": {"value": "第一条"}},
  {"_widget_xxx": {"value": "第二条"}}
]
```

返回:`{"status": "success", "success_count": 2, "success_ids": ["id1", "id2"]}`

---

#### `update_record` — 修改单条记录

只需传入**需要修改的字段**,未传字段保持原值。

```
app_id:   "5e3b..."
entry_id: "5e3b..."
data_id:  "66a1234567890abc12345678"
data:     {"_widget_xxx": {"value": "修改后的值"}}
```

---

#### `delete_record` — 删除单条记录

> ⚠️ 删除不可恢复,请谨慎操作。

```
app_id:   "5e3b..."
entry_id: "5e3b..."
data_id:  "66a1234567890abc12345678"
```

返回:`{"status": "success"}`

---

## 修改默认端口

服务默认使用 `8765`。如需修改:

1. `docker-compose.yml` — 修改 `ports` 中的宿主机端口映射
2. `server.py` 末尾 — 修改 `mcp.run(port=8765)` 中的值

---

## 运维命令

```bash
# 查看服务状态
docker compose ps

# 实时查看日志
docker compose logs -f

# 重启服务
docker compose restart

# 更新代码后重新部署
docker compose up -d --build

# 停止并移除容器
docker compose down
```

---

## 技术架构

```
MCP 客户端(Claude Code 等)
      ↓  SSE(HTTP 或 HTTPS)
  [可选] Nginx 反向代理(SSL 终止)
      ↓  HTTP 127.0.0.1:8765
Docker 容器(python:3.12-slim)
      ↓
FastMCP 3.x + Uvicorn
      ↓  HTTPS
简道云 API (www.jiandaoyun.com/api/v5/...)
```

| 组件 | 版本 |
|------|------|
| FastMCP | ≥ 2.0.0(已测试 3.x) |
| Python | 3.12 |
| 传输协议 | SSE (Server-Sent Events) |
| 简道云 API | v5 |

---

## License

MIT