Skip to content

Commit 4ebfa83

Browse files
authored
Fix: report the real package version in the MCP handshake (#10)
createServer hardcoded version 0.1.0, so every client saw that in serverInfo while the package shipped 0.2.1. package.json is already the single source of truth for every manifest - the entry point now reads it too, through createRequire, which resolves the same from dist/index.js and src/index.ts. The new binary test runs the built artefact, so it also covers the one way the runtime read could break: package.json not being reachable from the packed layout.
1 parent fa358a3 commit 4ebfa83

3 files changed

Lines changed: 33 additions & 2 deletions

File tree

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ server/
44
coverage/
55
*.tsbuildinfo
66

7+
# Editor and IDE state
8+
.idea/
9+
.vscode/
10+
.DS_Store
11+
712
# Working design docs and plans, not part of the published project
813
docs/superpowers/
914

src/index.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#!/usr/bin/env node
22
import { realpathSync } from 'node:fs';
3+
import { createRequire } from 'node:module';
34
import { pathToFileURL } from 'node:url';
45
import { McpServer } from '@modelcontextprotocol/server';
56
import { StdioServerTransport } from '@modelcontextprotocol/server/stdio';
@@ -17,8 +18,14 @@ import { registerRawTool } from './tools/raw.js';
1718
import type { ToolContext } from './tools/registry.js';
1819
import { registerSystemTools } from './tools/system.js';
1920

21+
// Read rather than repeated as a literal: package.json is the only place a
22+
// version is edited by hand, and a hardcoded one here went stale silently -
23+
// the handshake still reported 0.1.0 two releases later. `../package.json`
24+
// resolves from dist/index.js and src/index.ts alike, and npm always packs it.
25+
const VERSION = createRequire(import.meta.url)('../package.json').version as string;
26+
2027
export function createServer(ctx: ToolContext): McpServer {
21-
const server = new McpServer({ name: 'keenetic', version: '0.1.0' });
28+
const server = new McpServer({ name: 'keenetic', version: VERSION });
2229
registerSystemTools(server, ctx);
2330
registerDeviceTools(server, ctx);
2431
registerInterfaceTools(server, ctx);

tests/binary.test.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { spawn } from 'node:child_process';
2-
import { mkdtemp, symlink } from 'node:fs/promises';
2+
import { mkdtemp, readFile, symlink } from 'node:fs/promises';
33
import { tmpdir } from 'node:os';
44
import { join } from 'node:path';
55
import { fileURLToPath } from 'node:url';
@@ -59,6 +59,25 @@ describe('the built binary', () => {
5959
expect(result.stdout).toContain('keenetic');
6060
});
6161

62+
// The version in the handshake is what a client displays and what a bug
63+
// report quotes, so it has to be the published one. It was a literal in
64+
// src/index.ts and sat at 0.1.0 while the package shipped 0.2.1. Run against
65+
// dist because that also proves package.json is reachable from the built
66+
// layout, which is the only place the runtime read can go wrong.
67+
it('reports the package version in serverInfo', async () => {
68+
const pkg = JSON.parse(
69+
await readFile(new URL('../package.json', import.meta.url), 'utf8')
70+
) as { version: string };
71+
72+
const result = await run(DIST, `${INITIALIZE}\n`, CONFIGURED);
73+
const response = JSON.parse(result.stdout.split('\n')[0] ?? '{}') as {
74+
result?: { serverInfo?: { name?: string; version?: string } };
75+
};
76+
77+
expect(response.result?.serverInfo?.name).toBe('keenetic');
78+
expect(response.result?.serverInfo?.version).toBe(pkg.version);
79+
});
80+
6281
// Regression: npm installs a bin as a symlink in node_modules/.bin, so under
6382
// npx the entry path is the link and the module path is its target. Version
6483
// 0.1.0 compared them unresolved, matched nothing, and exited silently.

0 commit comments

Comments
 (0)