@dyno181cm.nexsoft/zentao_mcp 1.6.0 → 1.7.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/README.md +16 -28
- package/build/tools/detailTool.js +32 -0
- package/build/tools.js +3 -9
- package/package.json +1 -1
- package/build/tools/bugTool.js +0 -22
- package/build/tools/downloadTool.js +0 -56
- package/build/tools/taskTool.js +0 -22
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
[](https://nodejs.org)
|
|
8
8
|
[](https://www.typescriptlang.org)
|
|
9
9
|
[](https://modelcontextprotocol.io)
|
|
10
|
-
[](https://github.com/dyno-nexsoft/zentao_mcp/tree/master/tests)
|
|
11
11
|
|
|
12
12
|
A **Model Context Protocol (MCP)** server for integrating AI assistants (Claude, Cursor, etc.) with the [ZenTao](https://www.zentao.net) project management API.
|
|
13
13
|
Fetch task details, bug reports, and attachments — all directly inside your AI chat.
|
|
@@ -18,13 +18,12 @@ Fetch task details, bug reports, and attachments — all directly inside your AI
|
|
|
18
18
|
|
|
19
19
|
| Tool | Description |
|
|
20
20
|
|---|---|
|
|
21
|
-
| `
|
|
22
|
-
| `zentao_get_bug_details` | Fetch full details of a bug by ID (severity, repro steps, history & comments, inline images, attachments) |
|
|
23
|
-
| `zentao_download_attachment` | Download any ZenTao file attachment to local disk |
|
|
21
|
+
| `zentao_get_details` | Fetch full details of a task or bug by ID |
|
|
24
22
|
| `zentao_get_comments` | Fetch only the history and comments timeline of a task or bug |
|
|
25
23
|
| `zentao_add_comment` | Add a comment/remark to a task or bug |
|
|
26
24
|
| `zentao_update_task_status` | Update task status (start, finish, close, pause, cancel, restart) and add optional comments/hours |
|
|
27
25
|
| `zentao_update_bug_status` | Update bug status (resolve, close, activate) and add optional comments/resolutions |
|
|
26
|
+
| `zentao_get_assigned_to_me` | Get tasks and bugs currently assigned to you (configured via `ZENTAO_ACCOUNT`) |
|
|
28
27
|
|
|
29
28
|
|
|
30
29
|
**Under the hood:**
|
|
@@ -104,27 +103,13 @@ Add to your MCP client config (e.g. `claude_desktop_config.json`):
|
|
|
104
103
|
|
|
105
104
|
## 🛠️ Available Tools
|
|
106
105
|
|
|
107
|
-
### `
|
|
108
|
-
Get full details of a ZenTao task.
|
|
106
|
+
### `zentao_get_details`
|
|
107
|
+
Get full details of a ZenTao task or bug, including repro steps (for bugs), inline images, attachments, history, and comments.
|
|
109
108
|
|
|
110
109
|
| Parameter | Type | Required | Description |
|
|
111
110
|
|---|---|---|---|
|
|
112
|
-
| `
|
|
113
|
-
|
|
114
|
-
### `zentao_get_bug_details`
|
|
115
|
-
Get full details of a ZenTao bug, including repro steps and inline images.
|
|
116
|
-
|
|
117
|
-
| Parameter | Type | Required | Description |
|
|
118
|
-
|---|---|---|---|
|
|
119
|
-
| `bugId` | `string \| number` | ✅ | Bug ID |
|
|
120
|
-
|
|
121
|
-
### `zentao_download_attachment`
|
|
122
|
-
Download a ZenTao file attachment to local disk.
|
|
123
|
-
|
|
124
|
-
| Parameter | Type | Required | Description |
|
|
125
|
-
|---|---|---|---|
|
|
126
|
-
| `fileId` | `string \| number` | ✅ | File ID to download |
|
|
127
|
-
| `extension` | `string` | ❌ | File extension hint (e.g. `mp4`, `png`) |
|
|
111
|
+
| `type` | `"task" \| "bug"` | ✅ | Type of the object |
|
|
112
|
+
| `id` | `string \| number` | ✅ | Task or Bug ID |
|
|
128
113
|
|
|
129
114
|
### `zentao_get_comments`
|
|
130
115
|
Get only the history and comments timeline of a task or bug.
|
|
@@ -171,6 +156,9 @@ Update a bug's status with optional comments and resolutions.
|
|
|
171
156
|
| `assignedTo` | `string` | ❌ | Optional user account to assign to next |
|
|
172
157
|
| `openedBuild` | `string` | ❌ | Optional build ID where bug was found (for `activate`) |
|
|
173
158
|
|
|
159
|
+
### `zentao_get_assigned_to_me`
|
|
160
|
+
Get tasks and bugs currently assigned to the configured user account. Takes no arguments.
|
|
161
|
+
|
|
174
162
|
---
|
|
175
163
|
|
|
176
164
|
## 🧑💻 Development
|
|
@@ -198,19 +186,19 @@ src/
|
|
|
198
186
|
│ ├── attachmentRenderer.ts # Attachments → Markdown ## Files section
|
|
199
187
|
│ ├── actionFormatter.ts # renderHistoryAndComments
|
|
200
188
|
│ ├── taskFormatter.ts # taskToMarkdown (includes comments)
|
|
201
|
-
│
|
|
189
|
+
│ ├── bugFormatter.ts # bugToMarkdown (includes comments)
|
|
190
|
+
│ └── myWorkFormatter.ts # myWorkToMarkdown (includes comments)
|
|
202
191
|
└── tools/
|
|
203
|
-
├──
|
|
204
|
-
├── bugTool.ts # zentao_get_bug_details
|
|
205
|
-
├── downloadTool.ts # zentao_download_attachment
|
|
192
|
+
├── detailTool.ts # zentao_get_details
|
|
206
193
|
├── commentTool.ts # zentao_get_comments · zentao_add_comment
|
|
207
|
-
|
|
194
|
+
├── statusTool.ts # zentao_update_task_status · zentao_update_bug_status
|
|
195
|
+
└── myWorkTool.ts # zentao_get_assigned_to_me
|
|
208
196
|
```
|
|
209
197
|
|
|
210
198
|
### Running tests
|
|
211
199
|
|
|
212
200
|
```bash
|
|
213
|
-
npm test # Unit tests —
|
|
201
|
+
npm test # Unit tests — 13 tests across ZentaoClient
|
|
214
202
|
npm run test:api # Live API integration test (requires .env)
|
|
215
203
|
```
|
|
216
204
|
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { taskToMarkdown } from "../formatters/taskFormatter.js";
|
|
3
|
+
import { bugToMarkdown } from "../formatters/bugFormatter.js";
|
|
4
|
+
import { buildMcpResponse } from "../utils/mcpResponse.js";
|
|
5
|
+
/**
|
|
6
|
+
* Register the `zentao_get_details` MCP tool on the given server.
|
|
7
|
+
*
|
|
8
|
+
* @param server The MCP Server instance.
|
|
9
|
+
* @param client Authenticated ZentaoClient used to fetch and process data.
|
|
10
|
+
*/
|
|
11
|
+
export function registerDetailTool(server, client) {
|
|
12
|
+
server.registerTool("zentao_get_details", {
|
|
13
|
+
description: "Get detailed information of a task or a bug",
|
|
14
|
+
inputSchema: {
|
|
15
|
+
type: z.enum(["task", "bug"]).describe("Type of the object ('task' or 'bug')"),
|
|
16
|
+
id: z.union([z.string(), z.number()]).describe("Task or Bug ID"),
|
|
17
|
+
},
|
|
18
|
+
}, async ({ type, id }) => {
|
|
19
|
+
let data;
|
|
20
|
+
let markdown;
|
|
21
|
+
const downloadedImages = [];
|
|
22
|
+
if (type === "task") {
|
|
23
|
+
data = await client.getTaskDetails(id);
|
|
24
|
+
markdown = await taskToMarkdown(data, client, downloadedImages);
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
data = await client.getBugDetails(id);
|
|
28
|
+
markdown = await bugToMarkdown(data, client, downloadedImages);
|
|
29
|
+
}
|
|
30
|
+
return await buildMcpResponse(markdown, downloadedImages);
|
|
31
|
+
});
|
|
32
|
+
}
|
package/build/tools.js
CHANGED
|
@@ -13,9 +13,7 @@
|
|
|
13
13
|
import { ZentaoClient } from "./zentaoClient.js";
|
|
14
14
|
import { taskToMarkdown as _taskToMarkdown, } from "./formatters/taskFormatter.js";
|
|
15
15
|
import { bugToMarkdown as _bugToMarkdown, } from "./formatters/bugFormatter.js";
|
|
16
|
-
import {
|
|
17
|
-
import { registerBugTool } from "./tools/bugTool.js";
|
|
18
|
-
import { registerDownloadTool } from "./tools/downloadTool.js";
|
|
16
|
+
import { registerDetailTool } from "./tools/detailTool.js";
|
|
19
17
|
import { registerCommentTool } from "./tools/commentTool.js";
|
|
20
18
|
import { registerStatusTools } from "./tools/statusTool.js";
|
|
21
19
|
import { registerMyWorkTool } from "./tools/myWorkTool.js";
|
|
@@ -37,9 +35,7 @@ export function bugToMarkdown(rawBug, downloadedImages) {
|
|
|
37
35
|
* Registers all Zentao MCP tools on the provided server instance.
|
|
38
36
|
*
|
|
39
37
|
* Available tools:
|
|
40
|
-
* - `
|
|
41
|
-
* - `zentao_get_bug_details` — Fetch full details of a bug by ID.
|
|
42
|
-
* - `zentao_download_attachment` — Download an attachment and save locally.
|
|
38
|
+
* - `zentao_get_details` — Fetch full details of a task or a bug by ID.
|
|
43
39
|
* - `zentao_get_comments` — Fetch history and comments timeline for task/bug.
|
|
44
40
|
* - `zentao_update_task_status` — Update a task's status with comments.
|
|
45
41
|
* - `zentao_update_bug_status` — Update a bug's status with comments.
|
|
@@ -47,9 +43,7 @@ export function bugToMarkdown(rawBug, downloadedImages) {
|
|
|
47
43
|
* @param server The MCP Server instance where the tools will be registered.
|
|
48
44
|
*/
|
|
49
45
|
export function registerTools(server) {
|
|
50
|
-
|
|
51
|
-
registerBugTool(server, client);
|
|
52
|
-
registerDownloadTool(server, client);
|
|
46
|
+
registerDetailTool(server, client);
|
|
53
47
|
registerCommentTool(server, client);
|
|
54
48
|
registerStatusTools(server, client);
|
|
55
49
|
registerMyWorkTool(server, client);
|
package/package.json
CHANGED
package/build/tools/bugTool.js
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
import { bugToMarkdown } from "../formatters/bugFormatter.js";
|
|
3
|
-
import { buildMcpResponse } from "../utils/mcpResponse.js";
|
|
4
|
-
/**
|
|
5
|
-
* Register the `zentao_get_bug_details` MCP tool on the given server.
|
|
6
|
-
*
|
|
7
|
-
* @param server The MCP Server instance.
|
|
8
|
-
* @param client Authenticated ZentaoClient used to fetch and process data.
|
|
9
|
-
*/
|
|
10
|
-
export function registerBugTool(server, client) {
|
|
11
|
-
server.registerTool("zentao_get_bug_details", {
|
|
12
|
-
description: "Get detailed information of a bug",
|
|
13
|
-
inputSchema: {
|
|
14
|
-
bugId: z.union([z.string(), z.number()]).describe("Bug ID"),
|
|
15
|
-
},
|
|
16
|
-
}, async ({ bugId }) => {
|
|
17
|
-
const data = await client.getBugDetails(bugId);
|
|
18
|
-
const downloadedImages = [];
|
|
19
|
-
const markdown = await bugToMarkdown(data, client, downloadedImages);
|
|
20
|
-
return await buildMcpResponse(markdown, downloadedImages);
|
|
21
|
-
});
|
|
22
|
-
}
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
import * as os from "os";
|
|
3
|
-
import * as path from "path";
|
|
4
|
-
import fs from "fs";
|
|
5
|
-
import { mcpText } from "../utils/mcpResponse.js";
|
|
6
|
-
/** Tracks in-flight downloads to deduplicate concurrent requests for the same file. */
|
|
7
|
-
const activeDownloads = new Map();
|
|
8
|
-
/**
|
|
9
|
-
* Download a ZenTao attachment to a local path.
|
|
10
|
-
* Deduplicates concurrent requests for the same target file.
|
|
11
|
-
*/
|
|
12
|
-
async function downloadAttachment(client, fileId, targetPath) {
|
|
13
|
-
if (fs.existsSync(targetPath) && !activeDownloads.has(targetPath)) {
|
|
14
|
-
return `File already exists locally at: ${targetPath}`;
|
|
15
|
-
}
|
|
16
|
-
if (activeDownloads.has(targetPath)) {
|
|
17
|
-
await activeDownloads.get(targetPath);
|
|
18
|
-
return `File downloaded successfully to: ${targetPath}`;
|
|
19
|
-
}
|
|
20
|
-
const downloadPromise = client.downloadFile(fileId, targetPath);
|
|
21
|
-
activeDownloads.set(targetPath, downloadPromise);
|
|
22
|
-
try {
|
|
23
|
-
const savedPath = await downloadPromise;
|
|
24
|
-
return `File downloaded successfully to: ${savedPath}`;
|
|
25
|
-
}
|
|
26
|
-
finally {
|
|
27
|
-
activeDownloads.delete(targetPath);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Register the `zentao_download_attachment` MCP tool on the given server.
|
|
32
|
-
*
|
|
33
|
-
* @param server The MCP Server instance.
|
|
34
|
-
* @param client Authenticated ZentaoClient used for downloading files.
|
|
35
|
-
*/
|
|
36
|
-
export function registerDownloadTool(server, client) {
|
|
37
|
-
server.registerTool("zentao_download_attachment", {
|
|
38
|
-
description: "Download a file attachment from ZenTao and save it locally",
|
|
39
|
-
inputSchema: {
|
|
40
|
-
fileId: z.union([z.string(), z.number()]).describe("File ID to download"),
|
|
41
|
-
extension: z.string().optional().describe("Optional file extension (e.g., mp4, png)"),
|
|
42
|
-
},
|
|
43
|
-
}, async ({ fileId, extension }) => {
|
|
44
|
-
const ext = extension
|
|
45
|
-
? extension.startsWith('.') ? extension : `.${extension}`
|
|
46
|
-
: '';
|
|
47
|
-
const targetPath = path.join(os.tmpdir(), `zentao_file_${fileId}${ext}`);
|
|
48
|
-
try {
|
|
49
|
-
const message = await downloadAttachment(client, fileId, targetPath);
|
|
50
|
-
return mcpText(message);
|
|
51
|
-
}
|
|
52
|
-
catch (error) {
|
|
53
|
-
return mcpText(`Failed to download file: ${error.message}`);
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
}
|
package/build/tools/taskTool.js
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
import { taskToMarkdown } from "../formatters/taskFormatter.js";
|
|
3
|
-
import { buildMcpResponse } from "../utils/mcpResponse.js";
|
|
4
|
-
/**
|
|
5
|
-
* Register the `zentao_get_task_details` MCP tool on the given server.
|
|
6
|
-
*
|
|
7
|
-
* @param server The MCP Server instance.
|
|
8
|
-
* @param client Authenticated ZentaoClient used to fetch and process data.
|
|
9
|
-
*/
|
|
10
|
-
export function registerTaskTool(server, client) {
|
|
11
|
-
server.registerTool("zentao_get_task_details", {
|
|
12
|
-
description: "Get detailed information of a task",
|
|
13
|
-
inputSchema: {
|
|
14
|
-
taskId: z.union([z.string(), z.number()]).describe("Task ID"),
|
|
15
|
-
},
|
|
16
|
-
}, async ({ taskId }) => {
|
|
17
|
-
const data = await client.getTaskDetails(taskId);
|
|
18
|
-
const downloadedImages = [];
|
|
19
|
-
const markdown = await taskToMarkdown(data, client, downloadedImages);
|
|
20
|
-
return await buildMcpResponse(markdown, downloadedImages);
|
|
21
|
-
});
|
|
22
|
-
}
|