@zzp123/mcp-zentao 1.4.0 → 1.4.2

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.
Files changed (3) hide show
  1. package/README.md +78 -14
  2. package/dist/index.js +76 -14
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,13 +1,32 @@
1
1
  # MCP-Zentao
2
2
 
3
+ [![npm version](https://badge.fury.io/js/%40zzp123%2Fmcp-zentao.svg)](https://www.npmjs.com/package/@zzp123/mcp-zentao)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+
3
6
  禅道项目管理系统的高级API集成包,提供任务管理、Bug跟踪等功能的完整封装,专为Cursor IDE设计的MCP扩展。
4
7
 
5
- ## 安装
8
+ ## 📦 安装
6
9
 
7
10
  ```bash
8
- npm install @bigtian/mcp-zentao -g
11
+ npm install @zzp123/mcp-zentao -g
9
12
  ```
10
13
 
14
+ ## 📋 版本历史
15
+
16
+ 查看完整的版本更新历史,请访问 [CHANGELOG.md](./CHANGELOG.md)
17
+
18
+ **最新版本**: v1.4.2
19
+ - 创建完整的版本更新历史文档(CHANGELOG.md)
20
+ - 更新所有文档和示例代码
21
+ - 修正包名和API签名
22
+
23
+ **主要版本**:
24
+ - v1.4.1 - 修复 uploadImageFromClipboard 返回值问题
25
+ - v1.4.0 - 新增解决Bug接口
26
+ - v1.3.1 - 修复剪贴板图片上传核心问题
27
+ - v1.3.0 - 添加命令行脚本支持
28
+ - v1.2.0 - 添加文件上传/下载功能
29
+
11
30
  ## 使用方法
12
31
 
13
32
  ### 首次使用(配置禅道信息)
@@ -158,7 +177,7 @@ docker run -d \
158
177
  ## 基本使用
159
178
 
160
179
  ```typescript
161
- import { ZentaoAPI } from '@bigtian/mcp-zentao';
180
+ import { ZentaoAPI } from '@zzp123/mcp-zentao';
162
181
 
163
182
  // 创建API实例
164
183
  const api = new ZentaoAPI({
@@ -198,19 +217,34 @@ async function finishTask(taskId: number) {
198
217
  }
199
218
  }
200
219
 
201
- // 解决Bug
220
+ // 解决Bug (v1.4.0+)
202
221
  async function resolveBug(bugId: number) {
203
222
  try {
204
- await api.resolveBug(bugId, {
223
+ const result = await api.resolveBug(bugId, {
205
224
  resolution: 'fixed',
206
225
  resolvedBuild: 'trunk',
226
+ assignedTo: 'admin',
207
227
  comment: '问题已修复'
208
228
  });
209
- console.log('Bug已解决');
229
+ console.log('Bug已解决:', result);
210
230
  } catch (error) {
211
231
  console.error('解决Bug失败:', error);
212
232
  }
213
233
  }
234
+
235
+ // 上传剪贴板图片 (v1.3.1+)
236
+ async function uploadClipboardImage() {
237
+ try {
238
+ // 注意:需要先复制图片到系统剪贴板
239
+ const result = await api.uploadFile({
240
+ filename: 'screenshot.png',
241
+ uid: 'optional-uid'
242
+ });
243
+ console.log('图片已上传:', result);
244
+ } catch (error) {
245
+ console.error('上传失败:', error);
246
+ }
247
+ }
214
248
  ```
215
249
 
216
250
  ## API文档
@@ -243,12 +277,22 @@ constructor(config: {
243
277
  - 参数: taskId - 任务ID
244
278
  - 返回: Promise<void>
245
279
 
246
- 4. `resolveBug(bugId: number, resolution: BugResolution): Promise<void>`
280
+ 4. `resolveBug(bugId: number, resolution: ResolveBugRequest): Promise<Bug>` (v1.4.0+)
247
281
  - 解决指定ID的Bug
248
- - 参数:
282
+ - 参数:
249
283
  - bugId - Bug ID
250
284
  - resolution - Bug解决方案
251
- - 返回: Promise<void>
285
+ - 返回: Promise<Bug> - 返回更新后的Bug对象
286
+
287
+ 5. `uploadFile(request: UploadFileRequest): Promise<FileUploadResponse>` (v1.2.0+)
288
+ - 上传文件到禅道
289
+ - 参数: UploadFileRequest - 文件上传请求
290
+ - 返回: Promise<FileUploadResponse> - 包含文件ID和访问URL
291
+
292
+ 6. `downloadFile(fileId: number): Promise<Buffer>` (v1.2.0+)
293
+ - 从禅道下载文件
294
+ - 参数: fileId - 文件ID
295
+ - 返回: Promise<Buffer> - 文件的二进制数据
252
296
 
253
297
  ### 类型定义
254
298
 
@@ -258,6 +302,8 @@ interface Task {
258
302
  name: string;
259
303
  status: string;
260
304
  pri: number;
305
+ assignedTo: string;
306
+ deadline: string;
261
307
  // ... 其他任务属性
262
308
  }
263
309
 
@@ -266,14 +312,32 @@ interface Bug {
266
312
  title: string;
267
313
  status: string;
268
314
  severity: number;
315
+ resolvedBy: string;
316
+ resolution: string;
269
317
  // ... 其他Bug属性
270
318
  }
271
319
 
272
- interface BugResolution {
273
- resolution: string; // 解决方案类型
274
- resolvedBuild?: string; // 解决版本
275
- duplicateBug?: number; // 重复Bug ID
276
- comment?: string; // 备注
320
+ // v1.4.0+
321
+ type ResolutionType = 'fixed' | 'bydesign' | 'duplicate' | 'external' | 'notrepro' | 'postponed' | 'willnotfix';
322
+
323
+ interface ResolveBugRequest {
324
+ resolution: ResolutionType; // 解决方案(必填)
325
+ resolvedBuild?: string; // 解决版本(resolution='fixed'时必填)
326
+ assignedTo?: string; // 指派给
327
+ comment?: string; // 备注
328
+ duplicateBug?: number; // 重复Bug的ID(resolution='duplicate'时必填)
329
+ }
330
+
331
+ // v1.2.0+
332
+ interface UploadFileRequest {
333
+ file: Buffer; // 文件数据
334
+ filename: string; // 文件名
335
+ uid?: string; // 唯一标识符(可选)
336
+ }
337
+
338
+ interface FileUploadResponse {
339
+ id: number; // 文件ID
340
+ url: string; // 文件访问URL
277
341
  }
278
342
  ```
279
343
 
package/dist/index.js CHANGED
@@ -999,18 +999,26 @@ server.tool("uploadImageFromClipboard", {
999
999
  filename: z.string().optional(),
1000
1000
  uid: z.string().optional()
1001
1001
  }, async ({ filename, uid }) => {
1002
- if (!zentaoApi)
1003
- throw new Error("Please initialize Zentao API first");
1002
+ if (!zentaoApi) {
1003
+ return {
1004
+ content: [{
1005
+ type: "text",
1006
+ text: JSON.stringify({ error: "请先初始化禅道API配置" }, null, 2)
1007
+ }],
1008
+ isError: true
1009
+ };
1010
+ }
1004
1011
  const fs = await import('fs');
1005
1012
  const path = await import('path');
1006
1013
  const { execSync } = await import('child_process');
1007
1014
  try {
1015
+ console.log('[uploadImageFromClipboard] 开始执行...');
1008
1016
  // 读取系统剪贴板图片
1009
- let base64Data;
1010
1017
  let fileBuffer;
1011
1018
  let finalFilename;
1012
1019
  // Windows: 使用 PowerShell 读取剪贴板
1013
1020
  if (process.platform === 'win32') {
1021
+ console.log('[uploadImageFromClipboard] Windows平台,使用PowerShell读取剪贴板...');
1014
1022
  const psScript = `
1015
1023
  Add-Type -AssemblyName System.Windows.Forms
1016
1024
  $img = [System.Windows.Forms.Clipboard]::GetImage()
@@ -1028,64 +1036,118 @@ server.tool("uploadImageFromClipboard", {
1028
1036
  stdio: ['pipe', 'pipe', 'pipe']
1029
1037
  }).trim();
1030
1038
  if (!result || result.includes('NoImage') || result.includes('Error')) {
1031
- throw new Error('剪贴板中没有图片。请先复制图片,不要粘贴到输入框,直接告诉我"上传"。');
1039
+ console.error('[uploadImageFromClipboard] 剪贴板中没有图片');
1040
+ return {
1041
+ content: [{
1042
+ type: "text",
1043
+ text: JSON.stringify({
1044
+ error: "剪贴板中没有图片",
1045
+ tip: "请先复制图片,不要粘贴到输入框,直接告诉我'上传'"
1046
+ }, null, 2)
1047
+ }],
1048
+ isError: true
1049
+ };
1032
1050
  }
1033
- base64Data = result;
1034
- fileBuffer = Buffer.from(base64Data, 'base64');
1051
+ fileBuffer = Buffer.from(result, 'base64');
1035
1052
  finalFilename = filename || `clipboard_${Date.now()}.png`;
1053
+ console.log(`[uploadImageFromClipboard] 已读取剪贴板图片,大小: ${fileBuffer.length} bytes`);
1036
1054
  }
1037
1055
  // macOS: 使用 pngpaste
1038
1056
  else if (process.platform === 'darwin') {
1057
+ console.log('[uploadImageFromClipboard] macOS平台,使用pngpaste读取剪贴板...');
1039
1058
  const tempFile = path.join(process.cwd(), '.temp_clipboard.png');
1040
1059
  try {
1041
1060
  execSync(`pngpaste "${tempFile}"`);
1042
1061
  fileBuffer = fs.readFileSync(tempFile);
1043
1062
  fs.unlinkSync(tempFile);
1044
1063
  finalFilename = filename || `clipboard_${Date.now()}.png`;
1064
+ console.log(`[uploadImageFromClipboard] 已读取剪贴板图片,大小: ${fileBuffer.length} bytes`);
1045
1065
  }
1046
- catch {
1047
- throw new Error('剪贴板中没有图片。请先安装 pngpaste: brew install pngpaste');
1066
+ catch (err) {
1067
+ console.error('[uploadImageFromClipboard] macOS读取剪贴板失败:', err);
1068
+ return {
1069
+ content: [{
1070
+ type: "text",
1071
+ text: JSON.stringify({
1072
+ error: "剪贴板中没有图片或pngpaste未安装",
1073
+ tip: "请先安装 pngpaste: brew install pngpaste"
1074
+ }, null, 2)
1075
+ }],
1076
+ isError: true
1077
+ };
1048
1078
  }
1049
1079
  }
1050
1080
  // Linux: 使用 xclip
1051
1081
  else {
1082
+ console.log('[uploadImageFromClipboard] Linux平台,使用xclip读取剪贴板...');
1052
1083
  try {
1053
1084
  const buffer = execSync('xclip -selection clipboard -t image/png -o', {
1054
1085
  maxBuffer: 10 * 1024 * 1024
1055
1086
  });
1056
1087
  fileBuffer = buffer;
1057
1088
  finalFilename = filename || `clipboard_${Date.now()}.png`;
1089
+ console.log(`[uploadImageFromClipboard] 已读取剪贴板图片,大小: ${fileBuffer.length} bytes`);
1058
1090
  }
1059
- catch {
1060
- throw new Error('剪贴板中没有图片。请先安装 xclip: sudo apt-get install xclip');
1091
+ catch (err) {
1092
+ console.error('[uploadImageFromClipboard] Linux读取剪贴板失败:', err);
1093
+ return {
1094
+ content: [{
1095
+ type: "text",
1096
+ text: JSON.stringify({
1097
+ error: "剪贴板中没有图片或xclip未安装",
1098
+ tip: "请先安装 xclip: sudo apt-get install xclip"
1099
+ }, null, 2)
1100
+ }],
1101
+ isError: true
1102
+ };
1061
1103
  }
1062
1104
  }
1063
1105
  // 创建 img 文件夹
1064
1106
  const imgDir = path.join(process.cwd(), 'img');
1065
1107
  if (!fs.existsSync(imgDir)) {
1108
+ console.log(`[uploadImageFromClipboard] 创建目录: ${imgDir}`);
1066
1109
  fs.mkdirSync(imgDir, { recursive: true });
1067
1110
  }
1068
1111
  // 保存到 img 文件夹
1069
1112
  const savedPath = path.join(imgDir, finalFilename);
1070
1113
  fs.writeFileSync(savedPath, fileBuffer);
1114
+ console.log(`[uploadImageFromClipboard] 图片已保存到: ${savedPath}`);
1071
1115
  // 上传到禅道
1072
- const result = await zentaoApi.uploadFile({
1116
+ console.log('[uploadImageFromClipboard] 开始上传到禅道...');
1117
+ const uploadResult = await zentaoApi.uploadFile({
1073
1118
  file: fileBuffer,
1074
1119
  filename: finalFilename,
1075
1120
  uid
1076
1121
  });
1122
+ console.log('[uploadImageFromClipboard] 上传成功,结果:', uploadResult);
1077
1123
  const response = {
1078
- upload: result,
1124
+ success: true,
1125
+ upload: uploadResult,
1079
1126
  savedPath: savedPath,
1127
+ filename: finalFilename,
1128
+ fileSize: fileBuffer.length,
1080
1129
  message: `图片已保存到本地并上传到禅道`
1081
1130
  };
1082
- return { content: [{ type: "text", text: JSON.stringify(response, null, 2) }] };
1131
+ console.log('[uploadImageFromClipboard] 返回结果:', response);
1132
+ return {
1133
+ content: [{
1134
+ type: "text",
1135
+ text: JSON.stringify(response, null, 2)
1136
+ }]
1137
+ };
1083
1138
  }
1084
1139
  catch (error) {
1140
+ console.error('[uploadImageFromClipboard] 发生错误:', error);
1141
+ const errorResponse = {
1142
+ success: false,
1143
+ error: error.message || String(error),
1144
+ stack: error.stack,
1145
+ tip: "请检查:\n1. 确保已复制图片到剪贴板\n2. 不要粘贴到输入框,直接说'上传剪贴板图片'\n3. 或使用命令行: upload.bat"
1146
+ };
1085
1147
  return {
1086
1148
  content: [{
1087
1149
  type: "text",
1088
- text: `错误: ${error.message}\n\n提示:\n1. 确保已复制图片到剪贴板\n2. 不要粘贴到输入框,直接说"上传剪贴板图片"\n3. 或使用命令行: upload.bat`
1150
+ text: JSON.stringify(errorResponse, null, 2)
1089
1151
  }],
1090
1152
  isError: true
1091
1153
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zzp123/mcp-zentao",
3
- "version": "1.4.0",
3
+ "version": "1.4.2",
4
4
  "description": "禅道项目管理系统的高级API集成包,提供任务管理、Bug跟踪等功能的完整封装,专为Cursor IDE设计的MCP扩展",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",