Files
yixiong-claude-marketplace/plugins/zentao/skills/zentao-misc/SKILL.md
T
SkyJourneyandClaude Sonnet 5 9d9e31c98e [feat] Add zentao plugin (Claude Code + Codex dual scaffold)
新增禅道项目管理系统插件,含项目集/产品/项目/执行、需求
(story/epic/requirement)、Bug、任务、测试、计划与发布、反馈工单
八个工作流技能,自动配置 MCP 连接(禅道「个人中心 → 获取凭证」
自助生成 14 天 Token)。

MCP Server 是团队自建的 zentao-mcp 网桥(部署在
pm.ops.yixiong-tech.com/mcp),基于开源 openapi-mcp-server 二次开发。
Claude 侧走 userConfig 钥匙链 + 自定义 token 头;Codex 侧受限于官方
插件格式只支持 bearer_token_env_var,走 Authorization: Bearer——网桥
那边已经加了 preferred_header/bearer_mode 配置项统一归一化处理,两条
路径都验证过连通。

三轮审查(静态字段对照 openapi.json、跨文件一致性、真实端点实测)
修正过程中发现的问题,技能文档里引用的工具名全部跟服务器真实注册
的 118 个工具核对过。

同步更新:.claude-plugin/marketplace.json、.agents/plugins/marketplace.json、
README.md、CLAUDE.md 的插件索引与说明;README 补充「获取凭证」操作
截图(已脱敏)。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016pFx6jnym6kRWRQ5JyDUNv
2026-08-25 13:50:41 +08:00

102 lines
4.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: zentao-misc
description: "禅道反馈、工单、应用管理、附件改名。当用户说「提个反馈」「开个工单」「工单关掉」「建个应用」「改一下附件名字」时使用。"
---
# 禅道反馈 / 工单 / 应用 / 附件
**前置:先读 `zentao-shared`(尤其"路径参数不出现在 inputSchema 里"一节)。**
---
## 反馈(feedback
```
get_products_productID_feedbacks(productID, ...)
get_feedbacks_feedbackID(feedbackID)
post_feedbacks({ payload: { product, title, module?, type?, desc?, feedbackBy?, source? } })
put_feedbacks_feedbackID({ feedbackID, payload: {...} })
delete_feedbacks_feedbackID({ feedbackID })
put_feedbacks_feedbackID_close({ feedbackID, payload: { closedReason, comment? } })
put_feedbacks_feedbackID_activate({ feedbackID, payload: {...} })
```
**创建字段名注意:所属产品叫 `product`,不是 `productID`**(跟大多数其他实体不一致,
`zentao-plan` 的 build/release 也是这个坑)。
**"没有反馈/工单"和"参数传错"在这两个接口上长得一模一样**:实测发现某个产品下没有
反馈/工单记录时,后端返回的是 `HTTP 200` + **完全空的响应体**,跟 `zentao-shared` 里说的
"路径参数传漏/传错 → 静默返回空结果"是同一种表现。`zentao-shared` 那条"先怀疑参数
传漏了,再怀疑数据本身"的排查顺序在这两个接口上不管用——换任何一个真实存在的
`productID` 都可能一样是空的。真要鉴别,换个已知有数据的接口(比如 `get_products`
确认这个 productID 本身没写错,或者直接问用户这个产品下是否本来就没有反馈/工单。
`type`(反馈类型)受限枚举:`story` 需求 | `task` 任务 | `bug` Bug | `todo` 待办 |
`advice` 建议 | `issue` 问题 | `risk` 风险 | `opportunity` 机会——这个类型决定了反馈
可能被后续转化成对应的实体,跟用户确认清楚类型再提交。
`closedReason` 关闭必填,受限枚举:`commented` 已处理 | `repeat` 重复 | `refuse` 不予采纳。
关闭前按 `zentao-shared` 全局约定跟用户确认原因。
---
## 工单(ticket
```
get_products_productID_tickets(productID, ...)
get_tickets_ticketID(ticketID)
post_tickets({ payload: { product, title, module?, type?, desc?, assignedTo?, deadline?,
openedBuild? } })
put_tickets_ticketID({ ticketID, payload: {...} })
delete_tickets_ticketID({ ticketID })
put_tickets_ticketID_close({ ticketID, payload: { closedReason, comment } })
put_tickets_ticketID_activate({ ticketID, payload: {...} })
```
同样是 `product` 不是 `productID``type`(工单类型)受限枚举:`code` 程序报错 |
`data` 数据错误 | `stuck` 流程卡断 | `security` 安全问题 | `affair` 事务。
`openedBuild`(影响版本)**是字符串数组**,可以关联多个版本,不是单个 ID,跟 `zentao-bug`
`openedBuild` 的数组结构是同一个模式。
**关闭工单 `closedReason` 和 `comment` 都必填**(反馈关闭只要求 `closedReason`,工单
两个都要)——`closedReason` 枚举:`commented` 已处理 | `repeat` 重复 | `refuse` 不予处理。
---
## 应用(system
```
get_products_productID_systems(productID, ...)
post_systems({ payload: { productID, integrated, children, name, desc? } })
put_systems_systemID({ systemID, payload: {...} })
```
**没有查询单条应用详情、也没有删除应用的接口**(只有创建/修改),这跟其他实体都不一样,
需要删除或者查看单条详情要引导用户去网页端。
**`get_products_productID_systems` 实测对部分账号会返回 `HTTP 403 Access not allowed`**——
应用管理看起来受账号权限控制,不是所有 Token 都能查。403 时先怀疑是权限不够(提示用户
去禅道网页确认自己有没有应用管理权限),不要当成参数错误去排查。
四个必填字段里 `integrated`(是否集成应用:`0` 否 | `1` 是)和 `children`(集成应用需要
包含哪些其他应用的 ID 列表,非集成应用传空数组 `[]`)都容易漏传——创建前先问清楚这个
应用是不是"集成应用"(把多个子应用打包发布的那种),决定这两个字段怎么填。
---
## 附件改名(file
```
put_files_fileID({ fileID, payload: { fileName } })
```
**这套 MCP 工具里附件相关能力只有改名这一个**`zentao-shared` 已提过):上传新附件、
删除附件都不在工具列表里,需要引导用户去网页端操作。`fileName` 必填,改名会连带更新
附件的扩展名(如果新文件名里带了不同的后缀)。