fix(sequentialthinking): read server version from package.json (#4576)
* fix(sequentialthinking): read server version from package.json Replace the hardcoded 0.2.0 so initialize serverInfo tracks the package version (0.6.2 in-tree; CalVer after release), matching the approach used for memory server version sync. Skip the dist-layout assertion when dist/ is absent so CI's test-before-build job (and local runs without prepare) still pass. * test(sequentialthinking): smoke stdio initialize serverInfo.version Spawn the built server over stdio and assert getServerVersion() matches package.json (and is not the old hardcoded 0.2.0). Skip when dist/ is absent so test-before-build CI still passes.
This commit is contained in:
parent
11845d51cb
commit
40a8de87ed
3 changed files with 92 additions and 1 deletions
57
src/sequentialthinking/__tests__/server-version.test.ts
Normal file
57
src/sequentialthinking/__tests__/server-version.test.ts
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
import { describe, it, expect } from 'vitest';
|
||||||
|
import { createRequire } from 'node:module';
|
||||||
|
import { existsSync } from 'node:fs';
|
||||||
|
import path from 'node:path';
|
||||||
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
||||||
|
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
||||||
|
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
|
||||||
|
import { resolvePackageVersion, SERVER_VERSION } from '../version.js';
|
||||||
|
|
||||||
|
const packageJson = createRequire(import.meta.url)('../package.json') as { version: string };
|
||||||
|
const packageRoot = path.join(path.dirname(fileURLToPath(import.meta.url)), '..');
|
||||||
|
const distVersionPath = path.join(packageRoot, 'dist', 'version.js');
|
||||||
|
const distIndexPath = path.join(packageRoot, 'dist', 'index.js');
|
||||||
|
|
||||||
|
describe('server version', () => {
|
||||||
|
it('uses package.json version instead of a hardcoded string', () => {
|
||||||
|
expect(SERVER_VERSION).toBe(packageJson.version);
|
||||||
|
expect(resolvePackageVersion()).toBe(packageJson.version);
|
||||||
|
expect(SERVER_VERSION).not.toBe('0.2.0');
|
||||||
|
});
|
||||||
|
|
||||||
|
// CI runs `npm test` before the dedicated build job. `npm ci` usually
|
||||||
|
// materializes dist/ via prepare, but that is not guaranteed (e.g. local
|
||||||
|
// `rm -rf dist && npm test`, or install with --ignore-scripts).
|
||||||
|
it.skipIf(!existsSync(distVersionPath))(
|
||||||
|
'resolves package.json from the dist layout after build',
|
||||||
|
async () => {
|
||||||
|
const distModule = (await import(pathToFileURL(distVersionPath).href)) as {
|
||||||
|
SERVER_VERSION: string;
|
||||||
|
};
|
||||||
|
expect(distModule.SERVER_VERSION).toBe(packageJson.version);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
it.skipIf(!existsSync(distIndexPath))(
|
||||||
|
'stdio initialize reports package.json version in serverInfo',
|
||||||
|
async () => {
|
||||||
|
const transport = new StdioClientTransport({
|
||||||
|
command: process.execPath,
|
||||||
|
args: [distIndexPath],
|
||||||
|
cwd: packageRoot,
|
||||||
|
stderr: 'pipe',
|
||||||
|
});
|
||||||
|
const client = new Client({ name: 'version-smoke', version: '0.0.0' });
|
||||||
|
|
||||||
|
try {
|
||||||
|
await client.connect(transport);
|
||||||
|
const serverInfo = client.getServerVersion();
|
||||||
|
expect(serverInfo?.name).toBe('sequential-thinking-server');
|
||||||
|
expect(serverInfo?.version).toBe(packageJson.version);
|
||||||
|
expect(serverInfo?.version).not.toBe('0.2.0');
|
||||||
|
} finally {
|
||||||
|
await client.close();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
@ -4,6 +4,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
||||||
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { SequentialThinkingServer } from './lib.js';
|
import { SequentialThinkingServer } from './lib.js';
|
||||||
|
import { SERVER_VERSION } from './version.js';
|
||||||
|
|
||||||
/** Safe boolean coercion that correctly handles string "false" */
|
/** Safe boolean coercion that correctly handles string "false" */
|
||||||
const coercedBoolean = z.preprocess((val) => {
|
const coercedBoolean = z.preprocess((val) => {
|
||||||
|
|
@ -17,7 +18,7 @@ const coercedBoolean = z.preprocess((val) => {
|
||||||
|
|
||||||
const server = new McpServer({
|
const server = new McpServer({
|
||||||
name: "sequential-thinking-server",
|
name: "sequential-thinking-server",
|
||||||
version: "0.2.0",
|
version: SERVER_VERSION,
|
||||||
});
|
});
|
||||||
|
|
||||||
const thinkingServer = new SequentialThinkingServer();
|
const thinkingServer = new SequentialThinkingServer();
|
||||||
|
|
|
||||||
33
src/sequentialthinking/version.ts
Normal file
33
src/sequentialthinking/version.ts
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
import { createRequire } from 'node:module';
|
||||||
|
import path from 'node:path';
|
||||||
|
import { fileURLToPath } from 'node:url';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve this package's version from package.json.
|
||||||
|
*
|
||||||
|
* Works both from source (`src/sequentialthinking/`) and from the published
|
||||||
|
* layout (`dist/`), where package.json lives one directory up.
|
||||||
|
*/
|
||||||
|
export function resolvePackageVersion(): string {
|
||||||
|
const require = createRequire(import.meta.url);
|
||||||
|
const moduleDir = path.dirname(fileURLToPath(import.meta.url));
|
||||||
|
const candidates = [
|
||||||
|
path.join(moduleDir, 'package.json'),
|
||||||
|
path.join(moduleDir, '..', 'package.json'),
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const candidate of candidates) {
|
||||||
|
try {
|
||||||
|
const pkg = require(candidate) as { version?: string };
|
||||||
|
if (pkg.version) {
|
||||||
|
return pkg.version;
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Try the next candidate when running from dist/ or source.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error('Could not locate package.json for server version');
|
||||||
|
}
|
||||||
|
|
||||||
|
export const SERVER_VERSION = resolvePackageVersion();
|
||||||
Loading…
Reference in a new issue