fix: update MCP registry namespace - #1618
Conversation
Size Report
Startup median (7 runs, lower is better):
Top changed chunks:
|
|
The guidance type carried seven fields, but only three were ever set, and all
twenty call sites used it the same way: to hold a second, hand-written MCP
string next to a near-identical CLI one. That is the drift the abstraction was
meant to remove, so the type no longer offers a per-surface description at all.
A command now has one canonical description plus an optional tail per surface:
guidance: {
description: 'Shared body.',
cliDetail: 'Flags, positional syntax, terminal examples.',
mcpDetail: 'When-to-use and sequencing hints.',
}
Because a surface can only append, CLI help and MCP tool text cannot diverge —
the guard against CLI syntax in MCP descriptions becomes structural rather than
a review tripwire, since flag vocabulary only lives in cliDetail. All twenty
commands that previously carried two descriptions now share one body.
Also:
- Drop `summary` from the description fallback chain. It is the short list-view
line, so falling back to it replaced the full description with a fragment on
both surfaces: artifacts, boot, and shutdown each lost their real description.
- Stop writing the MCP variant back over `metadata.description`. That field
feeds CLI help, `explain`, and docs; `explain` was printing MCP-only text.
MCP now reads a separate `mcpDescription`.
- Drop `mcp.parameters`. It restated inputSchema property descriptions inside
the tool description — 1232 characters duplicated verbatim across six tools,
and three of sixteen declared hints silently rendered nothing because the
property had no description. Those properties are documented in the schema
instead, which serves MCP, --help, and docs at once.
- Drop `cli.flags`. Its one use appended "Relevant flags: --surface,
--launch-console." to help text that already named both flags inline.
Tests assert the structural property (both surfaces share a canonical prefix)
and the summary-fallback regression, alongside the existing CLI-syntax guard.
CLI help wording assertions follow the new copy.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dp3J8UUgYxtw5vzJzvjkSf
|
Review of exact head
The registry namespace correction itself is corroborated: the prior release publication authenticated successfully with GitHub OIDC, and the registry explicitly authorized |
Guidance no longer restates input fields in prose, so a tool's inputSchema is the only place its inputs are documented — for the model, for --help, and for the docs site. An undescribed property is a silent gap rather than a cosmetic one, which is exactly the failure mode the removed `mcp.parameters` selection had: it dropped hints for properties that carried no description and reported nothing. Describe the two trigger-app-event inputs that mechanism used to name, and add a ratcheting gate over every MCP tool input. A property key that is not already in the budget fails immediately; the total may never grow, and lowering it is required once properties gain descriptions, so the 132 remaining stay visible instead of settling in as permanent debt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Dp3J8UUgYxtw5vzJzvjkSf
|
The review targeted P2, CLI label synthesis. Confirmed as described — P2, silently dropped MCP parameters. Also confirmed, and broader than The gate you asked for. With prose no longer restating inputs, Beyond the review, the shared-description mechanism was unused: That also caught a regression on the reviewed head: CI wording. Fixed in iOS smoke failure — unrelated. Generated by Claude Code |
|
Re-review of exact head
|
Storing only the MCP variant left the shared body unpropagated: `metadata.description` and the executable definition kept their pre-guidance text, so `explain click` reported "Click or tap a semantic UI target..." while CLI help and the MCP tool both used the canonical "Activate a UI target...". 53 commands were affected — the CLI schema base, `explain`, and docs all read `metadata.description`. `projectCommandGuidance` now returns the canonical body plus the MCP-only tail, and `defineCommandFacet` writes the body to both metadata and the definition. Only the tail is stored apart, as `mcpDetail`, so the body has exactly one home instead of a second full copy that could drift; `composeMcpDescription` joins them for the tool surface. The surface gate pins the invariant: definition, metadata, and `explain` must report the identical body, and neither CLI help nor the MCP description may do anything but extend it. Both arms verified by breaking them. Also replace the undocumented-input ratchet's bare-key allowlist plus aggregate budget with exact `tool.property` identities. The old shape stayed green while a gap migrated: describing `foo.text` and adding an undescribed `bar.text` left both the allowed-name set and the total of 132 unchanged, and stale names kept authorizing later gaps. Verified with that exact scenario — `app` was already an allowed name via push/reinstall/settings and the total held at 132, yet a newly undescribed `open.app` now fails. Recording a fix requires deleting its baseline entry. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Dp3J8UUgYxtw5vzJzvjkSf
|
Both correct, both mine. Fixed in P2, canonical body not propagated. Confirmed and worse than stated: I measured 53 commands where
Parity is pinned in the surface gate: definition, metadata, and P2, ratchet preserves count while gaps migrate. Also confirmed. Replaced the bare-key allowlist and aggregate budget with exact Both problems shared a root cause worth naming: I was pinning derived outputs rather than the relation between surfaces. The count-and-names ratchet and the earlier shared-prefix check both admitted states where every individual assertion held and the invariant did not. The replacements assert identity between surfaces instead. CI: Generated by Claude Code |
`guidance.description` restated what `metadata.description` already is. Setting it shadowed the metadata literal rather than replacing it, so every command that used it shipped two bodies: the canonical one and a terse original that no surface could observe — 768 bytes of unreachable strings across 20 commands. Move each canonical body to the metadata literal where it belongs and delete the field. Guidance is now tails only, `cliDetail` and `mcpDetail`, which also removes the question of where a body is written: there is one place, and no chain to consult. Three guidance blocks held nothing else and are gone entirely. registry.js drops 1117 bytes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Dp3J8UUgYxtw5vzJzvjkSf
The CLI carried four prose fields with a fallback chain between them, and one of them — `helpDescription` — was authored on 45 commands and generated on the rest. That ambiguity is why surfaces drifted: whichever field a reader looked at, some other field might be the one actually rendered. Prose now lives in a single `CommandText`, and `CommandSchema` keeps only grammar: summary what is this command, in a list of ninety? (mandatory) description what does it do, and when do I reach for it? (mandatory) cliDetail flags, argument shapes, terminal examples mcpDetail sequencing and cross-tool hints `--help`, the command list, the MCP tool description and `explain` are projections computed where they render, so nothing derived is stored and no field can be both input and output. The four-field model was validated against the whole surface before the migration: all 67 commands reproduce their MCP text exactly and derive their help body from `description`, so none needed a fifth field. Making `summary` mandatory fixes a regression this branch introduced. 23 commands had none, so the command list fell back to the full detail paragraph; lengthening those descriptions earlier turned `click`'s list entry from 61 characters into 267, `fill`'s into 214, `devices`' into 159. Every command now states its own line, and a gate holds them under 72 characters, non-empty, period-free, and distinct from the description. Two duplications go with it: the per-command help printed its synopsis twice, once as a header and again under `Usage:`, and `press` said "use longpress" in both its body and its tail.
|
Re-reviewed exact head |
Self-review follow-ups on the text model, all quality-only: `command-text.ts` moves from `cli-schema/` to `commands/`. It is a command concept that MCP reads as much as the CLI does; living under `cli-schema` made the MCP surface import a CLI module to render its own tool descriptions. `defineCommandFacet` no longer casts. It took a facet and returned it with the schema completed, but claimed to return the input type, which needed `as unknown as` — a double cast is the type system reporting that the signature was wrong. Splitting `CommandFacetInput` from `CommandFacet` states the completion in the return type, so both that cast and the registry's `as CommandSchema` go. `push`'s summary duplicated its description apart from a trailing period, which the gate missed by comparing exact strings; it now compares normalised text, and the summary says something the description does not. `install-from-source`'s summary loses a clause it did not need.
* origin/main: chore: Update GitHub Sponsors usernames in FUNDING.yml fix: resolve Dependabot security alerts (callstack#1623) fix: update MCP registry namespace (callstack#1618) fix(ios): corroborate recorded tap outcomes (callstack#1605) fix(ios): never signal a recycled runner pid from a stale lease (callstack#1621) build: eliminate tsdown bundle warnings (callstack#1607) refactor(contracts): one viewport-root predicate for the whole repo (callstack#1613) refactor(contracts): name façade exports explicitly and retire the pin table (callstack#1614) refactor(ios): share one private-XCTest event bridge between gesture and text synthesis (callstack#1608) refactor(daemon): give the Maestro fallback and ambiguous-match details real types (callstack#1612) docs: clarify iOS drag synthesis profiles (callstack#1616) # Conflicts: # scripts/layering/facade-symbols.ts # src/commands/capture/screenshot.ts # src/commands/recording/index.ts
Summary
Publish the MCP server under
io.github.callstack/agent-device, matching the GitHub Actions OIDC publisher's authorizedcallstacknamespace.The previous
callstackincubatornamespace caused every post-npm-release registry publication to fail with a 403. The generated registry metadata and setup documentation now use the canonical name.Introduce cross-interface command guidance: a shared semantic description with independent CLI and MCP adapters. The CLI adapter can inject relevant flags while the MCP adapter can inject schema-backed input hints. MCP descriptions no longer contain flags, positional syntax, or terminal command examples; the lowest-scoring Glama tools now use richer MCP-specific guidance.
Validation
pnpm check:affected --runpasses. Focused guidance and command-surface tests pass, including a guard against CLI syntax in MCP descriptions. Runtime/device validation does not apply to the metadata, help, and documentation changes.