项目管理系统服务

Taiga MCP Server是一个基于Starlette的项目管理API桥接服务,提供CRUD操作和HTTP代理功能,支持Server-Sent Events和Streamable HTTP传输,适用于ChatGPT和其他MCP兼容客户端。

  • by OFFSET3
  • Python
  • 本地部署
  • 14 星标
  • 更新于
在 GitHub 查看 JohnWBlack/taiga-mcp

使用说明

Taiga MCP服务器

版本: 1.1.0
更新: 2024年12月17日

项目概述

  • 实现基于Starlette的模型上下文协议(MCP)服务器,该服务器为ChatGPT和其他符合MCP的客户端公开服务器发送事件(SSE)和可流式HTTP传输。
  • 作为ChatGPT和Taiga项目管理API之间的桥梁,通过MCP工具和HTTP操作代理提供完整的CRUD操作。
  • 作为容器工作负载部署到Azure容器应用程序,并打包通过GitHub容器注册表(GHCR)分发。

1.1.0中的新增功能

增强的CRUD操作✅

  • GET端点: 添加 epics.get, stories.get, tasks.get 用于先读后写验证
  • 删除端点: 暴露 epics.delete, stories.delete, tasks.delete 通过MCP工具
  • 仅附加更新: append_description 和 add_tags 安全协同编辑的参数
  • 软删除: archive_or_close 具有审核跟踪的生产安全删除助手
  • 分页默认值: page_size=50 默认情况下,防止大型有效载荷安全块
  • 现场控制: include_details 旗上 epics.list 最小场集与全场集

文档:


配置

  • 复制 .env.example 到 .env (或直接导出变量)并填写Taiga实例、凭据和部署设置的值。
  • 永不承诺 .env 文件或秘密;项目 .gitignore 默认情况下排除常见模式。
  • 本地脚本和辅助应用程序读取相同的变量(TAIGA_BASE_URL, TAIGA_USERNAME, TAIGA_PASSWORD, ACTION_PROXY_API_KEY, MCP_URL, TAIGA_PROXY_BASE_URL,和朋友),因此更新环境可以使整个工具链保持一致。

运行时架构

  • app.py 实例化 FastMCP 具有泰加MCP身份的SSE安装在 /sse/ 和流式HTTP /mcp/,并禁用尾随斜线重定向以保留MCP会话标头。
  • 自定义中间件重写裸机 /mcp 请求 /mcp/ 并规范子应用程序内的空白路径,以避免之前丢弃MCP会话报头的307重定向。
  • FastMCP会话管理器是通过Starlette的生命周期挂钩启动的,以确保可流式会话在长时间运行的ChatGPT对话中保持活动状态。
  • 健康检查:
    • GET / → 纯文本“Taiga MCP up”用于快速可用性探头。
    • GET /healthz → 容器编排器的最小健康端点。

端点摘要

  • / --根状态页面。
  • /healthz --Azure容器应用程序使用的Liveness探测器。
  • /sse/ --服务器发送事件传输;需要 Accept: text/event-stream 并在第一事件有效载荷中返回消息发布端点。
  • /sse/sse/messages/ --SSE消息提交的POST目标(在SSE中返回 endpoint 事件)。
  • /mcp/ --可流式HTTP传输;客户 必须 发送 Accept: application/json, text/event-stream 以满足协议协商。

MCP工具

读取操作

  • echo(message) --返回所提供消息的诊断助手。
  • taiga.projects.list(search?) --列出服务帐户为成员的项目(可选的不区分大小写的子字符串搜索,由经过身份验证的用户id限定范围)。
  • taiga.projects.get(project_id?, slug?) --通过数字标识符或slug(需要两个输入之一)获取项目记录。
  • taiga.epics.list(project_id, include_details?, page?, page_size?) --列出具有可选字段控件和分页的项目的epic(默认值:最小字段,page_size=50)。
  • taiga.epics.get(epic_id) — 新v1.1.0 按ID获取具有完整细节的特定史诗。
  • taiga.stories.list(project_id, search?, epic_id?, tags?, page?, page_size?) --列出项目的用户故事,其中包含文本搜索、史诗成员资格、标签和分页的可选过滤器(默认值:page_size=50)。
  • taiga.stories.get(user_story_id) — 新v1.1.0 通过ID获取具有完整细节的特定故事。
  • taiga.tasks.list(project_id?, user_story_id?, assigned_to?, search?, status?, page?, page_size?) --列出具有灵活过滤器和分页元数据的任务,在出现以下情况时解析状态名称 project_id 供应。
  • taiga.tasks.get(task_id) — 新v1.1.0 按ID获取具有完整详细信息的特定任务。
  • taiga.users.list(project_id?, search?) --按项目成员身份查找Taiga用户,可选的子字符串在全名、用户名或电子邮件中匹配。
  • taiga.milestones.list(project_id, search?) --返回项目的里程碑/冲刺,允许可选的名称/段塞过滤。

创建操作

  • taiga.stories.create(project_id, subject, description?, status?, tags?, assigned_to?) --创建Taiga用户故事; status 接受id或状态名称/slug。
  • taiga.epics.add_user_story(epic_id, user_story_id) --将用户故事链接到史诗。
  • taiga.tasks.create(user_story_id, subject, description?, assigned_to?, status?, tags?, due_date?, idempotency_key?) --在故事下创建一个Taiga任务,应用状态查找和幂等性保护。

更新操作

  • taiga.stories.update(user_story_id, subject?, description?, append_description?, status?, tags?, add_tags?, assigned_to?, epic_id?, milestone_id?, custom_attributes?, version?) --使用乐观并发检查和服务器端状态解析更新现有故事。 新v1.1.0: append_description 和 add_tags 用于安全的协作编辑。
  • taiga.tasks.update(task_id, subject?, description?, append_description?, assigned_to?, status?, tags?, add_tags?, due_date?, version?) --使用与故事相同的乐观并发处理来更新任务。 新v1.1.0:仅附加助手。

删除操作

  • taiga.epics.delete(epic_id) — 新v1.1.0 硬删除史诗(毁灭性-无法撤消)。
  • taiga.stories.delete(user_story_id) — 新v1.1.0 硬删除一个故事(破坏性-无法撤消)。
  • taiga.tasks.delete(task_id) — 新v1.1.0 硬删除任务(销毁-无法撤消)。
  • taiga.stories.archive_or_close(user_story_id, closed_status?, add_archive_tag?) — 新v1.1.0 通过将状态设置为关闭并添加存档标签(生产安全、可逆)进行软删除。
  • taiga.tasks.archive_or_close(task_id, closed_status?, add_archive_tag?) — 新v1.1.0 任务的软删除(生产安全、可逆)。

动作代理表面

  • 目的:为Taiga自动化提供一个轻量级的HTTP桥,同时MCP写入工具保持分配状态。
  • Auth:每个请求都提供 X-Api-Key;该值必须与 ACTION_PROXY_API_KEY 环境变量(丢失/无效密钥返回401、未配置密钥返回503)。
  • 终点:
    • GET /actions/list_projects?search=foo → { "projects": [...] } 具有可选的不区分大小写的名称过滤器(自动设置 member=<service-account-id> 除非你覆盖 member 查询参数)。
    • GET /actions/get_project?project_id=123 → { "project": {...} } 返回给定id的完整Taiga项目有效载荷。
    • GET /actions/get_project_by_slug?slug=acme-backlog → { "project": {...} } 通过slug解决该项目。
    • GET /actions/list_epics?project_id=123&project_id=456 → { "epics": [...] } 包括起源 project_id 对于每一部史诗。
    • GET /actions/get_epic?epic_id=123 → 新v1.1.0 { "epic": {...} } 拍摄一部具有完整细节的特定史诗。
    • GET /actions/list_stories?project_id=123&epic_id=456&search=prior+art&tag=ip → { "stories": [...] } 按项目、史诗、关键字、标签和可选分页进行筛选(page/page_size).
    • GET /actions/get_task?task_id=456 → 新v1.1.0 { "task": {...} } 获取具有完整细节的特定任务。
    • GET /actions/statuses?project_id=123 → { "statuses": [...] } 驱动状态选择器。
    • POST /actions/create_story → { "story": {...} };接受与MCP工具相同的有效载荷,并解析状态块/名称。
    • POST /actions/update_story → { "story": {...} };接受 story_id 加上以下各项的任意组合 project_id, subject, description, status, tags, assigned_to (状态字符串会自动解析为id)。
    • POST /actions/delete_story → { "deleted": {"story_id": ...} }.
    • POST /actions/add_story_to_epic → { "link": {...} } 在将故事与史诗联系起来之后。
    • POST /actions/create_epic / update_epic / delete_epic → 管理史诗(project_id, subject,可选 description, status, assigned_to, tags, color).
    • POST /actions/create_task / update_task / delete_task → 管理任务(project_id, subject,可选 description, status, assigned_to, tags, user_story_id).
    • POST /actions/create_issue / update_issue / delete_issue → 管理问题(project_id, subject,可选 description, status, priority, severity, type, assigned_to, tags).
  • 错误模型:JSON { "error": "..." } 有效载荷为4xx用于验证/Taiga错误,500用于意外故障(也记录在服务器端)。
  • 辅助脚本(必需 ACTION_PROXY_API_KEY 和 TAIGA_PROXY_BASE_URL 待设置):
    • \.\.chat-venv\Scripts\python.exe scripts/actions_proxy_client.py --pretty list-projects
    • \.\.chat-venv\Scripts\python.exe scripts/actions_proxy_client.py get-project --project-id <ID>
    • \.\.chat-venv\Scripts\python.exe scripts/actions_proxy_client.py get-project-by-slug --slug <slug>
    • powershell.exe -File scripts/actions-proxy.ps1 list-projects
  • 原始卷曲样品:
    • curl.exe -H "X-Api-Key: $env:ACTION_PROXY_API_KEY" "$env:TAIGA_PROXY_BASE_URL/actions/list_projects?search=beta"
    • curl.exe -H "X-Api-Key: $env:ACTION_PROXY_API_KEY" -H "Content-Type: application/json" -d "{\"project_id\":123,\"subject\":\"Story\"}" "$env:TAIGA_PROXY_BASE_URL/actions/create_story"

本地开发工作流程

  • 先决条件
    • Python 3.11(项目使用 .chat-venv 默认情况下为虚拟环境)。
    • Docker Desktop用于容器构建。
    • 用于部署自动化的Azure CLI。
    • GHCR认证(docker login ghcr.io).
  • 安装依赖项
    • python -m venv .chat-venv
    • .\.chat-venv\Scripts\python.exe -m pip install -r requirements.txt
  • 配置环境
    • copy .env.example .env (PowerShell: Copy-Item .env.example .env)并更新值以指向您的Taiga实例。
  • 在本地运行服务器
    • .\.chat-venv\Scripts\uvicorn.exe app:app --host 127.0.0.1 --port 8010
    • 可流式探头: .\.chat-venv\Scripts\python.exe streamable_client.py http://127.0.0.1:8010/mcp --message "hello local"
  • SSE手动测试
    • curl.exe -sN -H "Accept: text/event-stream" http://127.0.0.1:8010/sse/

容器构建和发布

  • 选择映像名称(默认部署使用 ghcr.io/johnwblack/taiga-mcp)并设置:
    • PowerShell: $env:CONTAINER_IMAGE = 'ghcr.io/johnwblack/taiga-mcp' 和 $env:IMAGE_TAG = 'v0.0.29'
    • 猛击: export CONTAINER_IMAGE=ghcr.io/johnwblack/taiga-mcp 和 export IMAGE_TAG=v0.0.29
  • 构建标记图像(集 --platform 交叉建筑时):
    • docker build -t "$CONTAINER_IMAGE:$IMAGE_TAG" -t "$CONTAINER_IMAGE:latest" .
  • 推送到您的注册表:
    • docker push "$CONTAINER_IMAGE:$IMAGE_TAG"
    • docker push "$CONTAINER_IMAGE:latest"

Azure容器应用部署

  • 导出以下环境变量(更新名称以匹配您的订阅):
    • $env:AZURE_RESOURCE_GROUP = 'your-resource-group'
    • $env:AZURE_CONTAINER_APP = 'taiga-mcp'
  • 部署新版本(在推送映像后):
    • az containerapp update -g $env:AZURE_RESOURCE_GROUP -n $env:AZURE_CONTAINER_APP --image "$CONTAINER_IMAGE:$IMAGE_TAG"
  • 或者运行辅助脚本(构建、推送和部署在一个步骤中;尊重相同的环境变量并接受覆盖):
    • python scripts/deploy_to_azure.py --image "$env:CONTAINER_IMAGE" --tag "$env:IMAGE_TAG" --resource-group "$env:AZURE_RESOURCE_GROUP" --container-app "$env:AZURE_CONTAINER_APP"
    • 可选标志: --skip-build, --skip-push, --latest-tag 帮助重新部署修补程序
  • 有用的Windows设置(避免WinError 5权限问题):
    • $env:AZURE_EXTENSION_DIR = Join-Path $HOME '.az-extensions'
    • $env:AZURE_CONFIG_DIR = Join-Path $HOME '.az-cli'

泰加证件的保密管理

  • 将Taiga凭据和代理密钥存储在您选择的秘密存储中(Azure容器应用程序秘密、Kubernetes秘密等),并将其作为容器内的环境变量显示出来。
  • 示例(Azure容器应用程序):
    • az containerapp secret set --resource-group $env:AZURE_RESOURCE_GROUP --name $env:AZURE_CONTAINER_APP --secrets taiga-username="<USERNAME>" taiga-password="<PASSWORD>"
    • az containerapp update --resource-group $env:AZURE_RESOURCE_GROUP --name $env:AZURE_CONTAINER_APP --set-env-vars TAIGA_USERNAME=secretref:taiga-username TAIGA_PASSWORD=secretref:taiga-password
  • 以相同的方式更新或旋转操作代理键:
    • az containerapp secret set --resource-group $env:AZURE_RESOURCE_GROUP --name $env:AZURE_CONTAINER_APP --secrets action-proxy-api-key="<RANDOM_TOKEN>"
    • az containerapp update --resource-group $env:AZURE_RESOURCE_GROUP --name $env:AZURE_CONTAINER_APP --set-env-vars ACTION_PROXY_API_KEY=secretref:action-proxy-api-key
  • 容器期望存在以下环境变量:
    • TAIGA_BASE_URL -Taiganeneneba API的基本URL(通常由秘密引用支持)。
    • TAIGA_USERNAME --服务帐户用户名。
    • TAIGA_PASSWORD --服务帐户密码。
    • ACTION_PROXY_API_KEY --共享秘密由 /actions/* 端点。
  • 定期轮换凭据并重新部署,以便新修订版能够接受更改。

连接MCP客户端

  • 您需要部署和托管自己的MCP服务器实例(例如在Azure容器应用程序、Docker桌面或任何其他Python托管目标上)。此存储库不公开共享公共终结点。
  • ChatGPT自定义GPT设置:
    • 打开GPT生成器UI,选择 创建,然后选择 配置 → 添加 在模型上下文协议工具部分。
    • 输入已部署的流式HTTP URL(例如 https://your-domain.example/mcp)作为端点,将headers/body留空,除非您保护了代理后面的路由。
    • 保存GPT并测试 echo 用于确认连接的工具。会话将在每次调用时重用您部署的服务器。
  • 开源MCP客户端(例如 mcp Python CLI或Claude Desktop)可以针对相同的目标 /mcp 终点;集 MCP_URL 在运行辅助脚本之前,请先将已部署的URL设置为 streamable_client.py.
  • 如果重新生成容器映像,则现有的环境变量和秘密引用仍将附加到容器应用程序。仅在引入新键/变量或凭据轮换时才重新设置它们。

验证检查表

  • 流式HTTP烟雾测试:
    • \.\.chat-venv\Scripts\python.exe streamable_client.py $env:MCP_URL --message "ping"
  • SSE可用性测试:
    • curl.exe -sN -H "Accept: text/event-stream" "$env:TAIGA_PROXY_BASE_URL/sse/" --max-time 5
  • Azure日志审查(如果部署到ACA):
    • az containerapp logs show -g $env:AZURE_RESOURCE_GROUP -n $env:AZURE_CONTAINER_APP --tail 50
  • ChatGPT连接器验证:
    • 使用部署的MCP端点配置ChatGPT或其他MCP客户端,并确认 echo 工具响应。
    • 端到端地练习项目、史诗和故事工作流,以确保Taiga凭据和权限正确。

故障排除说明

  • Not Acceptable: Client must accept text/event-stream --确保客户端发送 Accept: application/json, text/event-stream 通话时 /mcp/.
  • Session terminated 错误通常表示重定向;验证请求是否成功 /mcp/ (带尾随斜线)并且代理不会重写标头。
  • Azure命令行界面 WinError 5 权限问题通过设置来解决 AZURE_EXTENSION_DIR 和 AZURE_CONFIG_DIR 到用户可写的位置。
  • 更新机密后,Azure容器应用程序将重新启动修订版;在重新测试终点前留出1-2分钟的时间。

测试

  • 安装开发依赖项: python -m pip install -r requirements.txt pytest (从 .chat-venv 环境)。
  • 运行Python单元套件: pytest (封面 /actions/* 通过伪造进行身份验证、验证和Taiga错误处理)。
  • 在本地对助手CLI进行冒烟测试: .\.chat-venv\Scripts\python.exe scripts/actions_proxy_client.py --help.
  • PowerShell验证: powershell.exe -File scripts/actions-proxy.ps1 list-projects -BaseUrl http://127.0.0.1:8010 -ApiKey local-test 当服务器使用虚拟密钥运行时。

请求有效载荷参考

故事

  • 创建(POST /actions/create_story): { "project_id": int, "subject": str, "description"?: str, "status"?: int|str, "tags"?: [str], "assigned_to"?: int }
  • 更新(POST /actions/update_story): { "story_id": int, "project_id"?: int, "subject"?: str, "description"?: str, "status"?: int|str, "tags"?: [str], "assigned_to"?: int }
  • 删除(POST /actions/delete_story): { "story_id": int }

史诗

  • 创建(POST /actions/create_epic): { "project_id": int, "subject": str, "description"?: str, "status"?: int, "assigned_to"?: int, "tags"?: [str], "color"?: str }
  • 更新(POST /actions/update_epic): { "epic_id": int, "subject"?: str, "description"?: str, "status"?: int, "assigned_to"?: int, "tags"?: [str], "color"?: str }
  • 删除(POST /actions/delete_epic): { "epic_id": int }

任务

  • 创建(POST /actions/create_task): { "project_id": int, "subject": str, "description"?: str, "status"?: int, "assigned_to"?: int, "tags"?: [str], "user_story_id"?: int }
  • 更新(POST /actions/update_task): { "task_id": int, "subject"?: str, "description"?: str, "status"?: int, "assigned_to"?: int, "tags"?: [str], "user_story_id"?: int }
  • 删除(POST /actions/delete_task): { "task_id": int }

问题

  • 创建(POST /actions/create_issue): { "project_id": int, "subject": str, "description"?: str, "status"?: int, "priority"?: int, "severity"?: int, "type"?: int, "assigned_to"?: int, "tags"?: [str] }
  • 更新(POST /actions/update_issue): { "issue_id": int, "subject"?: str, "description"?: str, "status"?: int, "priority"?: int, "severity"?: int, "type"?: int, "assigned_to"?: int, "tags"?: [str] }
  • 删除(POST /actions/delete_issue): { "issue_id": int }

Azure AI回退(未来选项)

  • 想法:在ChatGPT MCP分配列表待定时,通过Azure OpenAI Assistants工具公开Taiga访问权限。
  • 组件:托管相同FastMCP逻辑的Azure函数(或容器应用程序),向HTTPS工具端点注册的Azure OpenAI Assistant,以及存储在密钥库中的服务主体凭据。
  • 状态:延期;重新审视OpenAI allowlist在代理推出后是否仍然被阻止。保持脚本模块化,以便相同的助手有效载荷为MCP代理和任何未来的Azure AI适配器提供数据。

项目历史(2025年10月亮点)

  • 重构Starlette路由,以消除在Azure上剥离MCP会话头的自动斜线重定向。
  • 添加了中间件来规范流式HTTP路径,并确保与Azure入口重写行为的兼容性。
  • 构建和发布的容器版本 v0.0.4 通过 v0.0.10,与 v0.0.10 作为修订版部署 taiga-mcp--0000016.
  • 使用本地客户端验证SSE和流式HTTP传输, curl,以及ChatGPT MCP连接器。
  • 将Taiga服务帐户凭据安全地存储在Azure容器应用程序机密中,以便将来能够对Taiga进行写访问。