@dyno181cm.nexsoft/zentao_mcp 1.4.1 → 1.4.3
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/build/tools/commentTool.js +12 -1
- package/build/tools/statusTool.js +6 -2
- package/build/zentaoClient.js +37 -1
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { renderHistoryAndComments } from "../formatters/actionFormatter.js";
|
|
3
|
-
import { buildMcpResponse } from "../utils/mcpResponse.js";
|
|
3
|
+
import { buildMcpResponse, mcpText } from "../utils/mcpResponse.js";
|
|
4
4
|
/**
|
|
5
5
|
* Register the `zentao_get_comments` MCP tool on the given server.
|
|
6
6
|
*
|
|
@@ -31,4 +31,15 @@ export function registerCommentTool(server, client) {
|
|
|
31
31
|
].join("\n\n");
|
|
32
32
|
return buildMcpResponse(output, downloadedImages);
|
|
33
33
|
});
|
|
34
|
+
server.registerTool("zentao_add_comment", {
|
|
35
|
+
description: "Add a comment/remark to a task or a bug",
|
|
36
|
+
inputSchema: {
|
|
37
|
+
type: z.enum(["task", "bug"]).describe("Type of the object ('task' or 'bug')"),
|
|
38
|
+
id: z.union([z.string(), z.number()]).describe("Task or Bug ID"),
|
|
39
|
+
comment: z.string().describe("Comment content"),
|
|
40
|
+
},
|
|
41
|
+
}, async ({ type, id, comment }) => {
|
|
42
|
+
const result = await client.addComment(type, id, comment);
|
|
43
|
+
return mcpText(result.message);
|
|
44
|
+
});
|
|
34
45
|
}
|
|
@@ -29,9 +29,13 @@ export function registerStatusTools(server, client) {
|
|
|
29
29
|
if (action === "finish") {
|
|
30
30
|
// Fetch task details to get realStarted / estStarted if not provided (Zentao requires them)
|
|
31
31
|
const task = await client.getTaskDetails(taskId);
|
|
32
|
-
|
|
32
|
+
let taskRealStarted = task.realStarted || task.estStarted || "";
|
|
33
|
+
if (taskRealStarted.includes("T")) {
|
|
34
|
+
taskRealStarted = taskRealStarted.split("T")[0];
|
|
35
|
+
}
|
|
36
|
+
payload.realStarted = realStarted || taskRealStarted || new Date().toISOString().split("T")[0];
|
|
33
37
|
payload.finishedDate = finishedDate || new Date().toISOString().split("T")[0];
|
|
34
|
-
payload.
|
|
38
|
+
payload.currentConsumed = consumed !== undefined ? consumed : (task.consumed || task.estimate || 1);
|
|
35
39
|
if (assignedTo)
|
|
36
40
|
payload.assignedTo = assignedTo;
|
|
37
41
|
}
|
package/build/zentaoClient.js
CHANGED
|
@@ -175,7 +175,9 @@ export class ZentaoClient {
|
|
|
175
175
|
* Fetches classic JSON API fallback data when REST API returns empty/errors.
|
|
176
176
|
*/
|
|
177
177
|
async getFallbackClassicData(type, id) {
|
|
178
|
-
const webBaseUrl = this.baseUrl.
|
|
178
|
+
const webBaseUrl = this.baseUrl.includes('/api.php/v1')
|
|
179
|
+
? this.baseUrl.split('/api.php/v1')[0]
|
|
180
|
+
: this.baseUrl.split('/api/v1')[0];
|
|
179
181
|
const url = `${webBaseUrl}/${type}-view-${id}.json`;
|
|
180
182
|
const res = await this.client.get(url, {
|
|
181
183
|
baseURL: '', // override baseURL
|
|
@@ -374,4 +376,38 @@ export class ZentaoClient {
|
|
|
374
376
|
async updateBugStatus(bugId, action, payload) {
|
|
375
377
|
return this.post(`/bugs/${bugId}/${action}`, payload);
|
|
376
378
|
}
|
|
379
|
+
/**
|
|
380
|
+
* Adds a comment to a task or a bug using the classic action comment endpoint.
|
|
381
|
+
*
|
|
382
|
+
* @param type The object type ('task' or 'bug').
|
|
383
|
+
* @param id The ID of the object.
|
|
384
|
+
* @param comment The text of the comment to add.
|
|
385
|
+
*/
|
|
386
|
+
async addComment(type, id, comment) {
|
|
387
|
+
if (!this.token) {
|
|
388
|
+
await this.login();
|
|
389
|
+
}
|
|
390
|
+
const webBaseUrl = this.baseUrl.includes('/api.php/v1')
|
|
391
|
+
? this.baseUrl.split('/api.php/v1')[0]
|
|
392
|
+
: this.baseUrl.split('/api/v1')[0];
|
|
393
|
+
const url = `${webBaseUrl}/action-comment-${type}-${id}.json?zentaosid=${this.token}`;
|
|
394
|
+
// Clear the cache so subsequent fetches get the new comment
|
|
395
|
+
this.clearCache();
|
|
396
|
+
const params = new URLSearchParams();
|
|
397
|
+
params.append('comment', comment);
|
|
398
|
+
const res = await this.client.post(url, params, {
|
|
399
|
+
baseURL: '', // override baseURL
|
|
400
|
+
headers: {
|
|
401
|
+
'Content-Type': 'application/x-www-form-urlencoded'
|
|
402
|
+
}
|
|
403
|
+
});
|
|
404
|
+
if (res.status === 200 && typeof res.data === 'string' && res.data.includes('reload')) {
|
|
405
|
+
return { result: 'success', message: 'Comment added successfully' };
|
|
406
|
+
}
|
|
407
|
+
const responseData = typeof res.data === 'string' && res.data.startsWith('{') ? JSON.parse(res.data) : res.data;
|
|
408
|
+
if (responseData && (responseData.status === 'success' || responseData.result === 'success')) {
|
|
409
|
+
return { result: 'success', message: 'Comment added successfully' };
|
|
410
|
+
}
|
|
411
|
+
throw new Error(`Failed to add comment to ${type} #${id}. Response: ${typeof res.data === 'string' ? res.data.substring(0, 200) : JSON.stringify(res.data)}`);
|
|
412
|
+
}
|
|
377
413
|
}
|