@xihe-lab/tapd-mcp-server 2.0.0-rc.3 → 2.0.0-rc.4
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/server.d.ts.map +1 -1
- package/dist/server.js +13 -1
- package/dist/server.js.map +1 -1
- package/dist/update-check.d.ts +68 -0
- package/dist/update-check.d.ts.map +1 -0
- package/dist/update-check.js +246 -0
- package/dist/update-check.js.map +1 -0
- package/dist/update-check.test.d.ts +6 -0
- package/dist/update-check.test.d.ts.map +1 -0
- package/dist/update-check.test.js +164 -0
- package/dist/update-check.test.js.map +1 -0
- package/package.json +3 -2
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAWnD,wBAAgB,YAAY,IAAI,SAAS,CAYxC;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,IAAI,CAmCvE;AAED,wBAAsB,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAyB3D"}
|
package/dist/server.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
2
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
3
|
import { ToolRegistry, TapdClient } from '@xihe-lab/tapd-core';
|
|
4
|
+
import { checkForUpdate } from './update-check.js';
|
|
4
5
|
let client = null;
|
|
5
6
|
function getTapdClient() {
|
|
6
7
|
client ??= TapdClient.fromEnv();
|
|
@@ -10,7 +11,10 @@ export function createServer() {
|
|
|
10
11
|
const server = new McpServer({
|
|
11
12
|
name: 'tapd-mcp-server',
|
|
12
13
|
version: '1.0.0',
|
|
13
|
-
}
|
|
14
|
+
},
|
|
15
|
+
// 声明 logging 能力:SDK 的 sendLoggingMessage 仅在 capabilities.logging
|
|
16
|
+
// 存在时才真正发出 notifications/message,否则静默丢弃
|
|
17
|
+
{ capabilities: { logging: {} } });
|
|
14
18
|
return server;
|
|
15
19
|
}
|
|
16
20
|
export function registerTools(server, tools) {
|
|
@@ -48,6 +52,14 @@ export async function start(tools) {
|
|
|
48
52
|
registerTools(server, tools);
|
|
49
53
|
const transport = new StdioServerTransport();
|
|
50
54
|
await server.connect(transport);
|
|
55
|
+
// 启动版本自检:异步执行,不阻塞初始化与工具响应;提示经 MCP logging
|
|
56
|
+
// notification 送达(严禁 stderr——Claude Code 会把 server 的 stderr 一律当
|
|
57
|
+
// error 显示)。断网 / registry 不可达时静默跳过;TAPD_MCP_UPDATE_CHECK=off 关闭。
|
|
58
|
+
void checkForUpdate({
|
|
59
|
+
notify: async (message) => {
|
|
60
|
+
await server.server.sendLoggingMessage({ level: 'notice', data: message });
|
|
61
|
+
},
|
|
62
|
+
});
|
|
51
63
|
process.on('SIGINT', () => {
|
|
52
64
|
void server.close();
|
|
53
65
|
process.exit(0);
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEjF,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 启动版本自检(update check)
|
|
3
|
+
*
|
|
4
|
+
* 背景(调研:tapd-knowledge-base/.claude/mcp-autoupdate-research.md):
|
|
5
|
+
* npx 缓存树只以「根包 spec 的 manifest」为新鲜度探针——`@xihe-lab/tapd-mcp-server@rc`
|
|
6
|
+
* 的 dist-tag 不动,整棵缓存树原样复用,用户可能长期跑在旧版本上而不自知。
|
|
7
|
+
* 本模块在 server 启动后异步查询 npm registry 的 @rc dist-tag,发现新版本时
|
|
8
|
+
* 通过 MCP logging notification(notifications/message)提示用户「重启即更新」。
|
|
9
|
+
*
|
|
10
|
+
* 硬约束:
|
|
11
|
+
* - 严禁 console.error / stderr 输出:Claude Code 会把 MCP server 的 stderr 一律
|
|
12
|
+
* 当 error 显示(anthropics/claude-code#17653)。唯一出口是 MCP 协议的
|
|
13
|
+
* logging notification。
|
|
14
|
+
* - 全程 try-catch + 请求超时兜底:断网 / registry 不可达 / 响应异常一律静默
|
|
15
|
+
* 跳过,绝不影响 server 启动与工具响应。
|
|
16
|
+
* - 环境开关:TAPD_MCP_UPDATE_CHECK=off(或 false / 0)跳过检查,默认开启。
|
|
17
|
+
*/
|
|
18
|
+
export interface LocalVersions {
|
|
19
|
+
/** 自身(@xihe-lab/tapd-mcp-server)版本;解析不到时为 null */
|
|
20
|
+
server: string | null;
|
|
21
|
+
/** 内核(@xihe-lab/tapd-core)版本;解析不到时为 null */
|
|
22
|
+
core: string | null;
|
|
23
|
+
}
|
|
24
|
+
export interface RemoteVersions {
|
|
25
|
+
server: string | null;
|
|
26
|
+
core: string | null;
|
|
27
|
+
}
|
|
28
|
+
export interface UpdateCheckDeps {
|
|
29
|
+
/** 环境变量来源,默认 process.env(测试注入用) */
|
|
30
|
+
env?: NodeJS.ProcessEnv;
|
|
31
|
+
/** 提示出口,默认由调用方(server.ts)接 MCP logging notification */
|
|
32
|
+
notify?: (message: string) => void | Promise<void>;
|
|
33
|
+
/** registry 探针,默认 https 直连(测试注入用) */
|
|
34
|
+
fetchRc?: (pkgName: string) => string | null | Promise<string | null>;
|
|
35
|
+
/** 版本解析起点模块 URL,默认本模块(测试注入用) */
|
|
36
|
+
fromUrl?: string;
|
|
37
|
+
/** registry 请求超时毫秒数 */
|
|
38
|
+
timeoutMs?: number;
|
|
39
|
+
}
|
|
40
|
+
interface ParsedVersion {
|
|
41
|
+
numbers: [number, number, number];
|
|
42
|
+
/** prerelease 标识段;GA(无 prerelease)为 null */
|
|
43
|
+
pre: (string | number)[] | null;
|
|
44
|
+
}
|
|
45
|
+
export declare function parseVersion(version: string): ParsedVersion | null;
|
|
46
|
+
/**
|
|
47
|
+
* 返回 1 / -1 / 0 表示 a 相对 b 更新 / 更旧 / 相同;任一版本无法解析时返回 0
|
|
48
|
+
*(解析失败不产生结论,避免误报更新)。
|
|
49
|
+
*/
|
|
50
|
+
export declare function compareVersions(a: string, b: string): number;
|
|
51
|
+
export declare function isUpdateCheckDisabled(env?: NodeJS.ProcessEnv): boolean;
|
|
52
|
+
/** registry 基址:尊重 npm 镜像环境变量,缺省 npmjs(与 npm CLI 的 env 形态一致) */
|
|
53
|
+
export declare function resolveRegistryBase(env?: NodeJS.ProcessEnv): string;
|
|
54
|
+
/** registry packument URL(scope 的 `/` 需编码为 %2F) */
|
|
55
|
+
export declare function packumentUrl(registryBase: string, pkgName: string): string;
|
|
56
|
+
/** 读自身与内核的本地安装版本;server 版本解析不到时整体放弃 */
|
|
57
|
+
export declare function readLocalVersions(fromUrl: string): LocalVersions | null;
|
|
58
|
+
/** 查询包在 npm registry 上 @rc dist-tag 指向的版本;任何失败返回 null(静默) */
|
|
59
|
+
export declare function fetchRcVersion(registryBase: string, pkgName: string, timeoutMs?: number): Promise<string | null>;
|
|
60
|
+
/** 本地任一包落后于 registry @rc 时返回提示文案;否则返回 null */
|
|
61
|
+
export declare function buildUpdateNotice(local: LocalVersions, remote: RemoteVersions): string | null;
|
|
62
|
+
/**
|
|
63
|
+
* 启动自检入口:读本地版本 → 查 registry @rc → 有更新则经 notify 提示。
|
|
64
|
+
* 自身保证不抛错、不写 stderr;调用方只需提供 notify(MCP logging notification)。
|
|
65
|
+
*/
|
|
66
|
+
export declare function checkForUpdate(deps?: UpdateCheckDeps): Promise<void>;
|
|
67
|
+
export {};
|
|
68
|
+
//# sourceMappingURL=update-check.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update-check.d.ts","sourceRoot":"","sources":["../src/update-check.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAgBH,MAAM,WAAW,aAAa;IAC5B,kDAAkD;IAClD,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,4CAA4C;IAC5C,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC9B,mCAAmC;IACnC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,uDAAuD;IACvD,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,qCAAqC;IACrC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACtE,gCAAgC;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uBAAuB;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAMD,UAAU,aAAa;IACrB,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,4CAA4C;IAC5C,GAAG,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG,IAAI,CAAC;CACjC;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAOlE;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CA0B5D;AAMD,wBAAgB,qBAAqB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAGnF;AAED,+DAA+D;AAC/D,wBAAgB,mBAAmB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAGhF;AAED,mDAAmD;AACnD,wBAAgB,YAAY,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAE1E;AAwCD,uCAAuC;AACvC,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAIvE;AAMD,6DAA6D;AAC7D,wBAAgB,cAAc,CAC5B,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,MAAM,EACf,SAAS,GAAE,MAA2B,GACrC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA2DxB;AAMD,8CAA8C;AAC9C,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,aAAa,EACpB,MAAM,EAAE,cAAc,GACrB,MAAM,GAAG,IAAI,CAcf;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,IAAI,GAAE,eAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsB9E"}
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 启动版本自检(update check)
|
|
3
|
+
*
|
|
4
|
+
* 背景(调研:tapd-knowledge-base/.claude/mcp-autoupdate-research.md):
|
|
5
|
+
* npx 缓存树只以「根包 spec 的 manifest」为新鲜度探针——`@xihe-lab/tapd-mcp-server@rc`
|
|
6
|
+
* 的 dist-tag 不动,整棵缓存树原样复用,用户可能长期跑在旧版本上而不自知。
|
|
7
|
+
* 本模块在 server 启动后异步查询 npm registry 的 @rc dist-tag,发现新版本时
|
|
8
|
+
* 通过 MCP logging notification(notifications/message)提示用户「重启即更新」。
|
|
9
|
+
*
|
|
10
|
+
* 硬约束:
|
|
11
|
+
* - 严禁 console.error / stderr 输出:Claude Code 会把 MCP server 的 stderr 一律
|
|
12
|
+
* 当 error 显示(anthropics/claude-code#17653)。唯一出口是 MCP 协议的
|
|
13
|
+
* logging notification。
|
|
14
|
+
* - 全程 try-catch + 请求超时兜底:断网 / registry 不可达 / 响应异常一律静默
|
|
15
|
+
* 跳过,绝不影响 server 启动与工具响应。
|
|
16
|
+
* - 环境开关:TAPD_MCP_UPDATE_CHECK=off(或 false / 0)跳过检查,默认开启。
|
|
17
|
+
*/
|
|
18
|
+
import { readFileSync } from 'node:fs';
|
|
19
|
+
import * as https from 'node:https';
|
|
20
|
+
import { createRequire } from 'node:module';
|
|
21
|
+
import path from 'node:path';
|
|
22
|
+
import { fileURLToPath } from 'node:url';
|
|
23
|
+
const SERVER_PKG_NAME = '@xihe-lab/tapd-mcp-server';
|
|
24
|
+
const CORE_PKG_NAME = '@xihe-lab/tapd-core';
|
|
25
|
+
const DEFAULT_REGISTRY = 'https://registry.npmjs.org';
|
|
26
|
+
/** 单次 registry 请求超时:自检是纯增益,超时即静默放弃 */
|
|
27
|
+
const REQUEST_TIMEOUT_MS = 3000;
|
|
28
|
+
/** packument 响应体上限(防御性;超限直接放弃) */
|
|
29
|
+
const MAX_BODY_BYTES = 8 * 1024 * 1024;
|
|
30
|
+
export function parseVersion(version) {
|
|
31
|
+
const match = /^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?$/.exec(version.trim());
|
|
32
|
+
if (!match)
|
|
33
|
+
return null;
|
|
34
|
+
const pre = match[4]
|
|
35
|
+
? match[4].split('.').map((seg) => (/^\d+$/.test(seg) ? Number(seg) : seg))
|
|
36
|
+
: null;
|
|
37
|
+
return { numbers: [Number(match[1]), Number(match[2]), Number(match[3])], pre };
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* 返回 1 / -1 / 0 表示 a 相对 b 更新 / 更旧 / 相同;任一版本无法解析时返回 0
|
|
41
|
+
*(解析失败不产生结论,避免误报更新)。
|
|
42
|
+
*/
|
|
43
|
+
export function compareVersions(a, b) {
|
|
44
|
+
const pa = parseVersion(a);
|
|
45
|
+
const pb = parseVersion(b);
|
|
46
|
+
if (!pa || !pb)
|
|
47
|
+
return 0;
|
|
48
|
+
for (let i = 0; i < 3; i++) {
|
|
49
|
+
if (pa.numbers[i] !== pb.numbers[i])
|
|
50
|
+
return pa.numbers[i] > pb.numbers[i] ? 1 : -1;
|
|
51
|
+
}
|
|
52
|
+
// x.y.z > x.y.z-rc.N(GA 优先级高于任何 prerelease)
|
|
53
|
+
if (pa.pre === null || pb.pre === null) {
|
|
54
|
+
if (pa.pre === pb.pre)
|
|
55
|
+
return 0;
|
|
56
|
+
return pa.pre === null ? 1 : -1;
|
|
57
|
+
}
|
|
58
|
+
const len = Math.max(pa.pre.length, pb.pre.length);
|
|
59
|
+
for (let i = 0; i < len; i++) {
|
|
60
|
+
const va = pa.pre[i];
|
|
61
|
+
const vb = pb.pre[i];
|
|
62
|
+
if (va === undefined)
|
|
63
|
+
return -1; // 前缀短者更旧
|
|
64
|
+
if (vb === undefined)
|
|
65
|
+
return 1;
|
|
66
|
+
if (va === vb)
|
|
67
|
+
continue;
|
|
68
|
+
// semver 规则:数字标识段 < 字母标识段
|
|
69
|
+
if (typeof va === 'number' && typeof vb === 'number')
|
|
70
|
+
return va > vb ? 1 : -1;
|
|
71
|
+
if (typeof va === 'string' && typeof vb === 'string')
|
|
72
|
+
return va > vb ? 1 : -1;
|
|
73
|
+
return typeof va === 'number' ? -1 : 1;
|
|
74
|
+
}
|
|
75
|
+
return 0;
|
|
76
|
+
}
|
|
77
|
+
// ---------------------------------------------------------------------------
|
|
78
|
+
// 开关与 registry 解析
|
|
79
|
+
// ---------------------------------------------------------------------------
|
|
80
|
+
export function isUpdateCheckDisabled(env = process.env) {
|
|
81
|
+
const raw = (env.TAPD_MCP_UPDATE_CHECK ?? '').trim().toLowerCase();
|
|
82
|
+
return raw === 'off' || raw === 'false' || raw === '0';
|
|
83
|
+
}
|
|
84
|
+
/** registry 基址:尊重 npm 镜像环境变量,缺省 npmjs(与 npm CLI 的 env 形态一致) */
|
|
85
|
+
export function resolveRegistryBase(env = process.env) {
|
|
86
|
+
const raw = (env.npm_config_registry ?? env.NPM_CONFIG_REGISTRY ?? DEFAULT_REGISTRY).trim();
|
|
87
|
+
return (raw === '' ? DEFAULT_REGISTRY : raw).replace(/\/+$/, '');
|
|
88
|
+
}
|
|
89
|
+
/** registry packument URL(scope 的 `/` 需编码为 %2F) */
|
|
90
|
+
export function packumentUrl(registryBase, pkgName) {
|
|
91
|
+
return `${registryBase.replace(/\/+$/, '')}/${pkgName.replace('/', '%2F')}`;
|
|
92
|
+
}
|
|
93
|
+
// ---------------------------------------------------------------------------
|
|
94
|
+
// 本地版本解析
|
|
95
|
+
// ---------------------------------------------------------------------------
|
|
96
|
+
/** 从模块所在目录逐级向上找自身 package.json(兼容 dist/bin、dist、src/tsx 各层级) */
|
|
97
|
+
function findOwnVersion(fromUrl) {
|
|
98
|
+
try {
|
|
99
|
+
let dir = path.dirname(fileURLToPath(fromUrl));
|
|
100
|
+
for (let i = 0; i < 10; i++) {
|
|
101
|
+
try {
|
|
102
|
+
const pkg = JSON.parse(readFileSync(path.join(dir, 'package.json'), 'utf8'));
|
|
103
|
+
if (pkg.name === SERVER_PKG_NAME && typeof pkg.version === 'string')
|
|
104
|
+
return pkg.version;
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
// 该层无 package.json 或不可读——继续向上
|
|
108
|
+
}
|
|
109
|
+
const parent = path.dirname(dir);
|
|
110
|
+
if (parent === dir)
|
|
111
|
+
break;
|
|
112
|
+
dir = parent;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
// 非文件协议(嵌入等场景)——放弃
|
|
117
|
+
}
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
/** 经 node_modules 解析内核包版本;不可达(独立检出等)返回 null */
|
|
121
|
+
function readCoreVersion(fromUrl) {
|
|
122
|
+
try {
|
|
123
|
+
const pkg = createRequire(fromUrl)(`${CORE_PKG_NAME}/package.json`);
|
|
124
|
+
return typeof pkg.version === 'string' ? pkg.version : null;
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/** 读自身与内核的本地安装版本;server 版本解析不到时整体放弃 */
|
|
131
|
+
export function readLocalVersions(fromUrl) {
|
|
132
|
+
const server = findOwnVersion(fromUrl);
|
|
133
|
+
if (server === null)
|
|
134
|
+
return null;
|
|
135
|
+
return { server, core: readCoreVersion(fromUrl) };
|
|
136
|
+
}
|
|
137
|
+
// ---------------------------------------------------------------------------
|
|
138
|
+
// registry 探针(https 直连,不走 npm CLI)
|
|
139
|
+
// ---------------------------------------------------------------------------
|
|
140
|
+
/** 查询包在 npm registry 上 @rc dist-tag 指向的版本;任何失败返回 null(静默) */
|
|
141
|
+
export function fetchRcVersion(registryBase, pkgName, timeoutMs = REQUEST_TIMEOUT_MS) {
|
|
142
|
+
return new Promise((resolve) => {
|
|
143
|
+
let settled = false;
|
|
144
|
+
const done = (value) => {
|
|
145
|
+
if (!settled) {
|
|
146
|
+
settled = true;
|
|
147
|
+
resolve(value);
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
try {
|
|
151
|
+
const request = https.get(packumentUrl(registryBase, pkgName), {
|
|
152
|
+
headers: {
|
|
153
|
+
accept: 'application/vnd.npm.install-v1+json',
|
|
154
|
+
'user-agent': `${SERVER_PKG_NAME} update-check`,
|
|
155
|
+
},
|
|
156
|
+
timeout: timeoutMs,
|
|
157
|
+
}, (res) => {
|
|
158
|
+
if (res.statusCode !== 200) {
|
|
159
|
+
res.resume();
|
|
160
|
+
done(null);
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
const chunks = [];
|
|
164
|
+
let size = 0;
|
|
165
|
+
res.on('data', (chunk) => {
|
|
166
|
+
size += chunk.length;
|
|
167
|
+
if (size > MAX_BODY_BYTES) {
|
|
168
|
+
request.destroy();
|
|
169
|
+
done(null);
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
chunks.push(chunk);
|
|
173
|
+
});
|
|
174
|
+
res.on('end', () => {
|
|
175
|
+
try {
|
|
176
|
+
const doc = JSON.parse(Buffer.concat(chunks).toString('utf8'));
|
|
177
|
+
const rc = doc['dist-tags']?.rc;
|
|
178
|
+
done(typeof rc === 'string' ? rc : null);
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
done(null);
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
res.on('error', () => done(null));
|
|
185
|
+
});
|
|
186
|
+
request.on('timeout', () => {
|
|
187
|
+
request.destroy();
|
|
188
|
+
done(null);
|
|
189
|
+
});
|
|
190
|
+
request.on('error', () => done(null));
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
done(null);
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
// ---------------------------------------------------------------------------
|
|
198
|
+
// 组装与入口
|
|
199
|
+
// ---------------------------------------------------------------------------
|
|
200
|
+
/** 本地任一包落后于 registry @rc 时返回提示文案;否则返回 null */
|
|
201
|
+
export function buildUpdateNotice(local, remote) {
|
|
202
|
+
const parts = [];
|
|
203
|
+
if (remote.server !== null && local.server !== null && compareVersions(remote.server, local.server) > 0) {
|
|
204
|
+
parts.push(`tapd-mcp-server 有新版本可用(${local.server} → ${remote.server})`);
|
|
205
|
+
}
|
|
206
|
+
if (remote.core !== null) {
|
|
207
|
+
if (local.core === null) {
|
|
208
|
+
parts.push(`tapd-core 有新版本可用(${remote.core})`);
|
|
209
|
+
}
|
|
210
|
+
else if (compareVersions(remote.core, local.core) > 0) {
|
|
211
|
+
parts.push(`tapd-core 有新版本可用(${local.core} → ${remote.core})`);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
if (parts.length === 0)
|
|
215
|
+
return null;
|
|
216
|
+
return `${parts.join(';')}——重启 MCP 会话即可更新(Claude Code 可用 /mcp 菜单 Reconnect)。`;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* 启动自检入口:读本地版本 → 查 registry @rc → 有更新则经 notify 提示。
|
|
220
|
+
* 自身保证不抛错、不写 stderr;调用方只需提供 notify(MCP logging notification)。
|
|
221
|
+
*/
|
|
222
|
+
export async function checkForUpdate(deps = {}) {
|
|
223
|
+
try {
|
|
224
|
+
const env = deps.env ?? process.env;
|
|
225
|
+
if (isUpdateCheckDisabled(env))
|
|
226
|
+
return;
|
|
227
|
+
const notify = deps.notify;
|
|
228
|
+
if (!notify)
|
|
229
|
+
return;
|
|
230
|
+
const local = readLocalVersions(deps.fromUrl ?? import.meta.url);
|
|
231
|
+
if (local === null)
|
|
232
|
+
return;
|
|
233
|
+
const registryBase = resolveRegistryBase(env);
|
|
234
|
+
const timeoutMs = deps.timeoutMs ?? REQUEST_TIMEOUT_MS;
|
|
235
|
+
const fetchRc = deps.fetchRc ??
|
|
236
|
+
((pkgName) => fetchRcVersion(registryBase, pkgName, timeoutMs));
|
|
237
|
+
const [remoteServer, remoteCore] = await Promise.all([fetchRc(SERVER_PKG_NAME), fetchRc(CORE_PKG_NAME)]);
|
|
238
|
+
const notice = buildUpdateNotice(local, { server: remoteServer, core: remoteCore });
|
|
239
|
+
if (notice !== null)
|
|
240
|
+
await notify(notice);
|
|
241
|
+
}
|
|
242
|
+
catch {
|
|
243
|
+
// 自检绝不能干扰 server 启动——所有异常静默吞掉(严禁 stderr)
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
//# sourceMappingURL=update-check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update-check.js","sourceRoot":"","sources":["../src/update-check.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update-check.test.d.ts","sourceRoot":"","sources":["../src/update-check.test.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
|
@@ -0,0 +1,164 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update-check.test.js","sourceRoot":"","sources":["../src/update-check.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xihe-lab/tapd-mcp-server",
|
|
3
|
-
"version": "2.0.0-rc.
|
|
3
|
+
"version": "2.0.0-rc.4",
|
|
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
6
|
"main": "dist/bin/tapd-mcp-server.js",
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
"build": "tsc",
|
|
12
12
|
"start": "node dist/bin/tapd-mcp-server.js",
|
|
13
13
|
"dev": "tsx src/bin/tapd-mcp-server.ts",
|
|
14
|
+
"test": "tsx src/update-check.test.ts",
|
|
14
15
|
"test:integration": "tsx src/integration-test.ts",
|
|
15
16
|
"type-check": "tsc --noEmit"
|
|
16
17
|
},
|
|
@@ -47,7 +48,7 @@
|
|
|
47
48
|
],
|
|
48
49
|
"dependencies": {
|
|
49
50
|
"@modelcontextprotocol/sdk": "^1.0.4",
|
|
50
|
-
"@xihe-lab/tapd-core": "
|
|
51
|
+
"@xihe-lab/tapd-core": "2.0.0-rc.4",
|
|
51
52
|
"zod": "^3.25.76"
|
|
52
53
|
},
|
|
53
54
|
"packageManager": "pnpm@12.3.4"
|