Skip to content

fix: encode the mcp subcommand in server.json package arguments - #2275

Merged
thymikee merged 2 commits into
mainfrom
fix/server-json-mcp-package-arguments
Sep 4, 2026
Merged

fix: encode the mcp subcommand in server.json package arguments#2275
thymikee merged 2 commits into
mainfrom
fix/server-json-mcp-package-arguments

Conversation

@thymikee

@thymikee thymikee commented Sep 3, 2026

Copy link
Copy Markdown
Member

Problem

Registry-format launchers start the server from the package descriptor only. server.json declared the npm package with a stdio transport but no packageArguments, so a client honoring the MCP registry entry (or the website's new /.well-known/mcp.json discovery manifest) runs the bare agent-device CLI instead of the stdio MCP server — src/bin.ts only starts the MCP server for the mcp subcommand.

Change

  • scripts/sync-mcp-metadata.mjs now writes the fixed positional mcp argument into the package entry, so the sync script, CI (check:mcp-metadata), and prepack all keep the invariant instead of relying on the file being hand-edited.
  • Regenerated server.json accordingly.

Verification

pnpm sync:mcp-metadata
pnpm check:mcp-metadata   # passes

Resulting entry:

"packages": [{
  "registryType": "npm",
  "identifier": "agent-device",
  "version": "0.20.11-dev",
  "transport": { "type": "stdio" },
  "packageArguments": [{ "type": "positional", "value": "mcp" }]
}]

Companion: website PR callstack-internal/v0-agent-device#10 ships the same shape at https://agent-device.dev/.well-known/mcp.json so the two sources of truth do not diverge.

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.
@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown

Size Report

Metric Base Current Diff
JS raw 2.60 MB 2.60 MB -2.9 kB
JS gzip 875.8 kB 874.3 kB -1.5 kB
npm bundled raw 2.60 MB 2.60 MB -2.9 kB
npm bundled gzip 875.8 kB 874.3 kB -1.5 kB
npm tarball 1.03 MB 1.03 MB -1.4 kB
npm unpacked 3.48 MB 3.48 MB -3.2 kB
npm clean-installed 3.48 MB 3.48 MB -3.2 kB

npm unpacked components

Component Base Current Diff
JS / dist source 2.76 MB 2.76 MB -3.3 kB
Apple runner source/project 544.4 kB 544.4 kB 0 B
Apple snapshot presentation source 33.8 kB 33.8 kB 0 B
macOS helper source 54.8 kB 54.8 kB 0 B
Android helper artifacts 43.3 kB 43.3 kB 0 B
Other package files 46.4 kB 46.5 kB +114 B

Startup median (7 runs, lower is better):

Scenario Base Current Diff
CLI --version 25.4 ms 25.1 ms -0.3 ms
CLI --help 63.3 ms 63.3 ms +0.0 ms

Top changed chunks:

Chunk Raw diff Gzip diff
dist/src/session2.js -573 B -161 B
dist/src/daemon-client-lifecycle.js +552 B +129 B
dist/src/internal/daemon.js -66 B -16 B

Top changed packed files

Packed file Base Current Diff
dist/src/artifact-download.js 2.6 kB 0 B -2.6 kB
dist/src/http-health.js 655 B 1.9 kB +1.3 kB
dist/src/transport.js 1.3 kB 0 B -1.3 kB
dist/src/session2.js 218.6 kB 218.0 kB -573 B
dist/src/daemon-client-lifecycle.js 41.9 kB 42.4 kB +552 B
dist/src/client-types.d.ts 57.9 kB 57.5 kB -412 B
dist/src/byte-limit-stream.js 398 B 0 B -398 B
dist/src/archive.js 7.9 kB 8.2 kB +272 B
server.json 602 B 716 B +114 B
dist/src/internal/daemon.js 107.8 kB 107.8 kB -66 B

@thymikee

thymikee commented Sep 3, 2026

Copy link
Copy Markdown
Member Author

BLOCKED at exact head 87fadfd. The packageArguments shape is correct and matches the MCP Registry schema, but the regression proof is incomplete: add an owning metadata test/gate assertion that finds the agent-device npm package entry and requires the exact fixed positional argument [{ type: "positional", value: "mcp" }], with planted-red evidence for a missing/wrong argument. The current check only demonstrates the corrected file is self-consistent. Also add a concise Unreleased changelog entry: registry-format clients currently launch the bare CLI, so this is a user-visible release fix. No device proof is required; exact-head CI and size are otherwise clean.

- 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.
@thymikee

thymikee commented Sep 4, 2026

Copy link
Copy Markdown
Member Author

Both asks addressed in 21083ca:

1. Owning metadata test with planted-red evidence — new scripts/__tests__/mcp-metadata.test.ts (wired into the unit-core project include list, so the unit lane owns it). It finds the agent-device npm package entry in the checked-in server.json by package.json name and asserts the exact fixed positional argument, in both failure directions:

Red #1 — argument missing (server.json reverted to the pre-fix shape):

FAIL  |unit-core| scripts/__tests__/mcp-metadata.test.ts > the published registry entry starts the MCP server, not the bare CLI
AssertionError: registry-format launchers must start the stdio MCP server; without the fixed mcp subcommand they run the bare CLI
+ actual - expected
+ undefined
- [
-   {
-     type: 'positional',
-     value: 'mcp'
-   }
- ]

Red #2 — wrong argument (value: 'cli'):

AssertionError: registry-format launchers must start the stdio MCP server; without the fixed mcp subcommand they run the bare CLI
  [
    {
      type: 'positional',
+     value: 'cli'
-     value: 'mcp'
    }
  ]

Green — with the shipped file: vitest run --project unit-core scripts/__tests__/mcp-metadata.test.ts → 1 passed; pnpm check:mcp-metadata and oxfmt/oxlint clean.

2. Changelog — Unreleased entry added:

Fixed: the MCP registry entry (server.json) now declares the fixed mcp subcommand via packageArguments, so a registry-format launcher — the MCP Registry or the website's /.well-known/mcp.json discovery manifest — starts the stdio MCP server. Previously it ran agent-device with no subcommand, i.e. the bare CLI (#2275).

@thymikee

thymikee commented Sep 4, 2026

Copy link
Copy Markdown
Member Author

Re-review of 21083ca3416de24e89607f19b12d0ccd825258a6: the prior code/documentation asks are resolved. scripts/__tests__/mcp-metadata.test.ts finds the agent-device npm entry by package name and pins npm + stdio + the exact fixed [{ type: "positional", value: "mcp" }] argument; it is owned by unit-core, and the response records planted-red output for both missing and wrong arguments. The Unreleased changelog now documents the user-visible bare-CLI launch bug. No remaining code finding; no device proof is needed.

Still not merge-ready on exact-head evidence: Repo Guards failed in the unchanged scripts/node-test-tmpdir.test.ts orphan-consumer timing case (expected the abandoned run dir to be pruned, observed []). This PR changes no TMPDIR code, so it appears to be an infrastructure/timing flake. Rerun that guard and await the remaining in-progress checks; if they finish green, this head is READY.

@thymikee

thymikee commented Sep 4, 2026

Copy link
Copy Markdown
Member Author

Both exact-head failures are infrastructure flakes in code this PR does not touch; reran the failed jobs (runs 33850336605 / 33850336650):

  • Repo Guardsscripts/node-test-tmpdir.test.ts:305 (a run whose owner alone was killed keeps its directory while a child still uses it, and loses it once the child exits): the orphan-pruning assertion saw [] where it expected the abandoned run dir. TMPDIR code is untouched by this PR (diff is server.json, the sync script, the new metadata test, the vitest include entry, and the changelog).
  • Smoke Tests (iOS runner lane) — all 5 failures are the same case, RunnerTests.testBareTypeUsesTappedInputWhenSoftwareKeyboardIsHidden, a software-keyboard timing case in the Swift runner (the keyboard-existence check retried ~8s before failing); the other three smoke lanes on this head pass. No Swift or runner code is touched by this PR.

Awaiting the reruns to finish; this head should then be READY per the re-review.

@thymikee

thymikee commented Sep 4, 2026

Copy link
Copy Markdown
Member Author

Reruns finished green: Repo Guards pass (3m44s) and the rerun Smoke Tests iOS runner lane pass (15m39s). Full check suite is green on exact head 21083ca — per the re-review, this head is READY.

@thymikee thymikee added the ready-for-human Valid work that needs human implementation, judgment, or maintainer merge label Sep 4, 2026
@thymikee
thymikee merged commit 658f822 into main Sep 4, 2026
23 of 25 checks passed
@thymikee
thymikee deleted the fix/server-json-mcp-package-arguments branch September 4, 2026 08:53
@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
PR Preview Action v1.8.1
Preview removed because the pull request was closed.
2026-09-04 08:53 UTC

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-human Valid work that needs human implementation, judgment, or maintainer merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant