使用说明
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最小场集与全场集
文档:
- TAIGA_MCP_ENHANCEMENTS.md –全面的功能指南
- 快速引用.md –示例和常见模式
- 增强_ SUMMARY.md –实施总结
配置
- 复制
.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 3.11(项目使用
- 安装依赖项
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
- PowerShell:
- 构建标记图像(集
--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客户端(例如
mcpPython 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凭据和权限正确。
- 使用部署的MCP端点配置ChatGPT或其他MCP客户端,并确认
故障排除说明
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进行写访问。
