mirror of
https://github.com/callstack/agent-device.git
synced 2026-09-14 20:06:34 +08:00
658f822c40
* fix: encode the mcp subcommand in server.json package arguments A registry-format launcher (e.g. one consuming /.well-known/mcp.json or the MCP registry entry) starts the server from the package descriptor only; without the positional "mcp" argument it runs the bare CLI instead of the stdio MCP server (bin.ts only starts the MCP server for the mcp subcommand). Enforce the argument in scripts/sync-mcp-metadata.mjs so sync and the CI/prepack checks (check:mcp-metadata) keep server.json correct, and regenerate server.json. * test: own the registry launch-argument invariant; add changelog entry - scripts/__tests__/mcp-metadata.test.ts asserts the checked-in server.json's agent-device npm package entry declares the exact fixed positional mcp argument (and stays stdio-only), so a missing or wrong argument fails the unit lane in both directions. Wired into the unit-core project include list. - Changelog: user-visible release fix under Unreleased.
49 lines
1.9 KiB
TypeScript
49 lines
1.9 KiB
TypeScript
/**
|
|
* Guard for the registry-format launch argument.
|
|
*
|
|
* The MCP registry entry (and the website's `/.well-known/mcp.json` discovery manifest) tell a
|
|
* launcher how to start the server: the npm package, the stdio transport, and
|
|
* `packageArguments`. Without the fixed `mcp` positional argument, a client that honors the
|
|
* manifest runs `agent-device` with no subcommand — the bare CLI — instead of the stdio MCP
|
|
* server (`src/bin.ts` only starts the server for the `mcp` subcommand).
|
|
*
|
|
* `check:mcp-metadata` compares the file against a regeneration, which proves the corrected file
|
|
* is self-consistent; this test owns the invariant directly against the checked-in file and fails
|
|
* in both directions — a missing argument and a wrong one.
|
|
*/
|
|
import assert from 'node:assert/strict';
|
|
import { readFile } from 'node:fs/promises';
|
|
import { join } from 'node:path';
|
|
import { test } from 'vitest';
|
|
|
|
const ROOT = join(import.meta.dirname, '..', '..');
|
|
|
|
const EXPECTED_MCP_PACKAGE_ARGUMENTS = [{ type: 'positional', value: 'mcp' }];
|
|
|
|
type ServerPackage = {
|
|
registryType?: string;
|
|
identifier?: string;
|
|
transport?: { type?: string };
|
|
packageArguments?: unknown;
|
|
};
|
|
|
|
test('the published registry entry starts the MCP server, not the bare CLI', async () => {
|
|
const pkg = JSON.parse(await readFile(join(ROOT, 'package.json'), 'utf8')) as {
|
|
name: string;
|
|
};
|
|
const server = JSON.parse(await readFile(join(ROOT, 'server.json'), 'utf8')) as {
|
|
packages?: ServerPackage[];
|
|
};
|
|
|
|
const entry = (server.packages ?? []).find((candidate) => candidate.identifier === pkg.name);
|
|
assert.ok(entry, `server.json must describe the ${pkg.name} npm package`);
|
|
assert.equal(entry.registryType, 'npm');
|
|
assert.deepEqual(entry.transport, { type: 'stdio' });
|
|
|
|
assert.deepEqual(
|
|
entry.packageArguments,
|
|
EXPECTED_MCP_PACKAGE_ARGUMENTS,
|
|
'registry-format launchers must start the stdio MCP server; without the fixed mcp subcommand they run the bare CLI',
|
|
);
|
|
});
|