@chenyingxian/zentao-mcp 0.1.0 → 0.1.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.
package/.env.example CHANGED
@@ -1,6 +1,8 @@
1
- ZENTAO_BASE_URL=https://zentao.example.com
2
- ZENTAO_ACCOUNT=admin
3
- ZENTAO_PASSWORD=change-me
4
- # Optional: use a pre-issued V1 token instead of logging in with account/password.
5
- ZENTAO_TOKEN=
6
- ZENTAO_TIMEOUT_MS=15000
1
+ ZENTAO_BASE_URL=https://zentao.example.com
2
+ ZENTAO_ACCOUNT=admin
3
+ ZENTAO_PASSWORD=change-me
4
+ # Optional: use a pre-issued V1 token instead of logging in with account/password.
5
+ ZENTAO_TOKEN=
6
+ ZENTAO_TIMEOUT_MS=15000
7
+ # Optional: put the variables above in another local file and expose only this path to your MCP client.
8
+ ZENTAO_CONFIG_FILE=
package/CONFIG.md CHANGED
@@ -19,13 +19,27 @@ ZENTAO_BASE_URL=https://zentao.example.com
19
19
  ZENTAO_TOKEN=your-token
20
20
  ```
21
21
 
22
- ## Optional Variables
23
-
24
- ```bash
25
- ZENTAO_TIMEOUT_MS=15000
26
- ```
27
-
28
- `ZENTAO_TIMEOUT_MS` controls the HTTP request timeout in milliseconds.
22
+ ## Optional Variables
23
+
24
+ ```bash
25
+ ZENTAO_TIMEOUT_MS=15000
26
+ ZENTAO_CONFIG_FILE=/path/to/zentao.env
27
+ ```
28
+
29
+ `ZENTAO_TIMEOUT_MS` controls the HTTP request timeout in milliseconds.
30
+
31
+ `ZENTAO_CONFIG_FILE` points to a local KEY=value config file. This is useful when you do not want to show credentials in the MCP client configuration UI.
32
+
33
+ Example config file:
34
+
35
+ ```bash
36
+ ZENTAO_BASE_URL=https://zentao.example.com
37
+ ZENTAO_ACCOUNT=your-account
38
+ ZENTAO_PASSWORD=your-password
39
+ ZENTAO_TIMEOUT_MS=15000
40
+ ```
41
+
42
+ Environment variables override values from `ZENTAO_CONFIG_FILE`.
29
43
 
30
44
  ## MCP Client Example
31
45
 
@@ -33,8 +47,8 @@ ZENTAO_TIMEOUT_MS=15000
33
47
  {
34
48
  "mcpServers": {
35
49
  "zentao": {
36
- "command": "npx",
37
- "args": ["zentao-mcp"],
50
+ "command": "npx",
51
+ "args": ["-y", "@chenyingxian/zentao-mcp@latest"],
38
52
  "env": {
39
53
  "ZENTAO_BASE_URL": "https://zentao.example.com",
40
54
  "ZENTAO_ACCOUNT": "your-account",
@@ -42,9 +56,25 @@ ZENTAO_TIMEOUT_MS=15000
42
56
  "ZENTAO_TIMEOUT_MS": "15000"
43
57
  }
44
58
  }
45
- }
46
- }
47
- ```
59
+ }
60
+ }
61
+ ```
62
+
63
+ Credentials can also be kept out of the MCP client config:
64
+
65
+ ```json
66
+ {
67
+ "mcpServers": {
68
+ "zentao": {
69
+ "command": "npx",
70
+ "args": ["-y", "@chenyingxian/zentao-mcp@latest"],
71
+ "env": {
72
+ "ZENTAO_CONFIG_FILE": "/path/to/zentao.env"
73
+ }
74
+ }
75
+ }
76
+ }
77
+ ```
48
78
 
49
79
  ## Token Helper
50
80
 
package/CONFIG.zh-CN.md CHANGED
@@ -19,13 +19,27 @@ ZENTAO_BASE_URL=https://zentao.example.com
19
19
  ZENTAO_TOKEN=your-token
20
20
  ```
21
21
 
22
- ## 可选变量
23
-
24
- ```bash
25
- ZENTAO_TIMEOUT_MS=15000
26
- ```
27
-
28
- `ZENTAO_TIMEOUT_MS` 用于控制 HTTP 请求超时时间,单位为毫秒。
22
+ ## 可选变量
23
+
24
+ ```bash
25
+ ZENTAO_TIMEOUT_MS=15000
26
+ ZENTAO_CONFIG_FILE=/path/to/zentao.env
27
+ ```
28
+
29
+ `ZENTAO_TIMEOUT_MS` 用于控制 HTTP 请求超时时间,单位为毫秒。
30
+
31
+ `ZENTAO_CONFIG_FILE` 指向一个本地 KEY=value 配置文件。这样 MCP 客户端配置里只需要展示文件路径,不需要直接展示密码。
32
+
33
+ 配置文件示例:
34
+
35
+ ```bash
36
+ ZENTAO_BASE_URL=https://zentao.example.com
37
+ ZENTAO_ACCOUNT=your-account
38
+ ZENTAO_PASSWORD=your-password
39
+ ZENTAO_TIMEOUT_MS=15000
40
+ ```
41
+
42
+ 环境变量会覆盖 `ZENTAO_CONFIG_FILE` 文件里的同名配置。
29
43
 
30
44
  ## MCP 客户端示例
31
45
 
@@ -33,8 +47,8 @@ ZENTAO_TIMEOUT_MS=15000
33
47
  {
34
48
  "mcpServers": {
35
49
  "zentao": {
36
- "command": "npx",
37
- "args": ["zentao-mcp"],
50
+ "command": "npx",
51
+ "args": ["-y", "@chenyingxian/zentao-mcp@latest"],
38
52
  "env": {
39
53
  "ZENTAO_BASE_URL": "https://zentao.example.com",
40
54
  "ZENTAO_ACCOUNT": "your-account",
@@ -42,9 +56,25 @@ ZENTAO_TIMEOUT_MS=15000
42
56
  "ZENTAO_TIMEOUT_MS": "15000"
43
57
  }
44
58
  }
45
- }
46
- }
47
- ```
59
+ }
60
+ }
61
+ ```
62
+
63
+ 也可以把账号密码放在本地配置文件中,MCP 客户端只配置路径:
64
+
65
+ ```json
66
+ {
67
+ "mcpServers": {
68
+ "zentao": {
69
+ "command": "npx",
70
+ "args": ["-y", "@chenyingxian/zentao-mcp@latest"],
71
+ "env": {
72
+ "ZENTAO_CONFIG_FILE": "/path/to/zentao.env"
73
+ }
74
+ }
75
+ }
76
+ }
77
+ ```
48
78
 
49
79
  ## Token 辅助脚本
50
80
 
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # zentao-mcp
1
+ # @chenyingxian/zentao-mcp
2
2
 
3
3
  ZenTao MCP server for RESTful API v1 and legacy JSON routes.
4
4
 
@@ -12,19 +12,19 @@ This package is intended for self-hosted ZenTao installations where the v1 API i
12
12
 
13
13
  ## Installation
14
14
 
15
- ```bash
16
- npm install -g zentao-mcp
17
- ```
18
-
19
- You can also run it without a global install:
20
-
21
- ```bash
22
- npx zentao-mcp
23
- ```
15
+ ```bash
16
+ npm install -g @chenyingxian/zentao-mcp
17
+ ```
18
+
19
+ You can also run it without a global install:
20
+
21
+ ```bash
22
+ npx @chenyingxian/zentao-mcp
23
+ ```
24
24
 
25
25
  ## Configuration
26
26
 
27
- Set the following environment variables in your MCP client:
27
+ Set the following environment variables in your MCP client:
28
28
 
29
29
  ```bash
30
30
  ZENTAO_BASE_URL=https://zentao.example.com
@@ -42,26 +42,51 @@ ZENTAO_TOKEN=your-token
42
42
  Optional:
43
43
 
44
44
  ```bash
45
- ZENTAO_TIMEOUT_MS=15000
46
- ```
47
-
48
- ## MCP Client Example
49
-
50
- ```json
51
- {
52
- "mcpServers": {
53
- "zentao": {
54
- "command": "npx",
55
- "args": ["zentao-mcp"],
56
- "env": {
57
- "ZENTAO_BASE_URL": "https://zentao.example.com",
58
- "ZENTAO_ACCOUNT": "your-account",
59
- "ZENTAO_PASSWORD": "your-password"
60
- }
61
- }
62
- }
63
- }
64
- ```
45
+ ZENTAO_TIMEOUT_MS=15000
46
+ ```
47
+
48
+ If you do not want to expose credentials directly in the MCP client config, put them in a local config file:
49
+
50
+ ```bash
51
+ ZENTAO_BASE_URL=https://zentao.example.com
52
+ ZENTAO_ACCOUNT=your-account
53
+ ZENTAO_PASSWORD=your-password
54
+ ZENTAO_TIMEOUT_MS=15000
55
+ ```
56
+
57
+ Then expose only the file path to the MCP client:
58
+
59
+ ```json
60
+ {
61
+ "mcpServers": {
62
+ "zentao": {
63
+ "command": "npx",
64
+ "args": ["-y", "@chenyingxian/zentao-mcp@latest"],
65
+ "env": {
66
+ "ZENTAO_CONFIG_FILE": "/path/to/zentao.env"
67
+ }
68
+ }
69
+ }
70
+ }
71
+ ```
72
+
73
+ Environment variables override values from `ZENTAO_CONFIG_FILE`.
74
+
75
+ ## MCP Client Example
76
+
77
+ ```json
78
+ {
79
+ "mcpServers": {
80
+ "zentao": {
81
+ "command": "npx",
82
+ "args": ["-y", "@chenyingxian/zentao-mcp@latest"],
83
+ "env": {
84
+ "ZENTAO_CONFIG_FILE": "/path/to/zentao.env"
85
+ }
86
+ }
87
+ }
88
+ }
89
+ ```
65
90
 
66
91
  ## Get a Token
67
92
 
package/README.zh-CN.md CHANGED
@@ -1,4 +1,4 @@
1
- # zentao-mcp
1
+ # @chenyingxian/zentao-mcp
2
2
 
3
3
  禅道 MCP Server,面向禅道 RESTful API v1 和部分旧版 JSON / 表单路由。
4
4
 
@@ -6,15 +6,15 @@
6
6
 
7
7
  ## 安装
8
8
 
9
- ```bash
10
- npm install -g zentao-mcp
11
- ```
9
+ ```bash
10
+ npm install -g @chenyingxian/zentao-mcp
11
+ ```
12
12
 
13
13
  也可以不全局安装,直接通过 `npx` 运行:
14
14
 
15
- ```bash
16
- npx zentao-mcp
17
- ```
15
+ ```bash
16
+ npx @chenyingxian/zentao-mcp
17
+ ```
18
18
 
19
19
  ## 文档
20
20
 
@@ -32,30 +32,55 @@ ZENTAO_ACCOUNT=your-account
32
32
  ZENTAO_PASSWORD=your-password
33
33
  ```
34
34
 
35
- 也可以直接使用已签发的 v1 token:
35
+ 也可以直接使用已签发的 v1 token:
36
36
 
37
37
  ```bash
38
38
  ZENTAO_BASE_URL=https://zentao.example.com
39
- ZENTAO_TOKEN=your-token
40
- ```
41
-
42
- ## MCP 客户端示例
43
-
44
- ```json
45
- {
46
- "mcpServers": {
47
- "zentao": {
48
- "command": "npx",
49
- "args": ["zentao-mcp"],
50
- "env": {
51
- "ZENTAO_BASE_URL": "https://zentao.example.com",
52
- "ZENTAO_ACCOUNT": "your-account",
53
- "ZENTAO_PASSWORD": "your-password"
54
- }
55
- }
56
- }
57
- }
58
- ```
39
+ ZENTAO_TOKEN=your-token
40
+ ```
41
+
42
+ 如果不希望密码直接展示在 MCP 客户端配置里,可以把真实配置写到本地配置文件:
43
+
44
+ ```bash
45
+ ZENTAO_BASE_URL=https://zentao.example.com
46
+ ZENTAO_ACCOUNT=your-account
47
+ ZENTAO_PASSWORD=your-password
48
+ ZENTAO_TIMEOUT_MS=15000
49
+ ```
50
+
51
+ 然后 MCP 客户端只配置文件路径:
52
+
53
+ ```json
54
+ {
55
+ "mcpServers": {
56
+ "zentao": {
57
+ "command": "npx",
58
+ "args": ["-y", "@chenyingxian/zentao-mcp@latest"],
59
+ "env": {
60
+ "ZENTAO_CONFIG_FILE": "/path/to/zentao.env"
61
+ }
62
+ }
63
+ }
64
+ }
65
+ ```
66
+
67
+ 环境变量会覆盖 `ZENTAO_CONFIG_FILE` 文件里的同名配置。
68
+
69
+ ## MCP 客户端示例
70
+
71
+ ```json
72
+ {
73
+ "mcpServers": {
74
+ "zentao": {
75
+ "command": "npx",
76
+ "args": ["-y", "@chenyingxian/zentao-mcp@latest"],
77
+ "env": {
78
+ "ZENTAO_CONFIG_FILE": "/path/to/zentao.env"
79
+ }
80
+ }
81
+ }
82
+ }
83
+ ```
59
84
 
60
85
  ## 获取 Token
61
86
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chenyingxian/zentao-mcp",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "MCP server for ZenTao RESTful API v1 and legacy JSON routes.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -25,7 +25,7 @@
25
25
  "engines": {
26
26
  "node": ">=18"
27
27
  },
28
- "files": [
28
+ "files": [
29
29
  "src",
30
30
  "scripts",
31
31
  "README.md",
@@ -34,7 +34,10 @@
34
34
  "CONFIG.zh-CN.md",
35
35
  "MCP_TOOLS.md",
36
36
  "MCP_TOOLS.zh-CN.md",
37
- ".env.example"
38
- ],
39
- "license": "MIT"
40
- }
37
+ ".env.example"
38
+ ],
39
+ "publishConfig": {
40
+ "access": "public"
41
+ },
42
+ "license": "MIT"
43
+ }
package/src/index.js CHANGED
@@ -4,10 +4,10 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
4
4
  import { z } from "zod";
5
5
  import { createClientFromEnv } from "./zentao-client.js";
6
6
 
7
- const server = new McpServer({
8
- name: "zentao-mcp",
9
- version: "0.1.0"
10
- });
7
+ const server = new McpServer({
8
+ name: "zentao-mcp",
9
+ version: "0.1.2"
10
+ });
11
11
 
12
12
  server.tool(
13
13
  "zentao_get_my_tasks",
@@ -1,3 +1,4 @@
1
+ import { readFileSync } from "node:fs";
1
2
  import { readFile } from "node:fs/promises";
2
3
  import { basename } from "node:path";
3
4
 
@@ -467,9 +468,57 @@ export class ZentaoClient {
467
468
  * @param {NodeJS.ProcessEnv} env Process environment.
468
469
  * @returns {ZentaoClient} ZenTao client.
469
470
  */
470
- export function createClientFromEnv(env = process.env) {
471
- return new ZentaoClient({ baseUrl: env.ZENTAO_BASE_URL, account: env.ZENTAO_ACCOUNT, password: env.ZENTAO_PASSWORD, token: env.ZENTAO_TOKEN, timeoutMs: env.ZENTAO_TIMEOUT_MS });
472
- }
471
+ export function createClientFromEnv(env = process.env) {
472
+ const fileConfig = env.ZENTAO_CONFIG_FILE ? readEnvConfigFile(env.ZENTAO_CONFIG_FILE) : {};
473
+ const merged = { ...fileConfig, ...compactEnv(env) };
474
+ return new ZentaoClient({ baseUrl: merged.ZENTAO_BASE_URL, account: merged.ZENTAO_ACCOUNT, password: merged.ZENTAO_PASSWORD, token: merged.ZENTAO_TOKEN, timeoutMs: merged.ZENTAO_TIMEOUT_MS });
475
+ }
476
+
477
+ /**
478
+ * Read a simple KEY=value config file.
479
+ * @param {string} filePath Config file path.
480
+ * @returns {Record<string, string>} Parsed config.
481
+ */
482
+ function readEnvConfigFile(filePath) {
483
+ const text = readFileSync(filePath, "utf8");
484
+ return parseEnvFile(text);
485
+ }
486
+
487
+ /**
488
+ * Parse dotenv-like config text without adding a runtime dependency.
489
+ * @param {string} text Raw config text.
490
+ * @returns {Record<string, string>} Parsed key-value pairs.
491
+ */
492
+ function parseEnvFile(text) {
493
+ const result = {};
494
+ for (const line of String(text).split(/\r?\n/)) {
495
+ const trimmed = line.trim();
496
+ if (!trimmed || trimmed.startsWith("#")) continue;
497
+ const match = trimmed.match(/^([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/);
498
+ if (!match) continue;
499
+ result[match[1]] = unquoteEnvValue(match[2].trim());
500
+ }
501
+ return result;
502
+ }
503
+
504
+ /**
505
+ * Remove simple dotenv quotes from one value.
506
+ * @param {string} value Raw config value.
507
+ * @returns {string} Unquoted value.
508
+ */
509
+ function unquoteEnvValue(value) {
510
+ if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) return value.slice(1, -1);
511
+ return value;
512
+ }
513
+
514
+ /**
515
+ * Keep only defined non-empty environment values so config files can provide defaults.
516
+ * @param {NodeJS.ProcessEnv} env Process environment.
517
+ * @returns {Record<string, string>} Compact environment.
518
+ */
519
+ function compactEnv(env) {
520
+ return Object.fromEntries(Object.entries(env).filter(([, value]) => value !== undefined && value !== ""));
521
+ }
473
522
 
474
523
  /**
475
524
  * Normalize a ZenTao site URL.