@zzp123/mcp-zentao 1.18.8 → 1.18.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1018 -1018
- package/LICENSE +20 -20
- package/README.md +527 -527
- package/dist/api/zentaoApi.js +19 -18
- package/dist/index-dev.js +43 -36
- package/dist/index-pm.js +69 -710
- package/dist/index-qa.js +29 -34
- package/dist/index.js +61 -41
- package/dist/roleConfig.d.ts +0 -4
- package/dist/roleConfig.js +24 -33
- package/dist/types/zentao.d.ts +1 -0
- package/json-args.js +26 -26
- package/package.json +75 -75
- package/scripts/MCP-INTEGRATION.md +298 -298
- package/scripts/README.md +315 -315
- package/scripts/generate-role-versions.cjs +212 -209
- package/scripts/get-clipboard-base64.js +93 -93
- package/scripts/get_clipboard.ps1 +13 -13
- package/scripts/upload-clipboard-image.js +200 -200
- package/scripts/upload-clipboard-image.ps1 +128 -128
- package/scripts/upload-clipboard-image.py +196 -196
- package/scripts/upload.bat.example +41 -41
package/dist/api/zentaoApi.js
CHANGED
|
@@ -55,7 +55,9 @@ export class ZentaoAPI {
|
|
|
55
55
|
}
|
|
56
56
|
catch (error) {
|
|
57
57
|
if (axios.isAxiosError(error)) {
|
|
58
|
-
|
|
58
|
+
const errData = error.response?.data;
|
|
59
|
+
const errMsg = typeof errData === 'object' ? JSON.stringify(errData) : (errData || error.message);
|
|
60
|
+
throw new Error(`请求失败: ${error.response?.status} - ${errMsg}`);
|
|
59
61
|
}
|
|
60
62
|
throw error;
|
|
61
63
|
}
|
|
@@ -477,18 +479,18 @@ export class ZentaoAPI {
|
|
|
477
479
|
}
|
|
478
480
|
async getProductPlans(productId, branch, begin, end, status, parent) {
|
|
479
481
|
try {
|
|
480
|
-
const
|
|
482
|
+
const params = {};
|
|
481
483
|
if (branch !== undefined)
|
|
482
|
-
|
|
484
|
+
params.branch = branch;
|
|
483
485
|
if (begin)
|
|
484
|
-
|
|
486
|
+
params.begin = begin;
|
|
485
487
|
if (end)
|
|
486
|
-
|
|
488
|
+
params.end = end;
|
|
487
489
|
if (status)
|
|
488
|
-
|
|
490
|
+
params.status = status;
|
|
489
491
|
if (parent !== undefined)
|
|
490
|
-
|
|
491
|
-
const response = await this.request('
|
|
492
|
+
params.parent = parent;
|
|
493
|
+
const response = await this.request('GET', `/products/${productId}/plans`, params);
|
|
492
494
|
if (Array.isArray(response)) {
|
|
493
495
|
return response;
|
|
494
496
|
}
|
|
@@ -505,7 +507,12 @@ export class ZentaoAPI {
|
|
|
505
507
|
}
|
|
506
508
|
async createStory(story) {
|
|
507
509
|
try {
|
|
508
|
-
|
|
510
|
+
// 禅道API要求:如果没有指定reviewer,需要设置needNotReview=true跳过评审
|
|
511
|
+
const requestData = {
|
|
512
|
+
...story,
|
|
513
|
+
needNotReview: true
|
|
514
|
+
};
|
|
515
|
+
const response = await this.request('POST', '/stories', undefined, requestData);
|
|
509
516
|
return response;
|
|
510
517
|
}
|
|
511
518
|
catch (error) {
|
|
@@ -532,7 +539,7 @@ export class ZentaoAPI {
|
|
|
532
539
|
}
|
|
533
540
|
async deletePlan(planId) {
|
|
534
541
|
try {
|
|
535
|
-
const response = await this.request('DELETE', `/
|
|
542
|
+
const response = await this.request('DELETE', `/productplans/${planId}`);
|
|
536
543
|
return response;
|
|
537
544
|
}
|
|
538
545
|
catch (error) {
|
|
@@ -705,14 +712,8 @@ export class ZentaoAPI {
|
|
|
705
712
|
*/
|
|
706
713
|
async changeStory(storyId, update) {
|
|
707
714
|
try {
|
|
708
|
-
//
|
|
709
|
-
const
|
|
710
|
-
// 如果用户没有设置评审人,也没有指定无需评审,则自动跳过评审
|
|
711
|
-
if (!updateData.reviewer && updateData.needNotReview !== true) {
|
|
712
|
-
updateData.needNotReview = true;
|
|
713
|
-
}
|
|
714
|
-
// 使用 PUT /stories/:id 接口
|
|
715
|
-
const response = await this.request('PUT', `/stories/${storyId}`, undefined, updateData);
|
|
715
|
+
// 使用 POST /stories/:id/change 接口(变更需求专用接口)
|
|
716
|
+
const response = await this.request('POST', `/stories/${storyId}/change`, undefined, update);
|
|
716
717
|
return response;
|
|
717
718
|
}
|
|
718
719
|
catch (error) {
|
package/dist/index-dev.js
CHANGED
|
@@ -3,6 +3,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { ZentaoAPI } from './api/zentaoApi.js';
|
|
5
5
|
import { loadConfig, saveConfig } from './config.js';
|
|
6
|
+
import { withApi } from './mcpHelpers.js';
|
|
6
7
|
import { interactiveInitTransport, startServerTransport } from './serverTransport.js';
|
|
7
8
|
// 解析命令行参数
|
|
8
9
|
const args = process.argv.slice(2);
|
|
@@ -33,6 +34,7 @@ const server = new McpServer({
|
|
|
33
34
|
});
|
|
34
35
|
// Initialize ZentaoAPI instance
|
|
35
36
|
let zentaoApi = null;
|
|
37
|
+
const getApi = () => zentaoApi;
|
|
36
38
|
export default async function main(params) {
|
|
37
39
|
// 如果传入了配置信息,就保存它
|
|
38
40
|
if (params.config) {
|
|
@@ -55,24 +57,20 @@ server.tool("initZentao", {}, async ({}) => {
|
|
|
55
57
|
});
|
|
56
58
|
server.tool("getMyTasks", {
|
|
57
59
|
status: z.enum(['wait', 'doing', 'done', 'all']).optional()
|
|
58
|
-
}, async ({ status }) => {
|
|
59
|
-
|
|
60
|
-
throw new Error("Please initialize Zentao API first");
|
|
61
|
-
const tasks = await zentaoApi.getMyTasks(status);
|
|
60
|
+
}, withApi(getApi, async (api, { status }) => {
|
|
61
|
+
const tasks = await api.getMyTasks(status);
|
|
62
62
|
return {
|
|
63
63
|
content: [{ type: "text", text: JSON.stringify(tasks, null, 2) }]
|
|
64
64
|
};
|
|
65
|
-
});
|
|
65
|
+
}));
|
|
66
66
|
server.tool("getTaskDetail", {
|
|
67
67
|
taskId: z.number()
|
|
68
|
-
}, async ({ taskId }) => {
|
|
69
|
-
|
|
70
|
-
throw new Error("Please initialize Zentao API first");
|
|
71
|
-
const task = await zentaoApi.getTaskDetail(taskId);
|
|
68
|
+
}, withApi(getApi, async (api, { taskId }) => {
|
|
69
|
+
const task = await api.getTaskDetail(taskId);
|
|
72
70
|
return {
|
|
73
71
|
content: [{ type: "text", text: JSON.stringify(task, null, 2) }]
|
|
74
72
|
};
|
|
75
|
-
});
|
|
73
|
+
}));
|
|
76
74
|
server.tool("getMyBugs", "获取我的Bug列表 - 固定查询指派给我的Bug(status='assigntome'),固定每页20条", {
|
|
77
75
|
productId: z.number().optional().describe("产品ID,默认使用第二个产品"),
|
|
78
76
|
page: z.number().optional().describe("页码,从1开始,默认为1"),
|
|
@@ -100,11 +98,11 @@ server.tool("getMyBugs", "获取我的Bug列表 - 固定查询指派给我的Bug
|
|
|
100
98
|
});
|
|
101
99
|
server.tool("getBugDetail", {
|
|
102
100
|
bugId: z.number(),
|
|
103
|
-
fields: z.enum(['basic', 'detail', 'full']).optional().describe(`
|
|
104
|
-
字段级别:
|
|
105
|
-
- basic: 基本信息(id, title, status, severity, pri等核心字段)
|
|
106
|
-
- detail: 详细信息(包含steps步骤,但不包含files/cases/linkBugs等关联数据)
|
|
107
|
-
- full: 完整信息(包含所有字段,默认值)
|
|
101
|
+
fields: z.enum(['basic', 'detail', 'full']).optional().describe(`
|
|
102
|
+
字段级别:
|
|
103
|
+
- basic: 基本信息(id, title, status, severity, pri等核心字段)
|
|
104
|
+
- detail: 详细信息(包含steps步骤,但不包含files/cases/linkBugs等关联数据)
|
|
105
|
+
- full: 完整信息(包含所有字段,默认值)
|
|
108
106
|
`.trim())
|
|
109
107
|
}, async ({ bugId, fields }) => {
|
|
110
108
|
if (!zentaoApi)
|
|
@@ -225,29 +223,26 @@ server.tool("getProjectReleases", {
|
|
|
225
223
|
};
|
|
226
224
|
});
|
|
227
225
|
server.tool("getStoryDetail", "获取需求详情 - 支持软件需求(story)和用户需求(requirement),自动识别类型", {
|
|
228
|
-
storyId: z.number().describe("需求ID(可以是story或requirement类型)")
|
|
229
|
-
|
|
230
|
-
字段级别:
|
|
231
|
-
- basic: 基本信息(id, title, status, stage, pri等核心字段)
|
|
232
|
-
- detail: 详细信息(包含spec和verify,但不包含executions/tasks/stages/children等关联数据)
|
|
233
|
-
- full: 完整信息(包含所有字段,默认值)
|
|
234
|
-
`.trim())
|
|
235
|
-
}, async ({ storyId, fields }) => {
|
|
226
|
+
storyId: z.number().describe("需求ID(可以是story或requirement类型)")
|
|
227
|
+
}, async ({ storyId }) => {
|
|
236
228
|
if (!zentaoApi)
|
|
237
229
|
throw new Error("Please initialize Zentao API first");
|
|
238
|
-
const story = await zentaoApi.getStoryDetail(storyId,
|
|
239
|
-
//
|
|
230
|
+
const story = await zentaoApi.getStoryDetail(storyId, 'basic');
|
|
231
|
+
// 只返回基本信息
|
|
240
232
|
const result = {
|
|
241
|
-
|
|
242
|
-
|
|
233
|
+
id: story.id,
|
|
234
|
+
title: story.title,
|
|
235
|
+
status: story.status,
|
|
236
|
+
stage: story.stage,
|
|
237
|
+
pri: story.pri,
|
|
238
|
+
type: story.type,
|
|
239
|
+
category: story.category,
|
|
240
|
+
product: story.product,
|
|
241
|
+
productName: story.productName,
|
|
242
|
+
openedBy: story.openedBy,
|
|
243
|
+
openedDate: story.openedDate,
|
|
244
|
+
assignedTo: story.assignedTo
|
|
243
245
|
};
|
|
244
|
-
// 根据字段级别添加提示
|
|
245
|
-
if (fields === 'basic') {
|
|
246
|
-
result.note = '仅显示基本信息,如需完整内容请使用 fields=detail 或 fields=full';
|
|
247
|
-
}
|
|
248
|
-
else if (fields === 'detail') {
|
|
249
|
-
result.note = '显示详细信息但不包含关联数据(executions/tasks/stages/children),如需完整内容请使用 fields=full';
|
|
250
|
-
}
|
|
251
246
|
return {
|
|
252
247
|
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
253
248
|
};
|
|
@@ -258,8 +253,17 @@ server.tool("getProjectExecutions", {
|
|
|
258
253
|
if (!zentaoApi)
|
|
259
254
|
throw new Error("Please initialize Zentao API first");
|
|
260
255
|
const executions = await zentaoApi.getProjectExecutions(projectId);
|
|
256
|
+
// 只返回基本字段
|
|
257
|
+
const simplified = executions.map((e) => ({
|
|
258
|
+
id: e.id,
|
|
259
|
+
name: e.name,
|
|
260
|
+
status: e.status,
|
|
261
|
+
begin: e.begin,
|
|
262
|
+
end: e.end,
|
|
263
|
+
progress: e.progress
|
|
264
|
+
}));
|
|
261
265
|
return {
|
|
262
|
-
content: [{ type: "text", text: JSON.stringify(
|
|
266
|
+
content: [{ type: "text", text: JSON.stringify(simplified, null, 2) }]
|
|
263
267
|
};
|
|
264
268
|
});
|
|
265
269
|
server.tool("getProjects", {
|
|
@@ -269,8 +273,10 @@ server.tool("getProjects", {
|
|
|
269
273
|
if (!zentaoApi)
|
|
270
274
|
throw new Error("Please initialize Zentao API first");
|
|
271
275
|
const projects = await zentaoApi.getProjects(page, limit);
|
|
276
|
+
// 只返回 id 和 name 字段
|
|
277
|
+
const simplified = projects.map((p) => ({ id: p.id, name: p.name }));
|
|
272
278
|
return {
|
|
273
|
-
content: [{ type: "text", text: JSON.stringify(
|
|
279
|
+
content: [{ type: "text", text: JSON.stringify(simplified, null, 2) }]
|
|
274
280
|
};
|
|
275
281
|
});
|
|
276
282
|
server.tool("deleteTask", {
|
|
@@ -341,6 +347,7 @@ server.tool("deleteProject", { projectId: z.number() }, async ({ projectId }) =>
|
|
|
341
347
|
server.tool("createExecution", {
|
|
342
348
|
projectId: z.number(), project: z.number(), name: z.string(), code: z.string(),
|
|
343
349
|
begin: z.string(), end: z.string(), days: z.number().optional(), lifetime: z.string().optional(),
|
|
350
|
+
products: z.array(z.number()).describe("关联产品ID数组"),
|
|
344
351
|
PO: z.string().optional(), PM: z.string().optional(), QD: z.string().optional(),
|
|
345
352
|
RD: z.string().optional(), teamMembers: z.array(z.string()).optional(),
|
|
346
353
|
desc: z.string().optional(), acl: z.string().optional(), whitelist: z.array(z.string()).optional()
|