@zzp123/mcp-zentao 1.11.1 → 1.12.0
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 +24 -0
- package/dist/api/zentaoApi.d.ts +10 -2
- package/dist/api/zentaoApi.js +95 -30
- package/dist/index.js +8 -6
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,30 @@ 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.12.0] - 2025-11-07
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- **字段级别过滤功能** 📦
|
|
12
|
+
- 为 `getMyBugs` 和 `getProductBugs` 添加 `fields` 参数
|
|
13
|
+
- 支持三种字段级别:
|
|
14
|
+
- `basic`: 基本信息(8个核心字段:id, title, status, pri, severity, assignedTo, openedBy, openedDate)
|
|
15
|
+
- `default`: 默认信息(18个常用字段,适合列表展示,**默认使用**)
|
|
16
|
+
- `full`: 完整信息(所有字段)
|
|
17
|
+
- 显著减少数据传输量,提升响应速度
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
- **优化默认返回数据**
|
|
21
|
+
- 默认使用 `default` 字段级别,只返回列表展示所需的字段
|
|
22
|
+
- 保持默认每页 20 条记录不变
|
|
23
|
+
- 需要完整信息时可设置 `fields='full'`
|
|
24
|
+
|
|
25
|
+
### Improved
|
|
26
|
+
- **性能优化**
|
|
27
|
+
- 使用 default 模式减少约 60% 的数据传输量
|
|
28
|
+
- 使用 basic 模式减少约 80% 的数据传输量
|
|
29
|
+
- 更快的响应速度和更低的网络开销
|
|
30
|
+
- 更适合移动端和弱网络环境使用
|
|
31
|
+
|
|
8
32
|
## [1.11.1] - 2025-11-07
|
|
9
33
|
|
|
10
34
|
### Fixed
|
package/dist/api/zentaoApi.d.ts
CHANGED
|
@@ -9,6 +9,12 @@ export declare class ZentaoAPI {
|
|
|
9
9
|
getMyTasks(status?: TaskStatus): Promise<Task[]>;
|
|
10
10
|
getTaskDetail(taskId: number): Promise<Task>;
|
|
11
11
|
getProducts(): Promise<Product[]>;
|
|
12
|
+
/**
|
|
13
|
+
* 过滤 Bug 字段
|
|
14
|
+
* @param bug 原始 Bug 对象
|
|
15
|
+
* @param fields 字段级别
|
|
16
|
+
*/
|
|
17
|
+
private filterBugFields;
|
|
12
18
|
/**
|
|
13
19
|
* 获取 Bug 列表
|
|
14
20
|
*
|
|
@@ -18,9 +24,10 @@ export declare class ZentaoAPI {
|
|
|
18
24
|
* @param limit 每页数量(默认20,最大100)
|
|
19
25
|
* @param branch 分支筛选('all'所有分支/'0'主干/分支ID,默认'all')
|
|
20
26
|
* @param order 排序字段(如:'id_desc'、'pri_desc'等,默认'id_desc')
|
|
27
|
+
* @param fields 返回字段级别('basic'基本/'default'默认/'full'完整,默认'default')
|
|
21
28
|
* @returns Promise<Bug列表及分页信息>
|
|
22
29
|
*/
|
|
23
|
-
getMyBugs(status?: BugStatus, productId?: number, page?: number, limit?: number, branch?: string, order?: string): Promise<{
|
|
30
|
+
getMyBugs(status?: BugStatus, productId?: number, page?: number, limit?: number, branch?: string, order?: string, fields?: 'basic' | 'default' | 'full'): Promise<{
|
|
24
31
|
page: number;
|
|
25
32
|
total: number;
|
|
26
33
|
limit: number;
|
|
@@ -35,9 +42,10 @@ export declare class ZentaoAPI {
|
|
|
35
42
|
* @param status Bug状态筛选(支持多种状态,详见BugStatus类型)
|
|
36
43
|
* @param branch 分支筛选('all'所有分支/'0'主干/分支ID,默认'all')
|
|
37
44
|
* @param order 排序字段(如:'id_desc'、'pri_desc'等,默认'id_desc')
|
|
45
|
+
* @param fields 返回字段级别('basic'基本/'default'默认/'full'完整,默认'default')
|
|
38
46
|
* @returns Promise<Bug列表及分页信息>
|
|
39
47
|
*/
|
|
40
|
-
getProductBugs(productId: number, page?: number, limit?: number, status?: BugStatus, branch?: string, order?: string): Promise<{
|
|
48
|
+
getProductBugs(productId: number, page?: number, limit?: number, status?: BugStatus, branch?: string, order?: string, fields?: 'basic' | 'default' | 'full'): Promise<{
|
|
41
49
|
page: number;
|
|
42
50
|
total: number;
|
|
43
51
|
limit: number;
|
package/dist/api/zentaoApi.js
CHANGED
|
@@ -111,6 +111,51 @@ export class ZentaoAPI {
|
|
|
111
111
|
throw error;
|
|
112
112
|
}
|
|
113
113
|
}
|
|
114
|
+
/**
|
|
115
|
+
* 过滤 Bug 字段
|
|
116
|
+
* @param bug 原始 Bug 对象
|
|
117
|
+
* @param fields 字段级别
|
|
118
|
+
*/
|
|
119
|
+
filterBugFields(bug, fields) {
|
|
120
|
+
if (fields === 'full') {
|
|
121
|
+
return bug;
|
|
122
|
+
}
|
|
123
|
+
if (fields === 'basic') {
|
|
124
|
+
// 基本信息:只返回最核心的字段
|
|
125
|
+
return {
|
|
126
|
+
id: bug.id,
|
|
127
|
+
title: bug.title,
|
|
128
|
+
status: bug.status,
|
|
129
|
+
pri: bug.pri,
|
|
130
|
+
severity: bug.severity,
|
|
131
|
+
assignedTo: bug.assignedTo,
|
|
132
|
+
openedBy: bug.openedBy,
|
|
133
|
+
openedDate: bug.openedDate
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
// default: 默认字段(适合列表展示)
|
|
137
|
+
return {
|
|
138
|
+
id: bug.id,
|
|
139
|
+
title: bug.title,
|
|
140
|
+
status: bug.status,
|
|
141
|
+
statusName: bug.statusName,
|
|
142
|
+
pri: bug.pri,
|
|
143
|
+
severity: bug.severity,
|
|
144
|
+
type: bug.type,
|
|
145
|
+
assignedTo: bug.assignedTo,
|
|
146
|
+
assignedDate: bug.assignedDate,
|
|
147
|
+
openedBy: bug.openedBy,
|
|
148
|
+
openedDate: bug.openedDate,
|
|
149
|
+
deadline: bug.deadline,
|
|
150
|
+
resolvedBy: bug.resolvedBy,
|
|
151
|
+
resolvedDate: bug.resolvedDate,
|
|
152
|
+
confirmed: bug.confirmed,
|
|
153
|
+
module: bug.module,
|
|
154
|
+
moduleTitle: bug.moduleTitle,
|
|
155
|
+
product: bug.product,
|
|
156
|
+
productName: bug.productName
|
|
157
|
+
};
|
|
158
|
+
}
|
|
114
159
|
/**
|
|
115
160
|
* 获取 Bug 列表
|
|
116
161
|
*
|
|
@@ -120,9 +165,10 @@ export class ZentaoAPI {
|
|
|
120
165
|
* @param limit 每页数量(默认20,最大100)
|
|
121
166
|
* @param branch 分支筛选('all'所有分支/'0'主干/分支ID,默认'all')
|
|
122
167
|
* @param order 排序字段(如:'id_desc'、'pri_desc'等,默认'id_desc')
|
|
168
|
+
* @param fields 返回字段级别('basic'基本/'default'默认/'full'完整,默认'default')
|
|
123
169
|
* @returns Promise<Bug列表及分页信息>
|
|
124
170
|
*/
|
|
125
|
-
async getMyBugs(status, productId, page, limit, branch, order) {
|
|
171
|
+
async getMyBugs(status, productId, page, limit, branch, order, fields) {
|
|
126
172
|
if (!productId) {
|
|
127
173
|
// 如果没有提供产品ID,获取第二个可用的产品(索引为1)
|
|
128
174
|
const products = await this.getProducts();
|
|
@@ -138,6 +184,7 @@ export class ZentaoAPI {
|
|
|
138
184
|
const finalPage = page || 1;
|
|
139
185
|
const finalBranch = branch || 'all';
|
|
140
186
|
const finalOrder = order || 'id_desc';
|
|
187
|
+
const finalFields = fields || 'default';
|
|
141
188
|
// 构建查询参数
|
|
142
189
|
const queryParams = new URLSearchParams();
|
|
143
190
|
queryParams.append('branch', finalBranch);
|
|
@@ -149,29 +196,37 @@ export class ZentaoAPI {
|
|
|
149
196
|
queryParams.append('status', status);
|
|
150
197
|
}
|
|
151
198
|
try {
|
|
152
|
-
console.log(`正在获取产品 ${productId} 的Bug列表,参数: status=${status || 'all'}, branch=${finalBranch}, page=${finalPage}, limit=${finalLimit}, order=${finalOrder}`);
|
|
199
|
+
console.log(`正在获取产品 ${productId} 的Bug列表,参数: status=${status || 'all'}, branch=${finalBranch}, page=${finalPage}, limit=${finalLimit}, order=${finalOrder}, fields=${finalFields}`);
|
|
153
200
|
const response = await this.request('GET', `/products/${productId}/bugs?${queryParams.toString()}`);
|
|
154
201
|
console.log(`Bug列表响应: 获取到 ${response.bugs?.length || 0} 条数据`);
|
|
202
|
+
let bugs = [];
|
|
203
|
+
if (Array.isArray(response)) {
|
|
204
|
+
bugs = response;
|
|
205
|
+
}
|
|
206
|
+
else if (response && typeof response === 'object' && Array.isArray(response.bugs)) {
|
|
207
|
+
bugs = response.bugs;
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
throw new Error(`获取Bug列表失败: 响应格式不正确 ${JSON.stringify(response)}`);
|
|
211
|
+
}
|
|
212
|
+
// 应用字段过滤
|
|
213
|
+
const filteredBugs = bugs.map(bug => this.filterBugFields(bug, finalFields));
|
|
155
214
|
if (Array.isArray(response)) {
|
|
156
|
-
// 如果返回的是数组,转换为标准格式
|
|
157
215
|
return {
|
|
158
216
|
page: finalPage,
|
|
159
|
-
total:
|
|
217
|
+
total: filteredBugs.length,
|
|
160
218
|
limit: finalLimit,
|
|
161
|
-
bugs:
|
|
219
|
+
bugs: filteredBugs
|
|
162
220
|
};
|
|
163
221
|
}
|
|
164
|
-
else
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
};
|
|
172
|
-
}
|
|
222
|
+
else {
|
|
223
|
+
return {
|
|
224
|
+
page: response.page || finalPage,
|
|
225
|
+
total: response.total || filteredBugs.length,
|
|
226
|
+
limit: response.limit || finalLimit,
|
|
227
|
+
bugs: filteredBugs
|
|
228
|
+
};
|
|
173
229
|
}
|
|
174
|
-
throw new Error(`获取Bug列表失败: 响应格式不正确 ${JSON.stringify(response)}`);
|
|
175
230
|
}
|
|
176
231
|
catch (error) {
|
|
177
232
|
console.error('获取Bug列表失败:', error);
|
|
@@ -187,16 +242,18 @@ export class ZentaoAPI {
|
|
|
187
242
|
* @param status Bug状态筛选(支持多种状态,详见BugStatus类型)
|
|
188
243
|
* @param branch 分支筛选('all'所有分支/'0'主干/分支ID,默认'all')
|
|
189
244
|
* @param order 排序字段(如:'id_desc'、'pri_desc'等,默认'id_desc')
|
|
245
|
+
* @param fields 返回字段级别('basic'基本/'default'默认/'full'完整,默认'default')
|
|
190
246
|
* @returns Promise<Bug列表及分页信息>
|
|
191
247
|
*/
|
|
192
|
-
async getProductBugs(productId, page, limit, status, branch, order) {
|
|
248
|
+
async getProductBugs(productId, page, limit, status, branch, order, fields) {
|
|
193
249
|
try {
|
|
194
250
|
// 默认每页20条,最多100条
|
|
195
251
|
const finalLimit = limit ? Math.min(limit, 100) : 20;
|
|
196
252
|
const finalPage = page || 1;
|
|
197
253
|
const finalBranch = branch || 'all';
|
|
198
254
|
const finalOrder = order || 'id_desc';
|
|
199
|
-
|
|
255
|
+
const finalFields = fields || 'default';
|
|
256
|
+
console.log(`正在获取产品 ${productId} 的Bug列表 (status=${status || 'all'}, branch=${finalBranch}, page=${finalPage}, limit=${finalLimit}, order=${finalOrder}, fields=${finalFields})...`);
|
|
200
257
|
// 构建查询参数
|
|
201
258
|
const queryParams = new URLSearchParams();
|
|
202
259
|
queryParams.append('branch', finalBranch);
|
|
@@ -209,26 +266,34 @@ export class ZentaoAPI {
|
|
|
209
266
|
}
|
|
210
267
|
const response = await this.request('GET', `/products/${productId}/bugs?${queryParams.toString()}`);
|
|
211
268
|
console.log(`产品Bug列表响应: 获取到 ${response.bugs?.length || 0} 条数据`);
|
|
269
|
+
let bugs = [];
|
|
270
|
+
if (Array.isArray(response)) {
|
|
271
|
+
bugs = response;
|
|
272
|
+
}
|
|
273
|
+
else if (response && typeof response === 'object' && Array.isArray(response.bugs)) {
|
|
274
|
+
bugs = response.bugs;
|
|
275
|
+
}
|
|
276
|
+
else {
|
|
277
|
+
throw new Error(`获取产品Bug列表失败: 响应格式不正确 ${JSON.stringify(response)}`);
|
|
278
|
+
}
|
|
279
|
+
// 应用字段过滤
|
|
280
|
+
const filteredBugs = bugs.map(bug => this.filterBugFields(bug, finalFields));
|
|
212
281
|
if (Array.isArray(response)) {
|
|
213
|
-
// 如果返回的是数组,转换为标准格式
|
|
214
282
|
return {
|
|
215
283
|
page: finalPage,
|
|
216
|
-
total:
|
|
284
|
+
total: filteredBugs.length,
|
|
217
285
|
limit: finalLimit,
|
|
218
|
-
bugs:
|
|
286
|
+
bugs: filteredBugs
|
|
219
287
|
};
|
|
220
288
|
}
|
|
221
|
-
else
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
};
|
|
229
|
-
}
|
|
289
|
+
else {
|
|
290
|
+
return {
|
|
291
|
+
page: response.page || finalPage,
|
|
292
|
+
total: response.total || filteredBugs.length,
|
|
293
|
+
limit: response.limit || finalLimit,
|
|
294
|
+
bugs: filteredBugs
|
|
295
|
+
};
|
|
230
296
|
}
|
|
231
|
-
throw new Error(`获取产品Bug列表失败: 响应格式不正确 ${JSON.stringify(response)}`);
|
|
232
297
|
}
|
|
233
298
|
catch (error) {
|
|
234
299
|
console.error('获取产品Bug列表失败:', error);
|
package/dist/index.js
CHANGED
|
@@ -114,11 +114,12 @@ server.tool("getMyBugs", "获取Bug列表 - 支持多种状态筛选(指派给
|
|
|
114
114
|
page: z.number().optional().describe("页码,从1开始,默认为1"),
|
|
115
115
|
limit: z.number().optional().describe("每页数量,默认20,最大100"),
|
|
116
116
|
branch: z.string().optional().describe("分支筛选:'all'(所有分支,默认)、'0'(主干分支)、分支ID"),
|
|
117
|
-
order: z.string().optional().describe("排序方式,如 id_desc(ID降序), pri_desc(优先级降序), openedDate_desc(创建时间降序)等,默认id_desc")
|
|
118
|
-
|
|
117
|
+
order: z.string().optional().describe("排序方式,如 id_desc(ID降序), pri_desc(优先级降序), openedDate_desc(创建时间降序)等,默认id_desc"),
|
|
118
|
+
fields: z.enum(['basic', 'default', 'full']).optional().describe("返回字段级别:'basic'(基本字段)、'default'(默认字段,推荐)、'full'(完整字段),默认'default'")
|
|
119
|
+
}, async ({ status, productId, page, limit, branch, order, fields }) => {
|
|
119
120
|
if (!zentaoApi)
|
|
120
121
|
throw new Error("Please initialize Zentao API first");
|
|
121
|
-
const result = await zentaoApi.getMyBugs(status, productId, page, limit, branch, order);
|
|
122
|
+
const result = await zentaoApi.getMyBugs(status, productId, page, limit, branch, order, fields);
|
|
122
123
|
// 返回分页信息和数据
|
|
123
124
|
const summary = {
|
|
124
125
|
summary: `当前第 ${result.page} 页,共 ${result.total} 个Bug,本页显示 ${result.bugs.length} 个`,
|
|
@@ -162,11 +163,12 @@ server.tool("getProductBugs", "获取指定产品的Bug列表 - 支持多种状
|
|
|
162
163
|
'bysearch' // 自定义搜索
|
|
163
164
|
]).optional().describe("Bug状态筛选,默认返回所有状态"),
|
|
164
165
|
branch: z.string().optional().describe("分支筛选:'all'(所有分支,默认)、'0'(主干分支)、分支ID"),
|
|
165
|
-
order: z.string().optional().describe("排序方式,如 id_desc(ID降序), pri_desc(优先级降序), openedDate_desc(创建时间降序)等,默认id_desc")
|
|
166
|
-
|
|
166
|
+
order: z.string().optional().describe("排序方式,如 id_desc(ID降序), pri_desc(优先级降序), openedDate_desc(创建时间降序)等,默认id_desc"),
|
|
167
|
+
fields: z.enum(['basic', 'default', 'full']).optional().describe("返回字段级别:'basic'(基本字段)、'default'(默认字段,推荐)、'full'(完整字段),默认'default'")
|
|
168
|
+
}, async ({ productId, page, limit, status, branch, order, fields }) => {
|
|
167
169
|
if (!zentaoApi)
|
|
168
170
|
throw new Error("Please initialize Zentao API first");
|
|
169
|
-
const result = await zentaoApi.getProductBugs(productId, page, limit, status, branch, order);
|
|
171
|
+
const result = await zentaoApi.getProductBugs(productId, page, limit, status, branch, order, fields);
|
|
170
172
|
// 返回分页信息和数据
|
|
171
173
|
const summary = {
|
|
172
174
|
summary: `当前第 ${result.page} 页,共 ${result.total} 个Bug,本页显示 ${result.bugs.length} 个`,
|