@zzp123/mcp-zentao 1.5.0 → 1.6.1

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 CHANGED
@@ -5,6 +5,48 @@ 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.6.1] - 2025-11-05
9
+
10
+ ### Fixed
11
+ - **修复 Windows 剪贴板图片读取问题**
12
+ - 替换为新的 PowerShell 脚本 `scripts/get_clipboard.ps1`
13
+ - 使用 `Add-Type` 加载 `System.Drawing` 程序集,确保正确处理图片
14
+ - 改进错误处理,提供更详细的错误信息
15
+ - 使用 `-ExecutionPolicy Bypass` 确保脚本可以执行
16
+
17
+ ### Changed
18
+ - Windows 平台现在使用外部 PowerShell 脚本文件而非内联脚本
19
+ - 优化了 base64 转换流程,确保内存流正确关闭
20
+
21
+ ## [1.6.0] - 2025-11-05
22
+
23
+ ### Changed - 重大更新
24
+ - **迁移到自定义模块接口** `/custom/modules` - 替代原生 `/modules` 接口
25
+ - 接口路径:`GET /custom/modules`(原 `/modules`)
26
+ - 支持字段过滤功能:通过 `fields` 参数指定返回字段
27
+ - 默认返回精简字段:id、name、parent、grade、type
28
+ - 可选字段:id、root、branch、name、parent、path、grade、order、type、owner、collector、short
29
+
30
+ ### Added
31
+ - 新增 `fields` 参数支持,可大幅减少返回数据量(60-80%)
32
+ - 新增 `ModulesResponse` 接口:`{ modules: SimpleModule[], total: number }`
33
+ - 更新 `SimpleModule` 接口,支持更多可选字段
34
+
35
+ ### Technical
36
+ - 返回数据结构变化:从嵌套树形结构改为扁平化数组
37
+ - 通过 `parent` 字段关联父子关系,通过 `path` 字段表示层级路径
38
+ - 移除 `simplifyModule()` 递归处理方法(不再需要)
39
+ - 接口响应包含 `total` 字段,返回模块总数
40
+
41
+ ### Benefits
42
+ - **性能提升**:支持按需获取字段,减少60-80%数据传输量
43
+ - **更灵活**:可根据实际需求指定返回字段
44
+ - **更标准**:返回格式包含 total 统计信息
45
+
46
+ ### Breaking Changes
47
+ - `getModules()` 返回类型从 `SimpleModule[]` 改为 `ModulesResponse`
48
+ - `SimpleModule` 不再包含 `children` 字段(数据已扁平化)
49
+
8
50
  ## [1.5.0] - 2025-11-05
9
51
 
10
52
  ### Added
package/README.md CHANGED
@@ -15,10 +15,10 @@ npm install @zzp123/mcp-zentao -g
15
15
 
16
16
  查看完整的版本更新历史,请访问 [CHANGELOG.md](./CHANGELOG.md)
17
17
 
18
- **最新版本**: v1.5.0
19
- - 模块数据简化功能 - getModules接口现在只返回核心字段
20
- - 大幅减少数据传输量,提升API响应速度
21
- - 新增 SimpleModule 接口,优化数据结构
18
+ **最新版本**: v1.6.1
19
+ - 修复 Windows 剪贴板图片读取问题
20
+ - 使用新的 PowerShell 脚本确保正确读取剪贴板图片
21
+ - 改进错误处理和日志输出
22
22
 
23
23
  **主要版本**:
24
24
  - v1.4.1 - 修复 uploadImageFromClipboard 返回值问题
@@ -1,4 +1,4 @@
1
- import { AssignFeedbackRequest, Bug, BugStatus, Build, CloseFeedbackRequest, CreateBuildRequest, CreateBugRequest, CreateExecutionRequest, CreateFeedbackRequest, CreatePlanRequest, CreateProductRequest, CreateProgramRequest, CreateProjectRequest, CreateStoryRequest, CreateTaskRequest, CreateTestCaseRequest, CreateTicketRequest, CreateUserRequest, Execution, Feedback, FileUploadResponse, ModuleType, Plan, Product, Program, Project, Release, ResolveBugRequest, SimpleModule, Story, Task, TaskStatus, TaskUpdate, TestCase, Ticket, UpdateBuildRequest, UpdateBugRequest, UpdateExecutionRequest, UpdateFeedbackRequest, UpdatePlanRequest, UpdateProductRequest, UpdateProgramRequest, UpdateProjectRequest, UpdateStoryRequest, UpdateTestCaseRequest, UpdateTicketRequest, UpdateUserRequest, UploadFileRequest, UserDetail, ZentaoConfig } from '../types/zentao';
1
+ import { AssignFeedbackRequest, Bug, BugStatus, Build, CloseFeedbackRequest, CreateBuildRequest, CreateBugRequest, CreateExecutionRequest, CreateFeedbackRequest, CreatePlanRequest, CreateProductRequest, CreateProgramRequest, CreateProjectRequest, CreateStoryRequest, CreateTaskRequest, CreateTestCaseRequest, CreateTicketRequest, CreateUserRequest, Execution, Feedback, FileUploadResponse, ModulesResponse, ModuleType, Plan, Product, Program, Project, Release, ResolveBugRequest, Story, Task, TaskStatus, TaskUpdate, TestCase, Ticket, UpdateBuildRequest, UpdateBugRequest, UpdateExecutionRequest, UpdateFeedbackRequest, UpdatePlanRequest, UpdateProductRequest, UpdateProgramRequest, UpdateProjectRequest, UpdateStoryRequest, UpdateTestCaseRequest, UpdateTicketRequest, UpdateUserRequest, UploadFileRequest, UserDetail, ZentaoConfig } from '../types/zentao';
2
2
  export declare class ZentaoAPI {
3
3
  private config;
4
4
  private client;
@@ -149,13 +149,13 @@ export declare class ZentaoAPI {
149
149
  message: string;
150
150
  }>;
151
151
  /**
152
- * 将完整的Module对象转换为简化的SimpleModule对象
152
+ * 获取模块列表(使用自定义接口,支持字段过滤)
153
+ * @param type 模块类型:story(需求)、bug、case(用例)、task(任务)、feedback(反馈)、product
154
+ * @param id 对象ID:产品ID或项目ID
155
+ * @param fields 可选,指定返回的字段,多个字段用逗号分隔。默认返回:id,name,parent,grade,type
156
+ * @returns Promise<ModulesResponse> 包含模块列表和总数
153
157
  */
154
- private simplifyModule;
155
- /**
156
- * 获取模块列表(返回简化数据)
157
- */
158
- getModules(type: ModuleType, id: number): Promise<SimpleModule[]>;
158
+ getModules(type: ModuleType, id: number, fields?: string): Promise<ModulesResponse>;
159
159
  uploadFile(uploadRequest: UploadFileRequest): Promise<FileUploadResponse>;
160
160
  downloadFile(fileId: number): Promise<Buffer>;
161
161
  }
@@ -1120,34 +1120,23 @@ export class ZentaoAPI {
1120
1120
  }
1121
1121
  // 模块相关API
1122
1122
  /**
1123
- * 将完整的Module对象转换为简化的SimpleModule对象
1123
+ * 获取模块列表(使用自定义接口,支持字段过滤)
1124
+ * @param type 模块类型:story(需求)、bug、case(用例)、task(任务)、feedback(反馈)、product
1125
+ * @param id 对象ID:产品ID或项目ID
1126
+ * @param fields 可选,指定返回的字段,多个字段用逗号分隔。默认返回:id,name,parent,grade,type
1127
+ * @returns Promise<ModulesResponse> 包含模块列表和总数
1124
1128
  */
1125
- simplifyModule(module) {
1126
- const simple = {
1127
- id: module.id,
1128
- name: module.name,
1129
- parent: module.parent,
1130
- grade: module.grade
1131
- };
1132
- // 递归处理子模块
1133
- if (module.children && module.children.length > 0) {
1134
- simple.children = module.children.map(child => this.simplifyModule(child));
1135
- }
1136
- return simple;
1137
- }
1138
- /**
1139
- * 获取模块列表(返回简化数据)
1140
- */
1141
- async getModules(type, id) {
1129
+ async getModules(type, id, fields) {
1142
1130
  try {
1143
- console.log(`正在获取模块列表,类型: ${type}, ID: ${id}...`);
1131
+ console.log(`正在获取模块列表,类型: ${type}, ID: ${id}, 字段: ${fields || '默认'}...`);
1144
1132
  const params = { type, id };
1145
- const response = await this.request('GET', '/modules', params);
1146
- console.log('获取模块列表响应(原始数据):', response);
1147
- // 转换为简化格式
1148
- const simpleModules = response.modules.map(module => this.simplifyModule(module));
1149
- console.log('获取模块列表响应(简化数据):', simpleModules);
1150
- return simpleModules;
1133
+ if (fields) {
1134
+ params.fields = fields;
1135
+ }
1136
+ // 使用新的自定义接口路径
1137
+ const response = await this.request('GET', '/custom/modules', params);
1138
+ console.log(`获取模块列表成功,共 ${response.total} 个模块`);
1139
+ return response;
1151
1140
  }
1152
1141
  catch (error) {
1153
1142
  console.error('获取模块列表失败:', error);
package/dist/index.js CHANGED
@@ -926,15 +926,16 @@ server.tool("deleteTicket", { ticketId: z.number() }, async ({ ticketId }) => {
926
926
  throw new Error("Please initialize Zentao API first");
927
927
  return { content: [{ type: "text", text: JSON.stringify(await zentaoApi.deleteTicket(ticketId), null, 2) }] };
928
928
  });
929
- // 模块相关工具
929
+ // 模块相关工具(使用自定义接口,支持字段过滤)
930
930
  server.tool("getModules", {
931
931
  type: z.enum(['story', 'task', 'bug', 'case', 'feedback', 'product']),
932
- id: z.number()
933
- }, async ({ type, id }) => {
932
+ id: z.number(),
933
+ fields: z.string().optional()
934
+ }, async ({ type, id, fields }) => {
934
935
  if (!zentaoApi)
935
936
  throw new Error("Please initialize Zentao API first");
936
- const modules = await zentaoApi.getModules(type, id);
937
- return { content: [{ type: "text", text: JSON.stringify(modules, null, 2) }] };
937
+ const response = await zentaoApi.getModules(type, id, fields);
938
+ return { content: [{ type: "text", text: JSON.stringify(response, null, 2) }] };
938
939
  });
939
940
  // 文件相关工具
940
941
  server.tool("uploadFile", {
@@ -1016,41 +1017,49 @@ server.tool("uploadImageFromClipboard", {
1016
1017
  // 读取系统剪贴板图片
1017
1018
  let fileBuffer;
1018
1019
  let finalFilename;
1019
- // Windows: 使用 PowerShell 读取剪贴板
1020
+ // Windows: 使用 PowerShell 脚本读取剪贴板
1020
1021
  if (process.platform === 'win32') {
1021
- console.log('[uploadImageFromClipboard] Windows平台,使用PowerShell读取剪贴板...');
1022
- const psScript = `
1023
- Add-Type -AssemblyName System.Windows.Forms
1024
- $img = [System.Windows.Forms.Clipboard]::GetImage()
1025
- if ($img -ne $null) {
1026
- $ms = New-Object System.IO.MemoryStream
1027
- $img.Save($ms, [System.Drawing.Imaging.ImageFormat]::Png)
1028
- [Convert]::ToBase64String($ms.ToArray())
1029
- } else {
1030
- Write-Error "NoImage"
1022
+ console.log('[uploadImageFromClipboard] Windows平台,使用PowerShell脚本读取剪贴板...');
1023
+ // 使用外部 PowerShell 脚本
1024
+ const scriptPath = path.join(process.cwd(), 'scripts', 'get_clipboard.ps1');
1025
+ console.log(`[uploadImageFromClipboard] 脚本路径: ${scriptPath}`);
1026
+ try {
1027
+ const result = execSync(`powershell -ExecutionPolicy Bypass -File "${scriptPath}"`, {
1028
+ encoding: 'utf8',
1029
+ maxBuffer: 10 * 1024 * 1024,
1030
+ stdio: ['pipe', 'pipe', 'pipe']
1031
+ }).trim();
1032
+ if (!result || result.includes('NoImage') || result.includes('Error')) {
1033
+ console.error('[uploadImageFromClipboard] 剪贴板中没有图片');
1034
+ return {
1035
+ content: [{
1036
+ type: "text",
1037
+ text: JSON.stringify({
1038
+ error: "剪贴板中没有图片",
1039
+ tip: "请先复制图片,不要粘贴到输入框,直接告诉我'上传'"
1040
+ }, null, 2)
1041
+ }],
1042
+ isError: true
1043
+ };
1031
1044
  }
1032
- `;
1033
- const result = execSync(`powershell -Command "${psScript.replace(/\n/g, ' ')}"`, {
1034
- encoding: 'utf8',
1035
- maxBuffer: 10 * 1024 * 1024,
1036
- stdio: ['pipe', 'pipe', 'pipe']
1037
- }).trim();
1038
- if (!result || result.includes('NoImage') || result.includes('Error')) {
1039
- console.error('[uploadImageFromClipboard] 剪贴板中没有图片');
1045
+ fileBuffer = Buffer.from(result, 'base64');
1046
+ finalFilename = filename || `clipboard_${Date.now()}.png`;
1047
+ console.log(`[uploadImageFromClipboard] 已读取剪贴板图片,大小: ${fileBuffer.length} bytes`);
1048
+ }
1049
+ catch (err) {
1050
+ console.error('[uploadImageFromClipboard] Windows读取剪贴板失败:', err);
1040
1051
  return {
1041
1052
  content: [{
1042
1053
  type: "text",
1043
1054
  text: JSON.stringify({
1044
- error: "剪贴板中没有图片",
1045
- tip: "请先复制图片,不要粘贴到输入框,直接告诉我'上传'"
1055
+ error: "读取剪贴板失败",
1056
+ details: err.message,
1057
+ tip: "请确保已复制图片到剪贴板,并且 PowerShell 脚本存在于 scripts/get_clipboard.ps1"
1046
1058
  }, null, 2)
1047
1059
  }],
1048
1060
  isError: true
1049
1061
  };
1050
1062
  }
1051
- fileBuffer = Buffer.from(result, 'base64');
1052
- finalFilename = filename || `clipboard_${Date.now()}.png`;
1053
- console.log(`[uploadImageFromClipboard] 已读取剪贴板图片,大小: ${fileBuffer.length} bytes`);
1054
1063
  }
1055
1064
  // macOS: 使用 pngpaste
1056
1065
  else if (process.platform === 'darwin') {
@@ -637,7 +637,18 @@ export interface SimpleModule {
637
637
  name: string;
638
638
  parent: string;
639
639
  grade: string;
640
- children?: SimpleModule[];
640
+ type?: string;
641
+ path?: string;
642
+ root?: string;
643
+ branch?: string;
644
+ order?: string;
645
+ owner?: string;
646
+ collector?: string;
647
+ short?: string;
648
+ }
649
+ export interface ModulesResponse {
650
+ modules: SimpleModule[];
651
+ total: number;
641
652
  }
642
653
  export interface FileUploadResponse {
643
654
  id: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zzp123/mcp-zentao",
3
- "version": "1.5.0",
3
+ "version": "1.6.1",
4
4
  "description": "禅道项目管理系统的高级API集成包,提供任务管理、Bug跟踪等功能的完整封装,专为Cursor IDE设计的MCP扩展",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -0,0 +1,13 @@
1
+ Add-Type -AssemblyName System.Windows.Forms
2
+ Add-Type -AssemblyName System.Drawing
3
+ $img = [System.Windows.Forms.Clipboard]::GetImage()
4
+ if ($img) {
5
+ $ms = New-Object System.IO.MemoryStream
6
+ $img.Save($ms, [System.Drawing.Imaging.ImageFormat]::Png)
7
+ $bytes = $ms.ToArray()
8
+ $ms.Close()
9
+ $base64 = [Convert]::ToBase64String($bytes)
10
+ Write-Output $base64
11
+ } else {
12
+ Write-Error "NoImage"
13
+ }