Metadata-Version: 2.4
Name: zentao-mcp-v1
Version: 1.0.1
Summary: 禅道 (ZenTao) V1.0 REST API MCP 服务器
Author: leslie
License-Expression: MIT
Project-URL: Homepage, https://www.zentao.net
Keywords: mcp,zentao,fastmcp,model-context-protocol,api
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: fastmcp<4,>=3.4
Requires-Dist: httpx<1,>=0.27
Requires-Dist: pydantic<3,>=2
Requires-Dist: PyYAML<7,>=6
Dynamic: license-file

# ZenTao MCP Server (V1.0)

禅道（ZenTao）**V1.0 REST API** 的 MCP（Model Context Protocol）服务器，覆盖官方 V1.0 API 手册全部 **97 个接口**，让 Claude 等 AI 助手直接查询与操作禅道的项目、需求、任务、Bug、用例等数据。

## 简介

- **全量覆盖**：Token、部门、用户、项目集、产品、产品计划、发布、需求、项目、版本、执行、任务、Bug、用例、测试单、反馈、工单 —— 17 个模块 97 个接口
- **规范驱动**：`docs/zentao-v1-openapi.json` 由脚本从[官方 API 手册](https://www.zentao.net/book/api/2309.html)第 2 章自动生成（可重复执行），FastMCP 据此自动注册全部工具
- **自动登录**：配置禅道账号密码后，服务端自动获取/续期 Token，MCP 客户端零配置接入；也可回退为客户端 Token 头透传
- **Streamable HTTP**：以 HTTP 服务方式部署，支持远程与多客户端共享

技术栈：Python ≥3.10、[FastMCP](https://gofastmcp.com) 3.x、httpx。

## 快速开始

### 1. 安装

```bash
git clone <本仓库地址> && cd zentao-mcp-v1.0
uv venv && uv pip install --python .venv/bin/python -e . --group dev
# 或 pip: python -m venv .venv && .venv/bin/pip install -e .
```

### 2. 配置

复制 `config.example.yaml` 为 `config.yaml`（已被 .gitignore 排除），填写：

```yaml
base_url: "http://您的禅道域名/api.php/v1"   # 必填
account: "您的禅道账号"                       # 自动登录（推荐）
password: "您的禅道密码"
```

> 注意：`spec_path` 默认为相对当前工作目录的 `docs/zentao-v1-openapi.json`，请从仓库根目录启动；也可在配置或环境变量（`ZENTAO_MCP_SPEC_PATH`）中指定绝对路径。

所有配置项均可用环境变量覆盖：`ZENTAO_MCP_BASE_URL` / `ZENTAO_MCP_ACCOUNT` / `ZENTAO_MCP_PASSWORD` / `ZENTAO_MCP_HOST` / `ZENTAO_MCP_PORT` 等。

### 3. 运行

```bash
cp config.example.yaml config.yaml  # 编辑后
.venv/bin/python -m zentao_mcp --config config.yaml
# 默认监听 0.0.0.0:9091，MCP 端点 http://127.0.0.1:9091/mcp
```

## 客户端接入

**自动登录模式（推荐）**——客户端只需 URL：

```json
{
  "mcpServers": {
    "zentao-v1": {
      "url": "http://127.0.0.1:9091/mcp"
    }
  }
}
```

**Token 透传模式**（未配置账号密码时；先用 `get_token` 工具或 `curl -X POST {base_url}/tokens` 获取 Token）：

```json
{
  "mcpServers": {
    "zentao-v1": {
      "url": "http://127.0.0.1:9091/mcp",
      "headers": { "token": "您的Token" }
    }
  }
}
```

## Docker 部署

```bash
docker build -t zentao-mcp-v1 .
docker run -d -p 9091:9091 \
  -e ZENTAO_MCP_BASE_URL=http://您的禅道域名/api.php/v1 \
  -e ZENTAO_MCP_ACCOUNT=您的账号 \
  -e ZENTAO_MCP_PASSWORD=您的密码 \
  zentao-mcp-v1
```

## 工具清单（97 个）

#### Token 认证（Token，1 个）

| 工具名 | 说明 |
|---|---|
| `get_token` | 获取Token（POST /tokens） |

#### 部门（Dept，2 个）

| 工具名 | 说明 |
|---|---|
| `get_dept_list` | 获取部门列表（GET /departments） |
| `get_dept_detail` | 获取部门详情（GET /departments/id） |

#### 用户（User，6 个）

| 工具名 | 说明 |
|---|---|
| `get_my_profile` | 获取我的个人信息（GET /user） |
| `get_user_list` | 获取用户列表（GET /users） |
| `get_user_detail` | 获取用户信息（GET /users/id） |
| `update_user` | 修改用户信息（PUT /users/id） |
| `delete_user` | 删除用户（DELETE /users/id） |
| `create_user` | 创建用户（POST /users） |

#### 项目集（Program，5 个）

| 工具名 | 说明 |
|---|---|
| `get_program_list` | 获取项目集列表（GET /programs） |
| `update_program` | 修改项目集（PUT /programs/id） |
| `get_program_detail` | 获取项目集详情（GET /programs/id） |
| `delete_program` | 删除项目集（DELETE /programs/id） |
| `create_program` | 创建项目集（POST /programs） |

#### 产品（Product，5 个）

| 工具名 | 说明 |
|---|---|
| `get_product_list` | 获取产品列表（GET /products） |
| `create_product` | 创建产品（POST /products） |
| `get_product_detail` | 获取产品详情（GET /products/id） |
| `update_product` | 编辑产品（PUT /product/id） |
| `delete_product` | 删除产品（DELETE /products/id） |

#### 产品计划（Productplan，9 个）

| 工具名 | 说明 |
|---|---|
| `get_product_plan_list` | 获取产品计划列表（GET /products/id/plans） |
| `create_plan` | 创建计划（POST /products/id/plans） |
| `get_plan_detail` | 获取计划详情（GET /productplans/id） |
| `update_plan` | 修改计划（PUT /productplans/id） |
| `delete_plan` | 删除计划（DELETE /productsplan/id） |
| `link_plan_stories` | 产品计划关联需求（None ） |
| `unlink_plan_stories` | 产品计划取消关联需求（None ） |
| `link_plan_bugs` | 产品计划关联Bug（None ） |
| `unlink_plan_bugs` | 产品计划取消关联Bug（None ） |

#### 发布（Release，2 个）

| 工具名 | 说明 |
|---|---|
| `get_product_release_list` | 获取产品发布列表（GET /products/id/releases） |
| `get_project_release_list` | 获取项目发布列表（GET /projects/id/releases） |

#### 需求（Story，9 个）

| 工具名 | 说明 |
|---|---|
| `get_product_story_list` | 获取产品需求列表（GET /products/id/stories） |
| `get_project_story_list` | 获取项目需求列表（GET /projects/id/stories） |
| `get_execution_story_list` | 获取执行需求列表（GET /executions/id/stories） |
| `create_story` | 创建需求（None ） |
| `get_story_detail` | 获取需求详情（GET /stories/id） |
| `change_story` | 变更需求（None ） |
| `update_story_fields` | 修改需求其他字段（None ） |
| `delete_story` | 删除需求（DELETE /stories/id） |
| `close_story` | 关闭需求（None ） |

#### 项目（Project，5 个）

| 工具名 | 说明 |
|---|---|
| `get_project_list` | 获取项目列表（GET /projects） |
| `create_project` | 创建项目（POST /projects） |
| `get_project_detail` | 获取项目详情（GET /projects/id） |
| `update_project` | 修改项目（PUT /projects/id） |
| `delete_project` | 删除项目（DELETE /projects/id） |

#### 版本（Build，6 个）

| 工具名 | 说明 |
|---|---|
| `get_project_build_list` | 获取项目版本列表（GET /projects/id/builds） |
| `get_execution_build_list` | 获取执行版本列表（GET /executions/id/builds） |
| `create_build` | 创建版本（None ） |
| `get_build_detail` | 获取版本详情（GET /builds/id） |
| `update_build` | 修改版本（None ） |
| `delete_build` | 删除版本（DELETE /builds/id） |

#### 执行（Execution，5 个）

| 工具名 | 说明 |
|---|---|
| `get_project_execution_list` | 获取项目的执行列表（GET /projects/id/executions） |
| `create_execution` | 创建执行（None ） |
| `get_execution_detail` | 查看执行详情（GET /executions/id） |
| `update_execution` | 修改执行（None ） |
| `delete_execution` | 删除执行（DELETE /executions/id） |

#### 任务（Task，12 个）

| 工具名 | 说明 |
|---|---|
| `get_execution_task_list` | 获取执行任务列表（GET /executions/id/tasks） |
| `close_task` | 关闭任务（None ） |
| `create_task_effort` | 添加任务日志（None ） |
| `get_task_effort_list` | 获取任务日志列表（None ） |
| `create_task` | 创建任务（None ） |
| `get_task_detail` | 获取任务详情（GET /tasks/id） |
| `update_task` | 修改任务（None ） |
| `delete_task` | 删除任务（DELETE /tasks/id） |
| `start_task` | 开始任务（None ） |
| `pause_task` | 暂停任务（None ） |
| `resume_task` | 继续任务（None ） |
| `finish_task` | 完成任务（None ） |

#### Bug（Bug，9 个）

| 工具名 | 说明 |
|---|---|
| `get_product_bug_list` | 获取产品Bug列表（GET /products/id/bugs） |
| `create_bug` | 创建Bug（None ） |
| `get_bug_detail` | 获取Bug详情（GET /bugs/id） |
| `update_bug` | 修改Bug（None ） |
| `delete_bug` | 删除Bug（DELETE /bugs/id） |
| `confirm_bug` | 确认Bug（None ） |
| `close_bug` | 关闭Bug（None ） |
| `activate_bug` | 激活Bug（None ） |
| `resolve_bug` | 解决Bug（None ） |

#### 用例（Testcase，6 个）

| 工具名 | 说明 |
|---|---|
| `get_product_testcase_list` | 获取产品用例列表（GET /products/id/testcases） |
| `create_testcase` | 创建用例（None ） |
| `get_testcase_detail` | 获取用例详情（GET /testcases/id） |
| `update_testcase` | 修改用例（None ） |
| `delete_testcase` | 删除用例（DELETE /testcases/id） |
| `run_testcase` | 执行用例（None ） |

#### 测试单（Testtask，3 个）

| 工具名 | 说明 |
|---|---|
| `get_testtask_list` | 获取测试单列表（GET /testtasks） |
| `get_project_testtask_list` | 获取项目的测试单（GET /projects/id/testtasks） |
| `get_testtask_detail` | 获取测试单详情（GET /testtasks/id） |

#### 反馈（Feedback，7 个）

| 工具名 | 说明 |
|---|---|
| `create_feedback` | 创建反馈（None ） |
| `assign_feedback` | 指派反馈（None ） |
| `close_feedback` | 关闭反馈（None ） |
| `delete_feedback` | 删除反馈（DELETE /feedbacks/id） |
| `update_feedback` | 修改反馈（None ） |
| `get_feedback_detail` | 获取反馈详情（GET /feedbacks/id） |
| `get_feedback_list` | 获取反馈列表（GET /feedbacks） |

#### 工单（Ticket，5 个）

| 工具名 | 说明 |
|---|---|
| `get_ticket_list` | 获取工单列表（GET /tickets） |
| `get_ticket_detail` | 获取工单详情（GET /tickets/id） |
| `update_ticket` | 修改工单（None ） |
| `create_ticket` | 创建工单（None ） |
| `delete_ticket` | 删除工单（DELETE /tickets/id） |
## 开发者指南

```bash
make test    # 全量测试
make cover   # 覆盖率
make spec    # 重新抓取官方文档并生成规范（幂等，缓存在 scripts/fixtures/raw/）
```

- 规范生成流水线：`scripts/fetch_pages.py`（抓取 97 页）→ `parse_page.py`（HTML 解析）→ `schema_builder.py`（JSON Schema 组装）→ `generate_spec.py`（生成 + 校验）。清单（页面 ID ↔ 工具名映射）在 `scripts/page_manifest.py`，`python scripts/page_manifest.py` 可对照线上手册目录核验。
- 解析中间产物 `docs/endpoints.json` 含每页告警记录，供人工审查文档不一致处。

## 兼容性说明

- 目标 API：禅道 V1.0 REST API（`api.php/v1`），适用于仍提供 V1 接口的禅道版本
- 规范中响应 schema 以官方文档字段表为准，仅供描述，不做运行时强校验（官方文档表格与真实响应存在少量类型差异，透传场景以上游响应为真相）
- 官方文档个别页面存在笔误（如"关闭任务"页面标题误标"继续任务"、`/productsplan/id` 拼写等），本项目的清单已按实际路径修正

## License

MIT
