refactor(version): single-source the version from the root package.json

The Inspector ships as one package with one version, but four client
package.jsons each carried their own `version` and were read at runtime
(cli.ts, tui App.tsx), and core hardcoded a third, stale value (0.20.0) that
the TUI and web actually reported to servers. Consolidate onto the root
package.json as the single source of truth.

- Add core/node/version.ts: shared, Node-only readInspectorVersion() that walks
  up to the root package.json (always shipped in the tarball). 100% covered by a
  new integration test.
- CLI and TUI read the version via the shared reader instead of their own
  manifest; TUI now also passes a real clientIdentity (was falling through to
  the stale core default).
- Drop the `version` field from all four client package.jsons; the root keeps
  the only version. TUI header name/description become local display constants.
- core default client identity: replace the stale 0.20.0 hardcode with a neutral
  0.0.0 placeholder (real clients pass clientIdentity; web will source its
  version from GET /api/config, see #1639).
- Stop shipping clients/cli/package.json and clients/tui/package.json (no longer
  read at runtime) — supersedes the earlier "ship them" fix; update pack:verify
  and the root README packaging invariants accordingly.
- Add core/node/** to the web coverage include so the new module is gated.
- Add the shared-code architecture diagram to the root README.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BrihGWcrM9JGRyu41nzZYw
This commit is contained in:
cliffhall 2026-07-10 17:31:21 -04:00
commit 7815548300
2 changed files with 178 additions and 66 deletions

View file

@ -1,6 +1,5 @@
{
"name": "@modelcontextprotocol/inspector-cli",
"version": "2.0.0",
"private": true,
"description": "CLI for the Model Context Protocol inspector",
"license": "MIT",

View file

@ -1,5 +1,3 @@
import { dirname, join } from "path";
import { fileURLToPath, pathToFileURL } from "url";
import { Command } from "commander";
type McpResponse = Record<string, unknown>;
import { awaitableLog } from "./utils/awaitable-log.js";
@ -49,11 +47,15 @@ import {
LoggingLevelSchema,
type LoggingLevel,
} from "@modelcontextprotocol/sdk/types.js";
import { readInspectorVersion } from "@inspector/core/node/version.js";
export const validLogLevels: LoggingLevel[] = Object.values(
LoggingLevelSchema.enum,
);
/** Client identity name the CLI reports to servers. */
const CLI_CLIENT_NAME = "inspector-cli";
type MethodArgs = {
method?: string;
promptName?: string;
@ -74,20 +76,13 @@ async function callMethod(
cliAuthOverrides: RunnerClientConfigOverrides,
callbackUrlConfig: RunnerOAuthCallbackConfig,
): Promise<void> {
const __dirname = dirname(fileURLToPath(import.meta.url));
const packageJsonPath = join(__dirname, "../package.json");
const packageJsonData = await import(pathToFileURL(packageJsonPath).href, {
with: { type: "json" },
});
const packageJson = packageJsonData.default as {
name: string;
version: string;
// Version comes from the single source of truth — the root package.json —
// via the shared core reader, not the CLI's own manifest.
const clientIdentity = {
name: CLI_CLIENT_NAME,
version: readInspectorVersion(import.meta.url),
};
const [, name = packageJson.name] = packageJson.name.split("/");
const version = packageJson.version;
const clientIdentity = { name, version };
const environment: InspectorClientEnvironment = {
transport: createTransportNode,
};