@zzp123/mcp-zentao 1.7.2 → 1.7.4
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 +32 -0
- package/dist/api/zentaoApi.js +17 -2
- package/dist/index.js +69 -53
- package/dist/types/zentao.d.ts +5 -5
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,38 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.7.4] - 2025-11-06
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- **修复 createTask 和 updateStory 中的评审人相关错误**
|
|
12
|
+
- 修复 `createTask` 工具中 `assignedTo` 参数类型错误(从字符串改为数组)
|
|
13
|
+
- 修复 `createTask` 工具中必填参数缺失问题(execution, type, estStarted, deadline)
|
|
14
|
+
- 修复 `updateStory` 工具中"评审人不能为null"错误
|
|
15
|
+
- 为 `updateStory` 添加自动跳过评审机制(needNotReview=true)
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
- `CreateTaskRequest` 接口更新:将 assignedTo 从可选字符串改为必需数组
|
|
19
|
+
- `createTask` MCP 工具参数重新定义:必填参数前置,类型修正
|
|
20
|
+
- `updateStory` API 方法添加智能评审人处理逻辑
|
|
21
|
+
- API 请求表单数据处理:支持数组类型参数的正确格式化
|
|
22
|
+
|
|
23
|
+
### Technical
|
|
24
|
+
- 更新测试文件以适配新的接口要求
|
|
25
|
+
- TypeScript 编译验证通过,确保类型安全
|
|
26
|
+
- 保持向后兼容性,同时修复API规范问题
|
|
27
|
+
|
|
28
|
+
## [1.7.3] - 2025-11-06
|
|
29
|
+
|
|
30
|
+
### Fixed
|
|
31
|
+
- **updateStory 工具参数格式优化**
|
|
32
|
+
- 修复 `update` 参数只能接受对象格式的问题
|
|
33
|
+
- 现在同时支持对象格式和 JSON 字符串格式
|
|
34
|
+
- 自动解析 JSON 字符串并提供友好的错误提示
|
|
35
|
+
|
|
36
|
+
### Changed
|
|
37
|
+
- `update` 参数使用 `z.union()` 同时接受对象和字符串格式
|
|
38
|
+
- 添加 JSON 字符串解析逻辑,提升工具兼容性
|
|
39
|
+
|
|
8
40
|
## [1.7.2] - 2025-11-06
|
|
9
41
|
|
|
10
42
|
### Added
|
package/dist/api/zentaoApi.js
CHANGED
|
@@ -217,7 +217,15 @@ export class ZentaoAPI {
|
|
|
217
217
|
const formData = new URLSearchParams();
|
|
218
218
|
Object.entries(task).forEach(([key, value]) => {
|
|
219
219
|
if (value !== undefined && value !== null) {
|
|
220
|
-
|
|
220
|
+
if (key === 'assignedTo' && Array.isArray(value)) {
|
|
221
|
+
// 对于assignedTo数组,需要特殊处理
|
|
222
|
+
value.forEach((item, index) => {
|
|
223
|
+
formData.append(`${key}[${index}]`, item.toString());
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
formData.append(key, value.toString());
|
|
228
|
+
}
|
|
221
229
|
}
|
|
222
230
|
});
|
|
223
231
|
// 在URL中添加执行ID
|
|
@@ -490,7 +498,14 @@ export class ZentaoAPI {
|
|
|
490
498
|
async updateStory(storyId, update) {
|
|
491
499
|
try {
|
|
492
500
|
console.log(`正在更新需求 ${storyId}...`);
|
|
493
|
-
|
|
501
|
+
// 自动处理评审人问题
|
|
502
|
+
const updateData = { ...update };
|
|
503
|
+
// 如果用户没有设置评审人,也没有指定无需评审,则自动跳过评审
|
|
504
|
+
if (!updateData.reviewer && updateData.needNotReview !== true) {
|
|
505
|
+
updateData.needNotReview = true;
|
|
506
|
+
console.log('自动设置needNotReview=true以跳过评审要求');
|
|
507
|
+
}
|
|
508
|
+
const response = await this.request('PUT', `/stories/${storyId}`, undefined, updateData);
|
|
494
509
|
console.log('更新需求响应:', response);
|
|
495
510
|
return response;
|
|
496
511
|
}
|
package/dist/index.js
CHANGED
|
@@ -197,32 +197,32 @@ server.tool("getProductPlans", {
|
|
|
197
197
|
server.tool("createTask", {
|
|
198
198
|
name: z.string(),
|
|
199
199
|
execution: z.number(),
|
|
200
|
+
type: z.string(),
|
|
201
|
+
assignedTo: z.array(z.string()),
|
|
202
|
+
estStarted: z.string(),
|
|
203
|
+
deadline: z.string(),
|
|
200
204
|
desc: z.string().optional(),
|
|
201
205
|
pri: z.number().min(1).max(4).optional(),
|
|
202
206
|
estimate: z.number().optional(),
|
|
203
207
|
project: z.number().optional(),
|
|
204
208
|
module: z.number().optional(),
|
|
205
|
-
story: z.number().optional()
|
|
206
|
-
type: z.string().optional(),
|
|
207
|
-
assignedTo: z.string().optional(),
|
|
208
|
-
estStarted: z.string().optional(),
|
|
209
|
-
deadline: z.string().optional()
|
|
209
|
+
story: z.number().optional()
|
|
210
210
|
}, async ({ name, execution, desc, pri, estimate, project, module, story, type, assignedTo, estStarted, deadline }) => {
|
|
211
211
|
if (!zentaoApi)
|
|
212
212
|
throw new Error("Please initialize Zentao API first");
|
|
213
213
|
const task = await zentaoApi.createTask({
|
|
214
214
|
name,
|
|
215
215
|
execution,
|
|
216
|
+
type,
|
|
217
|
+
assignedTo,
|
|
218
|
+
estStarted,
|
|
219
|
+
deadline,
|
|
216
220
|
desc,
|
|
217
221
|
pri,
|
|
218
222
|
estimate,
|
|
219
223
|
project,
|
|
220
224
|
module,
|
|
221
|
-
story
|
|
222
|
-
type,
|
|
223
|
-
assignedTo,
|
|
224
|
-
estStarted,
|
|
225
|
-
deadline
|
|
225
|
+
story
|
|
226
226
|
});
|
|
227
227
|
return {
|
|
228
228
|
content: [{ type: "text", text: JSON.stringify(task, null, 2) }]
|
|
@@ -463,52 +463,68 @@ server.tool("getProjects", {
|
|
|
463
463
|
// Add updateStory tool
|
|
464
464
|
server.tool("updateStory", {
|
|
465
465
|
storyId: z.number(),
|
|
466
|
-
update: z.
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
466
|
+
update: z.union([
|
|
467
|
+
z.object({
|
|
468
|
+
// 基本信息
|
|
469
|
+
title: z.string().optional(),
|
|
470
|
+
product: z.number().optional(),
|
|
471
|
+
parent: z.number().optional(),
|
|
472
|
+
module: z.number().optional(),
|
|
473
|
+
branch: z.number().optional(),
|
|
474
|
+
plan: z.union([z.number(), z.array(z.number())]).optional(),
|
|
475
|
+
type: z.string().optional(),
|
|
476
|
+
// 来源信息
|
|
477
|
+
source: z.string().optional(),
|
|
478
|
+
sourceNote: z.string().optional(),
|
|
479
|
+
// 分类与优先级
|
|
480
|
+
category: z.string().optional(),
|
|
481
|
+
pri: z.number().optional(),
|
|
482
|
+
estimate: z.number().optional(),
|
|
483
|
+
// 状态与阶段
|
|
484
|
+
stage: z.string().optional(),
|
|
485
|
+
status: z.string().optional(),
|
|
486
|
+
// 关键词与标识
|
|
487
|
+
keywords: z.string().optional(),
|
|
488
|
+
color: z.string().optional(),
|
|
489
|
+
grade: z.number().optional(),
|
|
490
|
+
// 人员相关
|
|
491
|
+
mailto: z.array(z.string()).optional(),
|
|
492
|
+
reviewer: z.array(z.string()).optional(),
|
|
493
|
+
assignedTo: z.string().optional(),
|
|
494
|
+
closedBy: z.string().optional(),
|
|
495
|
+
feedbackBy: z.string().optional(),
|
|
496
|
+
// 关闭相关
|
|
497
|
+
closedReason: z.enum(['done', 'subdivided', 'duplicate', 'postponed', 'willnotdo', 'cancel', 'bydesign']).optional(),
|
|
498
|
+
duplicateStory: z.number().optional(),
|
|
499
|
+
// 评审相关
|
|
500
|
+
needNotReview: z.boolean().optional(),
|
|
501
|
+
// 通知相关
|
|
502
|
+
notifyEmail: z.string().optional(),
|
|
503
|
+
// 描述内容
|
|
504
|
+
spec: z.string().optional(),
|
|
505
|
+
verify: z.string().optional(),
|
|
506
|
+
// 备注
|
|
507
|
+
comment: z.string().optional()
|
|
508
|
+
}),
|
|
509
|
+
z.string()
|
|
510
|
+
]).describe("需求更新字段 - 支持对象或JSON字符串格式")
|
|
508
511
|
}, async ({ storyId, update }) => {
|
|
509
512
|
if (!zentaoApi)
|
|
510
513
|
throw new Error("Please initialize Zentao API first");
|
|
511
|
-
|
|
514
|
+
// 如果 update 是字符串,尝试解析为对象
|
|
515
|
+
let updateData;
|
|
516
|
+
if (typeof update === 'string') {
|
|
517
|
+
try {
|
|
518
|
+
updateData = JSON.parse(update);
|
|
519
|
+
}
|
|
520
|
+
catch (error) {
|
|
521
|
+
throw new Error(`Invalid JSON string: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
else {
|
|
525
|
+
updateData = update;
|
|
526
|
+
}
|
|
527
|
+
const story = await zentaoApi.updateStory(storyId, updateData);
|
|
512
528
|
return {
|
|
513
529
|
content: [{ type: "text", text: JSON.stringify(story, null, 2) }]
|
|
514
530
|
};
|
package/dist/types/zentao.d.ts
CHANGED
|
@@ -10,13 +10,13 @@ export interface CreateTaskRequest {
|
|
|
10
10
|
pri?: number;
|
|
11
11
|
estimate?: number;
|
|
12
12
|
project?: number;
|
|
13
|
-
execution
|
|
13
|
+
execution: number;
|
|
14
14
|
module?: number;
|
|
15
15
|
story?: number;
|
|
16
|
-
type
|
|
17
|
-
assignedTo
|
|
18
|
-
estStarted
|
|
19
|
-
deadline
|
|
16
|
+
type: string;
|
|
17
|
+
assignedTo: string[];
|
|
18
|
+
estStarted: string;
|
|
19
|
+
deadline: string;
|
|
20
20
|
}
|
|
21
21
|
export interface Task {
|
|
22
22
|
id: number;
|