@zzp123/mcp-zentao 1.1.2 → 1.2.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/dist/api/zentaoApi.d.ts +4 -1
- package/dist/api/zentaoApi.js +60 -0
- package/dist/index.js +80 -0
- package/dist/types/zentao.d.ts +24 -0
- package/package.json +4 -2
package/dist/api/zentaoApi.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AssignFeedbackRequest, Bug, BugResolution, BugStatus, Build, CloseFeedbackRequest, CreateBuildRequest, CreateBugRequest, CreateExecutionRequest, CreateFeedbackRequest, CreatePlanRequest, CreateProductRequest, CreateProgramRequest, CreateProjectRequest, CreateStoryRequest, CreateTaskRequest, CreateTestCaseRequest, CreateTicketRequest, CreateUserRequest, Execution, Feedback, Plan, Product, Program, Project, Release, Story, Task, TaskStatus, TaskUpdate, TestCase, Ticket, UpdateBuildRequest, UpdateBugRequest, UpdateExecutionRequest, UpdateFeedbackRequest, UpdatePlanRequest, UpdateProductRequest, UpdateProgramRequest, UpdateProjectRequest, UpdateStoryRequest, UpdateTestCaseRequest, UpdateTicketRequest, UpdateUserRequest, UserDetail, ZentaoConfig } from '../types/zentao';
|
|
1
|
+
import { AssignFeedbackRequest, Bug, BugResolution, BugStatus, Build, CloseFeedbackRequest, CreateBuildRequest, CreateBugRequest, CreateExecutionRequest, CreateFeedbackRequest, CreatePlanRequest, CreateProductRequest, CreateProgramRequest, CreateProjectRequest, CreateStoryRequest, CreateTaskRequest, CreateTestCaseRequest, CreateTicketRequest, CreateUserRequest, Execution, Feedback, FileUploadResponse, Module, ModuleType, Plan, Product, Program, Project, Release, 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;
|
|
@@ -148,4 +148,7 @@ export declare class ZentaoAPI {
|
|
|
148
148
|
deleteTicket(ticketId: number): Promise<{
|
|
149
149
|
message: string;
|
|
150
150
|
}>;
|
|
151
|
+
getModules(type: ModuleType, id: number): Promise<Module[]>;
|
|
152
|
+
uploadFile(uploadRequest: UploadFileRequest): Promise<FileUploadResponse>;
|
|
153
|
+
downloadFile(fileId: number): Promise<Buffer>;
|
|
151
154
|
}
|
package/dist/api/zentaoApi.js
CHANGED
|
@@ -1116,4 +1116,64 @@ export class ZentaoAPI {
|
|
|
1116
1116
|
throw error;
|
|
1117
1117
|
}
|
|
1118
1118
|
}
|
|
1119
|
+
// 模块相关API
|
|
1120
|
+
async getModules(type, id) {
|
|
1121
|
+
try {
|
|
1122
|
+
console.log(`正在获取模块列表,类型: ${type}, ID: ${id}...`);
|
|
1123
|
+
const params = { type, id };
|
|
1124
|
+
const response = await this.request('GET', '/modules', params);
|
|
1125
|
+
console.log('获取模块列表响应:', response);
|
|
1126
|
+
return response.modules;
|
|
1127
|
+
}
|
|
1128
|
+
catch (error) {
|
|
1129
|
+
console.error('获取模块列表失败:', error);
|
|
1130
|
+
throw error;
|
|
1131
|
+
}
|
|
1132
|
+
}
|
|
1133
|
+
// 文件相关API
|
|
1134
|
+
async uploadFile(uploadRequest) {
|
|
1135
|
+
try {
|
|
1136
|
+
console.log(`正在上传文件: ${uploadRequest.filename}...`);
|
|
1137
|
+
const token = await this.getToken();
|
|
1138
|
+
// 创建FormData
|
|
1139
|
+
const FormData = (await import('form-data')).default;
|
|
1140
|
+
const formData = new FormData();
|
|
1141
|
+
formData.append('imgFile', uploadRequest.file, uploadRequest.filename);
|
|
1142
|
+
const params = uploadRequest.uid ? { uid: uploadRequest.uid } : undefined;
|
|
1143
|
+
const response = await this.client.request({
|
|
1144
|
+
method: 'POST',
|
|
1145
|
+
url: '/files',
|
|
1146
|
+
params,
|
|
1147
|
+
data: formData,
|
|
1148
|
+
headers: {
|
|
1149
|
+
Token: token,
|
|
1150
|
+
...formData.getHeaders()
|
|
1151
|
+
},
|
|
1152
|
+
});
|
|
1153
|
+
console.log('上传文件响应:', response.data);
|
|
1154
|
+
return response.data;
|
|
1155
|
+
}
|
|
1156
|
+
catch (error) {
|
|
1157
|
+
console.error('上传文件失败:', error);
|
|
1158
|
+
throw error;
|
|
1159
|
+
}
|
|
1160
|
+
}
|
|
1161
|
+
async downloadFile(fileId) {
|
|
1162
|
+
try {
|
|
1163
|
+
console.log(`正在下载文件 ${fileId}...`);
|
|
1164
|
+
const token = await this.getToken();
|
|
1165
|
+
const response = await this.client.request({
|
|
1166
|
+
method: 'GET',
|
|
1167
|
+
url: `/files/${fileId}`,
|
|
1168
|
+
headers: { Token: token },
|
|
1169
|
+
responseType: 'arraybuffer'
|
|
1170
|
+
});
|
|
1171
|
+
console.log('下载文件成功');
|
|
1172
|
+
return Buffer.from(response.data);
|
|
1173
|
+
}
|
|
1174
|
+
catch (error) {
|
|
1175
|
+
console.error('下载文件失败:', error);
|
|
1176
|
+
throw error;
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1119
1179
|
}
|
package/dist/index.js
CHANGED
|
@@ -920,6 +920,86 @@ server.tool("deleteTicket", { ticketId: z.number() }, async ({ ticketId }) => {
|
|
|
920
920
|
throw new Error("Please initialize Zentao API first");
|
|
921
921
|
return { content: [{ type: "text", text: JSON.stringify(await zentaoApi.deleteTicket(ticketId), null, 2) }] };
|
|
922
922
|
});
|
|
923
|
+
// 模块相关工具
|
|
924
|
+
server.tool("getModules", {
|
|
925
|
+
type: z.enum(['story', 'task', 'bug', 'case', 'feedback', 'product']),
|
|
926
|
+
id: z.number()
|
|
927
|
+
}, async ({ type, id }) => {
|
|
928
|
+
if (!zentaoApi)
|
|
929
|
+
throw new Error("Please initialize Zentao API first");
|
|
930
|
+
const modules = await zentaoApi.getModules(type, id);
|
|
931
|
+
return { content: [{ type: "text", text: JSON.stringify(modules, null, 2) }] };
|
|
932
|
+
});
|
|
933
|
+
// 文件相关工具
|
|
934
|
+
server.tool("uploadFile", {
|
|
935
|
+
filePath: z.string().optional(),
|
|
936
|
+
base64Data: z.string().optional(),
|
|
937
|
+
filename: z.string().optional(),
|
|
938
|
+
uid: z.string().optional()
|
|
939
|
+
}, async ({ filePath, base64Data, filename, uid }) => {
|
|
940
|
+
if (!zentaoApi)
|
|
941
|
+
throw new Error("Please initialize Zentao API first");
|
|
942
|
+
const fs = await import('fs');
|
|
943
|
+
const path = await import('path');
|
|
944
|
+
let fileBuffer;
|
|
945
|
+
let finalFilename;
|
|
946
|
+
let savedPath;
|
|
947
|
+
// 如果提供了 base64 数据(复制的图片)
|
|
948
|
+
if (base64Data) {
|
|
949
|
+
// 创建 img 文件夹(如果不存在)
|
|
950
|
+
const imgDir = path.join(process.cwd(), 'img');
|
|
951
|
+
if (!fs.existsSync(imgDir)) {
|
|
952
|
+
fs.mkdirSync(imgDir, { recursive: true });
|
|
953
|
+
}
|
|
954
|
+
// 处理 base64 数据
|
|
955
|
+
const matches = base64Data.match(/^data:image\/(\w+);base64,(.+)$/);
|
|
956
|
+
if (matches) {
|
|
957
|
+
const ext = matches[1];
|
|
958
|
+
const data = matches[2];
|
|
959
|
+
fileBuffer = Buffer.from(data, 'base64');
|
|
960
|
+
finalFilename = filename || `image_${Date.now()}.${ext}`;
|
|
961
|
+
}
|
|
962
|
+
else {
|
|
963
|
+
// 直接的 base64 数据,没有 data URL 前缀
|
|
964
|
+
fileBuffer = Buffer.from(base64Data, 'base64');
|
|
965
|
+
finalFilename = filename || `image_${Date.now()}.png`;
|
|
966
|
+
}
|
|
967
|
+
// 保存到 img 文件夹
|
|
968
|
+
savedPath = path.join(imgDir, finalFilename);
|
|
969
|
+
fs.writeFileSync(savedPath, fileBuffer);
|
|
970
|
+
}
|
|
971
|
+
// 如果提供了文件路径
|
|
972
|
+
else if (filePath) {
|
|
973
|
+
fileBuffer = fs.readFileSync(filePath);
|
|
974
|
+
finalFilename = path.basename(filePath);
|
|
975
|
+
}
|
|
976
|
+
else {
|
|
977
|
+
throw new Error("必须提供 filePath 或 base64Data 参数");
|
|
978
|
+
}
|
|
979
|
+
const result = await zentaoApi.uploadFile({
|
|
980
|
+
file: fileBuffer,
|
|
981
|
+
filename: finalFilename,
|
|
982
|
+
uid
|
|
983
|
+
});
|
|
984
|
+
const response = {
|
|
985
|
+
upload: result,
|
|
986
|
+
};
|
|
987
|
+
if (savedPath) {
|
|
988
|
+
response.savedPath = savedPath;
|
|
989
|
+
}
|
|
990
|
+
return { content: [{ type: "text", text: JSON.stringify(response, null, 2) }] };
|
|
991
|
+
});
|
|
992
|
+
server.tool("downloadFile", {
|
|
993
|
+
fileId: z.number(),
|
|
994
|
+
savePath: z.string()
|
|
995
|
+
}, async ({ fileId, savePath }) => {
|
|
996
|
+
if (!zentaoApi)
|
|
997
|
+
throw new Error("Please initialize Zentao API first");
|
|
998
|
+
const fs = await import('fs');
|
|
999
|
+
const fileBuffer = await zentaoApi.downloadFile(fileId);
|
|
1000
|
+
fs.writeFileSync(savePath, fileBuffer);
|
|
1001
|
+
return { content: [{ type: "text", text: `文件已下载到: ${savePath}` }] };
|
|
1002
|
+
});
|
|
923
1003
|
// Start receiving messages on stdin and sending messages on stdout
|
|
924
1004
|
const transport = new StdioServerTransport();
|
|
925
1005
|
await server.connect(transport).catch(console.error);
|
package/dist/types/zentao.d.ts
CHANGED
|
@@ -611,3 +611,27 @@ export interface UpdateTicketRequest {
|
|
|
611
611
|
type?: string;
|
|
612
612
|
desc?: string;
|
|
613
613
|
}
|
|
614
|
+
export interface Module {
|
|
615
|
+
id: string;
|
|
616
|
+
root: string;
|
|
617
|
+
branch: string;
|
|
618
|
+
name: string;
|
|
619
|
+
parent: string;
|
|
620
|
+
path: string;
|
|
621
|
+
grade: string;
|
|
622
|
+
order: string;
|
|
623
|
+
type: string;
|
|
624
|
+
owner: string;
|
|
625
|
+
collector?: string;
|
|
626
|
+
short?: string;
|
|
627
|
+
}
|
|
628
|
+
export type ModuleType = 'story' | 'task' | 'bug' | 'case' | 'feedback' | 'product';
|
|
629
|
+
export interface FileUploadResponse {
|
|
630
|
+
id: number;
|
|
631
|
+
url: string;
|
|
632
|
+
}
|
|
633
|
+
export interface UploadFileRequest {
|
|
634
|
+
file: Buffer | Blob;
|
|
635
|
+
filename: string;
|
|
636
|
+
uid?: string;
|
|
637
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zzp123/mcp-zentao",
|
|
3
|
-
"version": "1.1
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "禅道项目管理系统的高级API集成包,提供任务管理、Bug跟踪等功能的完整封装,专为Cursor IDE设计的MCP扩展",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -42,14 +42,16 @@
|
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"@modelcontextprotocol/sdk": "^1.6.1",
|
|
45
|
-
"@zzp123/mcp-zentao": "^1.
|
|
45
|
+
"@zzp123/mcp-zentao": "^1.2.0",
|
|
46
46
|
"axios": "^1.6.7",
|
|
47
47
|
"chalk": "^4.1.2",
|
|
48
|
+
"form-data": "^4.0.4",
|
|
48
49
|
"fs": "^0.0.1-security",
|
|
49
50
|
"table": "^6.8.1",
|
|
50
51
|
"yargs": "^17.7.2"
|
|
51
52
|
},
|
|
52
53
|
"devDependencies": {
|
|
54
|
+
"@types/form-data": "^2.2.1",
|
|
53
55
|
"@types/jest": "^29.5.12",
|
|
54
56
|
"@types/node": "^20.11.19",
|
|
55
57
|
"@types/table": "^6.3.2",
|