@xihe-lab/tapd-mcp-server 2.0.0-rc.5 → 2.0.0-rc.7

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/LICENSE CHANGED
@@ -1,3 +1,4 @@
1
+
1
2
  Apache License
2
3
  Version 2.0, January 2004
3
4
  http://www.apache.org/licenses/
@@ -48,7 +49,7 @@
48
49
  "Contribution" shall mean any work of authorship, including
49
50
  the original version of the Work and any modifications or additions
50
51
  to that Work or Derivative Works thereof, that is intentionally
51
- submitted to the Licensor for inclusion in the Work by the copyright owner
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
53
  or by an individual or Legal Entity authorized to submit on behalf of
53
54
  the copyright owner. For the purposes of this definition, "submitted"
54
55
  means any form of electronic, verbal, or written communication sent
@@ -60,7 +61,7 @@
60
61
  designated in writing by the copyright owner as "Not a Contribution."
61
62
 
62
63
  "Contributor" shall mean Licensor and any individual or Legal Entity
63
- on behalf of whom a Contribution has been received by the Licensor and
64
+ on behalf of whom a Contribution has been received by Licensor and
64
65
  subsequently incorporated within the Work.
65
66
 
66
67
  2. Grant of Copyright License. Subject to the terms and conditions of
@@ -106,7 +107,7 @@
106
107
  (d) If the Work includes a "NOTICE" text file as part of its
107
108
  distribution, then any Derivative Works that You distribute must
108
109
  include a readable copy of the attribution notices contained
109
- within such NOTICE file, excluding any notices that do not
110
+ within such NOTICE file, excluding those notices that do not
110
111
  pertain to any part of the Derivative Works, in at least one
111
112
  of the following places: within a NOTICE text file distributed
112
113
  as part of the Derivative Works; within the Source form or
@@ -175,7 +176,18 @@
175
176
 
176
177
  END OF TERMS AND CONDITIONS
177
178
 
178
- Copyright 2025 xihe-lab
179
+ APPENDIX: How to apply the Apache License to your work.
180
+
181
+ To apply the Apache License to your work, attach the following
182
+ boilerplate notice, with the fields enclosed by brackets "[]"
183
+ replaced with your own identifying information. (Don't include
184
+ the brackets!) The text should be enclosed in the appropriate
185
+ comment syntax for the file format. We also recommend that a
186
+ file or class name and description of purpose be included on the
187
+ same "printed page" as the copyright notice for easier
188
+ identification within third-party archives.
189
+
190
+ Copyright [yyyy] [name of copyright owner]
179
191
 
180
192
  Licensed under the Apache License, Version 2.0 (the "License");
181
193
  you may not use this file except in compliance with the License.
package/package.json CHANGED
@@ -1,14 +1,13 @@
1
1
  {
2
2
  "name": "@xihe-lab/tapd-mcp-server",
3
- "version": "2.0.0-rc.5",
3
+ "version": "2.0.0-rc.7",
4
4
  "description": "MCP server for TAPD project management API, enabling AI assistants to manage stories, bugs, tasks, iterations and more via natural language",
5
5
  "type": "module",
6
- "main": "dist/bin/tapd-mcp-server.js",
7
6
  "bin": {
8
7
  "tapd-mcp-server": "./dist/bin/tapd-mcp-server.js"
9
8
  },
10
9
  "scripts": {
11
- "build": "tsc",
10
+ "build": "tsc -p tsconfig.build.json",
12
11
  "start": "node dist/bin/tapd-mcp-server.js",
13
12
  "dev": "tsx src/bin/tapd-mcp-server.ts",
14
13
  "test": "tsx src/update-check.test.ts",
@@ -48,8 +47,11 @@
48
47
  ],
49
48
  "dependencies": {
50
49
  "@modelcontextprotocol/sdk": "^1.0.4",
51
- "@xihe-lab/tapd-core": "2.0.0-rc.5",
50
+ "@xihe-lab/tapd-core": "2.0.0-rc.7",
52
51
  "zod": "^3.25.76"
53
52
  },
54
- "packageManager": "pnpm@12.3.4"
53
+ "packageManager": "pnpm@12.3.4",
54
+ "mirrors": {
55
+ "gitee": "git+https://gitee.com/xihe-lab/tapd-mcp-server.git"
56
+ }
55
57
  }
@@ -1,10 +0,0 @@
1
- /**
2
- * Integration Test Script for Tasks 210-213
3
- *
4
- * Tests:
5
- * - Task 210: tapd_get_image_url
6
- * - Task 212: tapd_get_current_user
7
- * - Task 213: batch fetch functionality
8
- */
9
- export {};
10
- //# sourceMappingURL=integration-test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"integration-test.d.ts","sourceRoot":"","sources":["../src/integration-test.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
@@ -1,117 +0,0 @@
1
- /**
2
- * Integration Test Script for Tasks 210-213
3
- *
4
- * Tests:
5
- * - Task 210: tapd_get_image_url
6
- * - Task 212: tapd_get_current_user
7
- * - Task 213: batch fetch functionality
8
- */
9
- import { TapdClient } from '@xihe-lab/tapd-core';
10
- async function runTests() {
11
- console.log('Starting integration tests...\n');
12
- const client = TapdClient.fromEnv();
13
- const workspaceId = TapdClient.getDefaultWorkspaceId();
14
- if (!workspaceId) {
15
- console.error('ERROR: TAPD_DEFAULT_WORKSPACE_ID must be set');
16
- process.exit(1);
17
- }
18
- const results = [];
19
- // Test 212: tapd_get_current_user
20
- console.log('Test 212: tapd_get_current_user');
21
- try {
22
- const user = await client.get('/users/info');
23
- console.log(' Result:', JSON.stringify(user, null, 2).slice(0, 200));
24
- results.push({ test: 'tapd_get_current_user', status: 'PASS' });
25
- }
26
- catch (error) {
27
- const msg = error instanceof Error ? error.message : String(error);
28
- console.log(' Error:', msg);
29
- results.push({ test: 'tapd_get_current_user', status: 'FAIL', error: msg });
30
- }
31
- // Test 210: tapd_get_image_url
32
- console.log('\nTest 210: tapd_get_image_url');
33
- try {
34
- // Test with a sample image path
35
- const testImagePath = '/tfl/captures/2025/04/test.png';
36
- const imageUrl = await client.get('/files/get_image', {
37
- workspace_id: workspaceId,
38
- image_path: testImagePath,
39
- });
40
- console.log(' Result:', JSON.stringify(imageUrl, null, 2).slice(0, 200));
41
- results.push({ test: 'tapd_get_image_url', status: 'PASS' });
42
- }
43
- catch (error) {
44
- const msg = error instanceof Error ? error.message : String(error);
45
- console.log(' Error:', msg);
46
- // Expected to fail for non-existent image, but API should respond correctly
47
- if (msg.includes('TAPD API error')) {
48
- results.push({ test: 'tapd_get_image_url', status: 'PASS' }); // API responded correctly
49
- }
50
- else {
51
- results.push({ test: 'tapd_get_image_url', status: 'FAIL', error: msg });
52
- }
53
- }
54
- // Test 213: batch fetch stories
55
- console.log('\nTest 213: tapd_batch_fetch_stories');
56
- try {
57
- // Test with a single known story ID
58
- const testIds = ['1']; // Short ID test
59
- const promises = testIds.map(id => client.get('/stories', {
60
- workspace_id: workspaceId,
61
- id: TapdClient.toLongId(id, workspaceId),
62
- }));
63
- const stories = await Promise.all(promises);
64
- console.log(' Fetched stories count:', stories.length);
65
- results.push({ test: 'tapd_batch_fetch_stories', status: 'PASS' });
66
- }
67
- catch (error) {
68
- const msg = error instanceof Error ? error.message : String(error);
69
- console.log(' Error:', msg);
70
- results.push({ test: 'tapd_batch_fetch_stories', status: 'FAIL', error: msg });
71
- }
72
- // Test 213: batch fetch bugs
73
- console.log('\nTest 213: tapd_batch_fetch_bugs');
74
- try {
75
- const testIds = ['1'];
76
- const promises = testIds.map(id => client.get('/bugs', {
77
- workspace_id: workspaceId,
78
- id: TapdClient.toLongId(id, workspaceId),
79
- }));
80
- const bugs = await Promise.all(promises);
81
- console.log(' Fetched bugs count:', bugs.length);
82
- results.push({ test: 'tapd_batch_fetch_bugs', status: 'PASS' });
83
- }
84
- catch (error) {
85
- const msg = error instanceof Error ? error.message : String(error);
86
- console.log(' Error:', msg);
87
- results.push({ test: 'tapd_batch_fetch_bugs', status: 'FAIL', error: msg });
88
- }
89
- // Test 213: batch fetch tasks
90
- console.log('\nTest 213: tapd_batch_fetch_tasks');
91
- try {
92
- const testIds = ['1'];
93
- const promises = testIds.map(id => client.get('/tasks', {
94
- workspace_id: workspaceId,
95
- id: TapdClient.toLongId(id, workspaceId),
96
- }));
97
- const tasks = await Promise.all(promises);
98
- console.log(' Fetched tasks count:', tasks.length);
99
- results.push({ test: 'tapd_batch_fetch_tasks', status: 'PASS' });
100
- }
101
- catch (error) {
102
- const msg = error instanceof Error ? error.message : String(error);
103
- console.log(' Error:', msg);
104
- results.push({ test: 'tapd_batch_fetch_tasks', status: 'FAIL', error: msg });
105
- }
106
- // Summary
107
- console.log('\n=== Test Summary ===');
108
- const passed = results.filter(r => r.status === 'PASS').length;
109
- const failed = results.filter(r => r.status === 'FAIL').length;
110
- console.log(`Total: ${results.length}, PASS: ${passed}, FAIL: ${failed}`);
111
- for (const r of results) {
112
- console.log(` ${r.status}: ${r.test}${r.error ? ` - ${r.error.slice(0, 100)}` : ''}`);
113
- }
114
- process.exit(failed > 0 ? 1 : 0);
115
- }
116
- void runTests();
117
- //# sourceMappingURL=integration-test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"integration-test.js","sourceRoot":"","sources":["../src/integration-test.ts"],"names":[],"mappings":"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"}
@@ -1,6 +0,0 @@
1
- /**
2
- * update-check 单元测试:版本比较 / 开关 / registry 解析 / 提示组装 / 端到端注入
3
- * 运行:tsx src/update-check.test.ts(零网络依赖,registry 探针全部注入 mock)
4
- */
5
- export {};
6
- //# sourceMappingURL=update-check.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"update-check.test.d.ts","sourceRoot":"","sources":["../src/update-check.test.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
@@ -1,164 +0,0 @@
1
- /**
2
- * update-check 单元测试:版本比较 / 开关 / registry 解析 / 提示组装 / 端到端注入
3
- * 运行:tsx src/update-check.test.ts(零网络依赖,registry 探针全部注入 mock)
4
- */
5
- import assert from 'node:assert/strict';
6
- import { buildUpdateNotice, checkForUpdate, compareVersions, fetchRcVersion, isUpdateCheckDisabled, packumentUrl, readLocalVersions, resolveRegistryBase, } from './update-check.js';
7
- const checks = [
8
- // ---- 版本比较 ----
9
- ['compareVersions: 相同版本为 0', () => {
10
- assert.equal(compareVersions('2.0.0-rc.3', '2.0.0-rc.3'), 0);
11
- }],
12
- ['compareVersions: rc 序号按数值比较(rc.3 < rc.10)', () => {
13
- assert.equal(compareVersions('2.0.0-rc.3', '2.0.0-rc.10'), -1);
14
- assert.equal(compareVersions('2.0.0-rc.10', '2.0.0-rc.3'), 1);
15
- }],
16
- ['compareVersions: GA > 同号 rc', () => {
17
- assert.equal(compareVersions('2.0.0', '2.0.0-rc.5'), 1);
18
- assert.equal(compareVersions('2.0.0-rc.5', '2.0.0'), -1);
19
- }],
20
- ['compareVersions: 主次补丁位决定先后', () => {
21
- assert.equal(compareVersions('1.4.4', '2.0.0-rc.3'), -1);
22
- assert.equal(compareVersions('2.0.0-rc.3', '2.1.0-rc.1'), -1);
23
- assert.equal(compareVersions('2.0.1-rc.1', '2.0.0-rc.9'), 1);
24
- }],
25
- ['compareVersions: 无法解析不产生结论', () => {
26
- assert.equal(compareVersions('not-a-version', '2.0.0-rc.3'), 0);
27
- assert.equal(compareVersions('2.0.0-rc.3', ''), 0);
28
- }],
29
- // ---- 环境开关 ----
30
- ['isUpdateCheckDisabled: 默认开启', () => {
31
- assert.equal(isUpdateCheckDisabled({}), false);
32
- assert.equal(isUpdateCheckDisabled({ TAPD_MCP_UPDATE_CHECK: 'on' }), false);
33
- assert.equal(isUpdateCheckDisabled({ TAPD_MCP_UPDATE_CHECK: '' }), false);
34
- }],
35
- ['isUpdateCheckDisabled: off/false/0(含大小写与空白)关闭', () => {
36
- assert.equal(isUpdateCheckDisabled({ TAPD_MCP_UPDATE_CHECK: 'off' }), true);
37
- assert.equal(isUpdateCheckDisabled({ TAPD_MCP_UPDATE_CHECK: ' OFF ' }), true);
38
- assert.equal(isUpdateCheckDisabled({ TAPD_MCP_UPDATE_CHECK: 'false' }), true);
39
- assert.equal(isUpdateCheckDisabled({ TAPD_MCP_UPDATE_CHECK: '0' }), true);
40
- }],
41
- // ---- registry 解析 ----
42
- ['resolveRegistryBase: 缺省 npmjs,尊重 npm_config_registry 并去尾斜杠', () => {
43
- assert.equal(resolveRegistryBase({}), 'https://registry.npmjs.org');
44
- assert.equal(resolveRegistryBase({ npm_config_registry: 'https://registry.npmmirror.com/' }), 'https://registry.npmmirror.com');
45
- assert.equal(resolveRegistryBase({ NPM_CONFIG_REGISTRY: 'https://mirror.example.com/api' }), 'https://mirror.example.com/api');
46
- assert.equal(resolveRegistryBase({ npm_config_registry: ' ' }), 'https://registry.npmjs.org');
47
- }],
48
- ['packumentUrl: scope 斜杠编码为 %2F', () => {
49
- assert.equal(packumentUrl('https://registry.npmjs.org', '@xihe-lab/tapd-core'), 'https://registry.npmjs.org/@xihe-lab%2Ftapd-core');
50
- }],
51
- // ---- 本地版本解析 ----
52
- ['readLocalVersions: 能从本模块定位自身 package.json', () => {
53
- const local = readLocalVersions(import.meta.url);
54
- assert.ok(local !== null, '应能解析自身版本');
55
- assert.match(local.server ?? '', /^\d+\.\d+\.\d+/);
56
- // 工作区(symlink)/npx 树均可解析;独立无 node_modules 的检出允许为 null
57
- if (local.core !== null)
58
- assert.match(local.core, /^\d+\.\d+\.\d+/);
59
- }],
60
- // ---- 提示组装 ----
61
- ['buildUpdateNotice: 双双落后时合并提示并给重启指引', () => {
62
- const notice = buildUpdateNotice({ server: '2.0.0-rc.3', core: '2.0.0-rc.3' }, { server: '2.0.0-rc.5', core: '2.0.0-rc.5' });
63
- assert.ok(notice !== null);
64
- assert.match(notice, /tapd-mcp-server 有新版本可用(2\.0\.0-rc\.3 → 2\.0\.0-rc\.5)/);
65
- assert.match(notice, /tapd-core 有新版本可用(2\.0\.0-rc\.3 → 2\.0\.0-rc\.5)/);
66
- assert.match(notice, /重启 MCP 会话即可更新/);
67
- }],
68
- ['buildUpdateNotice: 仅内核落后时只提内核', () => {
69
- const notice = buildUpdateNotice({ server: '2.0.0-rc.5', core: '2.0.0-rc.3' }, { server: '2.0.0-rc.5', core: '2.0.0-rc.4' });
70
- assert.ok(notice !== null);
71
- assert.match(notice, /tapd-core 有新版本可用/);
72
- assert.doesNotMatch(notice, /tapd-mcp-server 有新版本/);
73
- }],
74
- ['buildUpdateNotice: 已是最新时返回 null', () => {
75
- assert.equal(buildUpdateNotice({ server: '2.0.0-rc.5', core: '2.0.0-rc.5' }, { server: '2.0.0-rc.5', core: '2.0.0-rc.5' }), null);
76
- assert.equal(buildUpdateNotice({ server: '2.0.0-rc.5', core: '2.0.0-rc.5' }, { server: null, core: null }), null);
77
- }],
78
- ['buildUpdateNotice: 本地解析不到内核时仍提示 registry 版本', () => {
79
- const notice = buildUpdateNotice({ server: '2.0.0-rc.3', core: null }, { server: null, core: '2.0.0-rc.9' });
80
- assert.ok(notice !== null);
81
- assert.match(notice, /tapd-core 有新版本可用(2\.0\.0-rc\.9)/);
82
- }],
83
- // ---- 端到端(注入探针与出口) ----
84
- ['checkForUpdate: 有更新时经 notify 发出一条提示', async () => {
85
- const messages = [];
86
- await checkForUpdate({
87
- env: {},
88
- fromUrl: import.meta.url,
89
- fetchRc: (name) => (name === '@xihe-lab/tapd-core' ? '2.0.0-rc.99' : null),
90
- notify: (message) => {
91
- messages.push(message);
92
- },
93
- });
94
- assert.equal(messages.length, 1);
95
- assert.match(messages[0] ?? '', /重启 MCP 会话即可更新/);
96
- }],
97
- ['checkForUpdate: TAPD_MCP_UPDATE_CHECK=off 时不探查不提示', async () => {
98
- let probed = 0;
99
- const messages = [];
100
- await checkForUpdate({
101
- env: { TAPD_MCP_UPDATE_CHECK: 'off' },
102
- fromUrl: import.meta.url,
103
- fetchRc: () => {
104
- probed += 1;
105
- return '2.0.0-rc.99';
106
- },
107
- notify: (message) => {
108
- messages.push(message);
109
- },
110
- });
111
- assert.equal(probed, 0);
112
- assert.equal(messages.length, 0);
113
- }],
114
- ['checkForUpdate: registry 全部不可达时静默跳过', async () => {
115
- const messages = [];
116
- await checkForUpdate({
117
- env: {},
118
- fromUrl: import.meta.url,
119
- fetchRc: () => null,
120
- notify: (message) => {
121
- messages.push(message);
122
- },
123
- });
124
- assert.equal(messages.length, 0);
125
- }],
126
- ['checkForUpdate: 探针抛错被吞掉且不影响调用方', async () => {
127
- const messages = [];
128
- await assert.doesNotReject(checkForUpdate({
129
- env: {},
130
- fromUrl: import.meta.url,
131
- fetchRc: () => {
132
- throw new Error('network down');
133
- },
134
- notify: (message) => {
135
- messages.push(message);
136
- },
137
- }));
138
- assert.equal(messages.length, 0);
139
- }],
140
- ['fetchRcVersion: 连接失败返回 null(不抛错)', async () => {
141
- const result = await fetchRcVersion('https://127.0.0.1:1', '@xihe-lab/tapd-core', 500);
142
- assert.equal(result, null);
143
- }],
144
- ];
145
- let failed = 0;
146
- for (const [name, fn] of checks) {
147
- try {
148
- await fn();
149
- console.log(`✓ ${name}`);
150
- }
151
- catch (error) {
152
- failed += 1;
153
- console.error(`✗ ${name}`);
154
- console.error(` ${error instanceof Error ? error.message : String(error)}`);
155
- }
156
- }
157
- if (failed > 0) {
158
- console.error(`\n${failed}/${checks.length} failed`);
159
- process.exitCode = 1;
160
- }
161
- else {
162
- console.log(`\n${checks.length}/${checks.length} passed`);
163
- }
164
- //# sourceMappingURL=update-check.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"update-check.test.js","sourceRoot":"","sources":["../src/update-check.test.ts"],"names":[],"mappings":"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"}