内容
# taiga-mcp
一个 [MCP](https://modelcontextprotocol.io) 服务器,暴露一个
[Taiga](https://taiga.io) 账户 — 项目、情节、用户故事、任务和
冲刺 — 作为 MCP 客户端(例如 Claude Code)可以调用的工具。
## 要求
- Python >= 3.14
- [uv](https://docs.astral.sh/uv/)
- 一个 Taiga 账户(Taiga Cloud 或自行托管)
## 安装
使用 [mise](https://mise.jdx.dev),安装固定的工具链(Python 和
uv)并设置环境(依赖项和 git 钩子,通过 uv):
```bash
mise install
mise run setup
```
复制示例环境文件并填写您的凭证:
```bash
cp .env.example .env
```
```dotenv
TAIGA_URL=https://api.taiga.io/api/v1
TAIGA_USERNAME=您的用户名
TAIGA_PASSWORD=您的密码
```
`TAIGA_URL` 是基本 API URL。对于 Taiga Cloud,请使用
`https://api.taiga.io/api/v1`;对于自行托管实例,请指向您的
服务器的 `/api/v1`。
创建、更新和获取工具返回一个链接到 Taiga 网页 UI 中的项目,
因此结果可以手动验证,并且 `list_tasks` 包括每个任务一个。
UI 基本 URL 源自 `TAIGA_URL`(Taiga Cloud 的 `api.taiga.io`
映射到 `tree.taiga.io`;自行托管实例删除 `/api/v1` 后缀)。
如果您的设置中派生不正确(例如,代理服务器在其他地方提供 UI),
请显式设置 `TAIGA_UI_URL`。
## 运行
```bash
uv run taiga-mcp
```
服务器在启动时进行身份验证(交换用户名/密码为令牌)
并通过 stdio 使用 MCP。
### 注册到 Claude Code
```bash
claude mcp add taiga -- uv run --directory /path/to/taiga-mcp taiga-mcp
```
## 工具
| 工具 | 参数 | 描述 |
| --- | --- | --- |
| `list_projects` | — | 列出身份验证用户可访问的所有项目。 |
| `list_epics` | `project_id` | 列出某个项目的情节。 |
| `list_user_stories` | `project_id`,`sprint_id?`,`status?`(`open`/`closed`) | 列出某个项目的用户故事,可选按冲刺或状态筛选。 |
| `list_tasks` | `project_id`,`user_story_id?` | 列出某个项目的任务,可选限定在某个用户故事中。 |
| `list_sprints` | `project_id`,`closed?` | 列出某个项目的冲刺,可选筛选为打开或关闭的冲刺。 |
| `get_current_sprint` | `project_id` | 获取某个项目的当前打开冲刺。 |
| `get_sprint` | `sprint_id` | 通过 ID 获取单个冲刺。 |
| `create_sprint` | `project_id`,`name`,`estimated_start`,`estimated_finish` | 创建一个冲刺。日期格式为 `YYYY-MM-DD`;名称必须在项目内唯一。 |
| `update_sprint` | `sprint_id`,+ 可选 `name`,`estimated_start`,`estimated_finish`,`closed` | 更新一个冲刺。`None` 保留字段不变;`closed=False` 重新打开关闭的冲刺。 |
| `close_sprint` | `sprint_id` | 关闭一个冲刺。 |
| `delete_sprint` | `sprint_id` | 永久删除一个冲刺。其故事 **不会** 被删除 — Taiga 将它们返回到待办事项列表中。 |
| `move_story_to_backlog` | `story_id` | 将故事从其冲刺中移出并返回到待办事项列表中。 |
| `create_epic` | `project_id`,`subject`,+ 可选 `description`,`status`,`assigned_to`,`tags`,`is_blocked`,`blocked_note`,`color` | 创建一个情节。`status` 是状态名称。 |
| `create_story` | `project_id`,`subject`,+ 可选 `description`,`status`,`sprint_id`,`epic_id`,`assigned_to`,`tags`,`is_blocked`,`blocked_note` | 创建一个故事,可选链接到情节。 |
| `get_epic` | `epic_id` | 通过 ID 获取单个情节及其完整字段集。 |
| `get_story` | `story_id` | 通过 ID 获取单个故事及其完整字段集。 |
| `get_epic_by_ref` | `project_id`,`ref` | 通过项目内的 `#ref`(Taiga UI 中显示的编号)获取单个情节。 |
| `get_story_by_ref` | `project_id`,`ref` | 通过项目内的 `#ref` 获取单个故事。 |
| `update_epic` | `epic_id`,+ 任意要更改的字段 | 更新一个情节。`None` 保留字段不变;`''` 清空它。 |
| `update_story` | `story_id`,+ 任意要更改的字段 | 更新一个故事。`None` 保留字段不变;`''` 清空它。 |
| `update_epic_by_ref` | `project_id`,`ref`,+ 任意要更改的字段 | 通过项目内的 `#ref` 更新一个情节。 |
| `update_story_by_ref` | `project_id`,`ref`,+ 任意要更改的字段 | 通过项目内的 `#ref` 更新一个故事。 |
列表工具显示 `#ref`(人类在 Taiga UI 中看到的标识符)
和数字 `id`。`id` 工具(`get_epic`、`update_story`,...)
采用数字 ID;`_by_ref` 工具采用 `(project_id, ref)`,
因为 `#ref` 仅在其项目内唯一。
所有列表工具自动遵循 Taiga 的分页,`list_projects`
限定为身份验证用户(未经筛选的查询将返回平台上的每个公共项目)。
## 发布
发布是自动的。每次推送到 `main` 分支都会运行检查,
[python-semantic-release](https://python-semantic-release.readthedocs.io)
根据上一个标签以来 [Conventional Commits](https://www.conventionalcommits.org)
的提交内容推导出下一个版本:
| 提交 | 增量 |
| --- | --- |
| `feat: …` | 小版本号(1.1.0 → 1.2.0) |
| `fix: …` / `perf: …` | 修订版本号(1.1.0 → 1.1.1) |
| 任意类型且带有 `BREAKING CHANGE:` 后缀 | 主版本号(1.1.0 → 2.0.0) |
| `chore:`、`docs:`、`ci:`、`test:`、`style:`、`refactor:` | 无 — 无发布 |
当有内容需要发布时,它会更新 `pyproject.toml` 中的版本号,
写入 `CHANGELOG.md`,提交为 `chore: release X.Y.Z`,
标记为 `vX.Y.Z`,并发布带有生成注释的 GitHub Release。
没有构建工件:GitHub 创建发布版本为不可变,因此资产必须在创建时密封,
而发布工具的单独上传步骤无法做到这一点 — 标签和注释是发布版本。
**请勿手动编辑版本号** — 提交历史是事实的来源,
手动编辑将被下一次发布覆盖。由于发布提交位于 `main` 分支,
请在发布后执行 `git pull`。
您的提交类型决定版本号,因此正确使用非常重要。
## 开发
运行测试套件:
```bash
uv run pytest
```
运行所有预提交钩子(lint、格式检查、测试)而无需提交:
```bash
mise run check
```
还有一个手动烟雾测试,针对真实的 Taiga 账户进行。
它使用**自己的**凭证,与 MCP 服务器的凭证分开,
因此您可以将其指向不同账户上的一个临时项目:
- 服务器:`TAIGA_URL` / `TAIGA_USERNAME` / `TAIGA_PASSWORD`
- 烟雾测试:`TAIGA_SMOKE_URL` / `TAIGA_SMOKE_USERNAME` / `TAIGA_SMOKE_PASSWORD`
(必需 — 无服务器 `TAIGA_*` 值的回退)
默认情况下,它是**只读**的 — 它列出项目并对第一个项目执行读取工具,
而不会修改任何内容:
```bash
uv run python scripts/smoke_test.py
```
为了在不影响真实工作的情况下测试完整的创建/获取/更新生命周期,
请在 Taiga 中创建一个专用的临时项目,并通过其 slug 指向烟雾测试:
该工具本身无法创建项目。然后,它在那里创建一个情节和一个链接的故事,
更新它们,读取它们,然后运行冲刺生命周期 — 创建一个冲刺,
将故事移入和移出冲刺,关闭冲刺并删除它:
```bash
TAIGA_SMOKE_PROJECT_SLUG=您的临时项目 uv run python scripts/smoke_test.py
```
情节和故事没有删除操作,因此每次完整的运行都会在烟雾项目中留下新的
(时间戳)情节和故事。它创建的冲刺在运行结束时被删除。