Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
120 commits
Select commit Hold shift + click to select a range
8dc5571
fix(smoke): run the Firefox pass in the Playwright container on macOS…
cliffhall Oct 12, 2026
297d578
docs(pr-flow): always start work in a new git worktree (#2661)
cliffhall Oct 12, 2026
2ba6a1e
fix(cli): refresh write-back updates the fresh on-disk entry (#2574)
cliffhall Oct 12, 2026
658d160
test(web): bind auto-open server to :0 instead of probing a free port…
cliffhall Oct 12, 2026
14588f5
fix(gate-lease): key the lock on a fixed per-user path, not TMPDIR (#…
cliffhall Oct 12, 2026
4285e1c
fix(smoke): chown the container export back to the caller; test runIn…
cliffhall Oct 12, 2026
9833451
chore(deps): upgrade the MCP TypeScript SDK to 2.3.1 (#2606)
cliffhall Oct 12, 2026
fc65347
fix(gate-lease): refuse a lease dir this user does not own (#2624)
cliffhall Oct 12, 2026
64c2291
Merge pull request #2663 from modelcontextprotocol/v2/docs/2661-pr-fl…
cliffhall Oct 12, 2026
68fd67e
fix(smoke): reject an unrecognized INSPECTOR_FIREFOX_SMOKE (#2625)
cliffhall Oct 12, 2026
fe0a106
fix(auth): carry stripped-namespace secrets over before purging (#2630)
cliffhall Oct 12, 2026
7f2e536
Merge pull request #2665 from modelcontextprotocol/v2/chore/2606-sdk-…
cliffhall Oct 12, 2026
73cc746
Merge pull request #2664 from modelcontextprotocol/v2/fix/2624-gate-l…
cliffhall Oct 12, 2026
34d6345
fix(cli): skip a slot whose tokens changed during the refresh (#2574)
cliffhall Oct 12, 2026
ed03ae9
Merge pull request #2669 from modelcontextprotocol/v2/fix/2602-auto-o…
cliffhall Oct 12, 2026
fbdaa15
fix(smoke): bound the docker info probe (#2625)
cliffhall Oct 12, 2026
4c3e1de
Merge pull request #2666 from modelcontextprotocol/v2/fix/2574-refres…
cliffhall Oct 12, 2026
21d4bdf
Merge pull request #2662 from modelcontextprotocol/v2/fix/2625-firefo…
cliffhall Oct 12, 2026
7445124
docs(agents): pace bulk GitHub writes under the secondary rate limit …
cliffhall Oct 12, 2026
94d5ed8
Merge pull request #2671 from modelcontextprotocol/v2/fix/2630-preser…
cliffhall Oct 12, 2026
2ab8f04
Merge pull request #2673 from modelcontextprotocol/v2/docs/2667-pace-…
cliffhall Oct 12, 2026
75c2782
fix(auth): pass empty fallbacks to joinSnapshot in updateOAuthServerE…
cliffhall Oct 12, 2026
f9a265e
feat(web): hide 'Run as task' on modern-era connections (#2674)
cliffhall Oct 12, 2026
77bb793
docs(skills): point test-servers at scripts/lib/ensure-test-servers.m…
cliffhall Oct 12, 2026
2bc28da
fix(mcpdo): route connections and OAuth through HTTPS_PROXY / HTTP_PR…
cliffhall Oct 12, 2026
80d8730
chore(pack:verify): assert skills/mcpdo ships and drive an mcpdo tool…
cliffhall Oct 12, 2026
d3a15b3
fix(remote): relay upstream HTTP status so auto era falls back on a 4…
cliffhall Oct 12, 2026
5a873e6
Merge pull request #2685 from modelcontextprotocol/v2/fix/2676-join-s…
cliffhall Oct 12, 2026
5309dd5
fix(web): keep every monitoring-sidebar entry inside its column (#2675)
cliffhall Oct 12, 2026
9c813f4
Merge branch 'v2/main' into v2/fix/2660-auto-era-probe-http-status
cliffhall Oct 12, 2026
cf22a0e
Merge branch 'v2/main' into v2/chore/2650-pack-verify-mcpdo
cliffhall Oct 12, 2026
f2cf0f7
Merge branch 'v2/main' into v2/docs/2523-test-servers-skill-path
cliffhall Oct 12, 2026
1b9f154
test(web): fail a rendered control squeezed to zero width (#2675)
cliffhall Oct 12, 2026
1e93ca3
Merge pull request #2684 from modelcontextprotocol/v2/fix/2660-auto-e…
cliffhall Oct 12, 2026
4440ea1
Merge pull request #2687 from modelcontextprotocol/v2/fix/2674-hide-r…
cliffhall Oct 12, 2026
0331b2c
Merge pull request #2688 from modelcontextprotocol/v2/fix/2675-monito…
cliffhall Oct 12, 2026
61b81c5
test(web): isolate integration OAuth state from ~/.mcp-inspector (#2670)
cliffhall Oct 12, 2026
8475384
test(web): make the default-store isolation check a beforeEach guard …
cliffhall Oct 12, 2026
6ccf925
Merge pull request #2679 from modelcontextprotocol/v2/chore/2650-pack…
cliffhall Oct 12, 2026
8be706c
Merge branch 'v2/main' into v2/fix/2642-mcpdo-proxy-fetch
cliffhall Oct 12, 2026
4a893ff
Merge pull request #2678 from modelcontextprotocol/v2/docs/2523-test-…
cliffhall Oct 12, 2026
7c75f11
Merge pull request #2677 from modelcontextprotocol/v2/fix/2670-isolat…
cliffhall Oct 12, 2026
c6ff20c
Merge pull request #2686 from modelcontextprotocol/v2/fix/2642-mcpdo-…
cliffhall Oct 12, 2026
10cb1b7
fix(web): re-read the viewed skill file on a skills/get fetch (#2516)
cliffhall Oct 12, 2026
4914f25
fix(auth): apply endpoint overrides when the AS publishes no metadata…
cliffhall Oct 12, 2026
4fdf2d6
fix(tui): Esc clears a kept list filter before exiting (#2647)
cliffhall Oct 12, 2026
cd9cb16
fix(web): print a one-line warning when the browser opener cannot sta…
cliffhall Oct 12, 2026
545df79
fix(auth): don't treat a plain 403 without WWW-Authenticate as an OAu…
cliffhall Oct 12, 2026
ec9e57a
docs(auth): narrow fetch-wrapper JSDoc to the challenges they act on …
cliffhall Oct 12, 2026
5e2f0de
fix(tui): delete copy-to-file temp files when the TUI exits (#2648)
cliffhall Oct 12, 2026
b907417
fix(auth): identify synthesized metadata by identity, not header (#2562)
cliffhall Oct 12, 2026
571593a
Merge pull request #2689 from modelcontextprotocol/v2/fix/2645-web-op…
cliffhall Oct 12, 2026
f16ef79
fix(tui): keep the '/' help row within an 80-column overlay (#2647)
cliffhall Oct 12, 2026
1974465
Merge pull request #2690 from modelcontextprotocol/v2/fix/2515-plain-…
cliffhall Oct 12, 2026
5dff990
Merge pull request #2692 from modelcontextprotocol/v2/fix/2648-clean-…
cliffhall Oct 12, 2026
3f535de
fix(launcher): print the version for --version / -V in every mode (#2…
cliffhall Oct 12, 2026
65c5c2d
Merge pull request #2693 from modelcontextprotocol/v2/fix/2647-tui-es…
cliffhall Oct 12, 2026
9bb8d75
fix(auth): exclude well-known-prefixed candidates from final-candidat…
cliffhall Oct 12, 2026
17d1607
Merge pull request #2694 from modelcontextprotocol/v2/fix/2516-skill-…
cliffhall Oct 12, 2026
e738605
Merge pull request #2695 from modelcontextprotocol/v2/fix/2632-versio…
cliffhall Oct 12, 2026
f3fdd30
docs(release): drive mcpdo in the milestone smoke (#2628)
cliffhall Oct 12, 2026
bf52246
fix(cli): take the task path for a taskSupport: required tool (#2649)
cliffhall Oct 12, 2026
1eb3354
fix(cli): exit quietly when --completion's reader closes early (#2646)
cliffhall Oct 12, 2026
0a6724e
fix(auth): synthesize metadata only for JSON discovery requests (#2562)
cliffhall Oct 12, 2026
70e94ea
fix(mcpdo): restore a fresh OAuth-flow lock instead of deleting it on…
cliffhall Oct 12, 2026
786148b
fix(cli): keep the stdio target when an option precedes it (#2631)
cliffhall Oct 12, 2026
6db25fc
fix(skills): name each client's own catalog-budget remedies (#2633)
cliffhall Oct 12, 2026
50a057b
test(mcpdo): give the budget-hint test an outer timeout above its com…
cliffhall Oct 12, 2026
aee893f
test(mcpdo): wait for the daemon socket to close before removing its …
cliffhall Oct 12, 2026
f390692
fix(cli): refuse a URL that contradicts a positional command or --tra…
cliffhall Oct 12, 2026
f81c2e4
Merge pull request #2696 from modelcontextprotocol/v2/fix/2643-stale-…
cliffhall Oct 12, 2026
fd4efe1
Merge pull request #2697 from modelcontextprotocol/v2/docs/2628-relea…
cliffhall Oct 12, 2026
801eeb5
fix(cli): suppress the --output "Wrote N bytes" status line under -q …
cliffhall Oct 12, 2026
fd5659f
Merge pull request #2698 from modelcontextprotocol/v2/fix/2633-skills…
cliffhall Oct 12, 2026
a44dcba
fix(cli,mcpdo,tui): name each client's own remedy on a connect timeou…
cliffhall Oct 12, 2026
56b8104
fix(auth): exclude event-stream Accept from discovery detection (#2562)
cliffhall Oct 12, 2026
fe0ddcb
fix(core): keep connectionTimeoutRemedy off CreateTransportOptions (#…
cliffhall Oct 12, 2026
b29eb6c
fix(auth): mirror the SDK's full discovery-continue predicate (#2562)
cliffhall Oct 12, 2026
4405fd0
fix(cli,mcpdo,tui): name no config filename in the timeout remedy (#2…
cliffhall Oct 12, 2026
72f6578
Merge pull request #2691 from modelcontextprotocol/v2/fix/2562-oauth-…
cliffhall Oct 12, 2026
622a073
Merge pull request #2699 from modelcontextprotocol/v2/fix/2649-cli-ta…
cliffhall Oct 12, 2026
ca0ab33
Merge pull request #2704 from modelcontextprotocol/v2/fix/2631-cli-bo…
cliffhall Oct 12, 2026
cbf3f52
Merge pull request #2700 from modelcontextprotocol/v2/fix/2646-comple…
cliffhall Oct 12, 2026
3d4511c
Merge pull request #2702 from modelcontextprotocol/v2/fix/2614-quiet-…
cliffhall Oct 12, 2026
894ee1f
Merge pull request #2703 from modelcontextprotocol/v2/fix/2615-connec…
cliffhall Oct 12, 2026
5f19555
Merge branch 'v2/main' into v2/fix/2611-cli-target-transport-conflicts
cliffhall Oct 12, 2026
840a181
fix(tui): show the Inspector version in the header (#2656)
cliffhall Oct 12, 2026
22b7610
feat(web): show tool/prompt/resource counts in list headers and Conne…
cliffhall Oct 12, 2026
cc2ee50
Merge pull request #2701 from modelcontextprotocol/v2/fix/2611-cli-ta…
cliffhall Oct 12, 2026
9203d13
feat(web): form rows for array-of-object tool inputs (#2561)
cliffhall Oct 12, 2026
24f4ffe
test(web): expect the counted Prompts heading in InspectorView (#2607)
cliffhall Oct 12, 2026
9588857
fix(web): seed array-of-object rows together and name each row (#2561)
cliffhall Oct 12, 2026
771430c
Merge pull request #2706 from modelcontextprotocol/v2/fix/2656-tui-he…
cliffhall Oct 12, 2026
3dffa7f
fix(web): withhold list counts until the first load completes (#2607)
cliffhall Oct 12, 2026
746c48e
fix(web): seed array-of-object rows recursively and per branch (#2561)
cliffhall Oct 12, 2026
8fb3b4e
Merge pull request #2708 from modelcontextprotocol/v2/feat/2607-list-…
cliffhall Oct 12, 2026
a58454d
Merge pull request #2707 from modelcontextprotocol/v2/feat/2561-array…
cliffhall Oct 12, 2026
e743a73
chore(deps): apply the in-range monthly refresh (#2557)
cliffhall Oct 12, 2026
4442499
chore(deps): move commander 15 and @napi-rs/keyring 2 (#2557)
cliffhall Oct 12, 2026
2b1db6b
chore(scripts): guard the file set each coverage run measures (#2709)
cliffhall Oct 13, 2026
a305dca
fix(scripts): require a reason on coverage-scope omissions; flag redu…
cliffhall Oct 13, 2026
ae4bca4
Merge pull request #2711 from modelcontextprotocol/v2/chore/2709-cove…
cliffhall Oct 13, 2026
cff0b68
Merge branch 'v2/main' into v2/chore/2557-monthly-dep-refresh
cliffhall Oct 13, 2026
a6aa805
Merge pull request #2710 from modelcontextprotocol/v2/chore/2557-mont…
cliffhall Oct 13, 2026
03c7dc3
chore(deps): deny esbuild/fsevents install scripts; guard unreviewed …
cliffhall Oct 13, 2026
db34adf
fix(install): strip npm_config_allow_scripts from the per-client inst…
cliffhall Oct 13, 2026
e3c76ab
test(install): pin the symlinked-checkout guard and spawn node withou…
cliffhall Oct 13, 2026
bfa1fbf
fix(scripts): match allowScripts keys and identity the way npm does (…
cliffhall Oct 13, 2026
1ac6e2f
test(install): pin the env wiring with a stub npm, independent of the…
cliffhall Oct 13, 2026
fa4469e
fix(scripts): fail closed on bundled install scripts (#2712)
cliffhall Oct 13, 2026
685e6aa
fix(scripts): require a decision for every non-registry dependency (#…
cliffhall Oct 13, 2026
996500e
fix(install): canonicalize both sides of the main guard (#2518)
cliffhall Oct 13, 2026
45c2815
fix(scripts): apply the prepare fallback only to resolved non-registr…
cliffhall Oct 13, 2026
5316f45
docs(scripts): state why the guard is needed under npm 10/11, not 'un…
cliffhall Oct 13, 2026
105d6f6
docs: describe the non-registry and bundled cases verify:install-scri…
cliffhall Oct 13, 2026
90a2791
Merge pull request #2713 from modelcontextprotocol/v2/fix/2518-instal…
cliffhall Oct 13, 2026
15d7721
Merge pull request #2714 from modelcontextprotocol/v2/chore/2712-deny…
cliffhall Oct 13, 2026
59d237b
chore: bump version to 2.11.0 (#2716)
cliffhall Oct 14, 2026
41018be
Merge pull request #2717 from modelcontextprotocol/v2/chore/2716-bump…
cliffhall Oct 14, 2026
079058e
chore: merge v2/main into main for the v2.11.0 release
cliffhall Oct 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 46 additions & 5 deletions .claude/skills/pr-flow/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,41 @@ branch cut from `v2/main` arrives at `v1/main` carrying the whole v2 tree
(Copilot). And never cut from a milestone-merge branch — it carries release-only
commits that will show up in your PR's diff.

Working in a git worktree is fine and often preferable. ⚠️ **A worktree needs a
real `npm install`, not a symlinked `node_modules`** — a symlink passes
lint/test/coverage and then fails all Storybook story files on Vite's
`fs.allow`.
**Always cut it into a new git worktree, never by switching branches in the
primary checkout** (#2661). This repo is routinely worked by several agent
sessions on one machine at once, and they share the primary checkout: a
`git switch` there moves the branch out from under every other session using
it, and carries one task's uncommitted edits, build output and `node_modules`
state into another's. A worktree per issue gives each task its own tree and
leaves the primary checkout alone.

Run it from the primary checkout. The worktree is a **sibling** directory named
for the checkout plus the issue number (`mcp-inspector-v2` →
`../mcp-inspector-v2-2661`), never a directory inside the repo, where every
lint, format and typecheck scope would see a second copy of the source:

```sh
git fetch origin
git worktree add --no-track "../$(basename "$PWD")-<ISSUE_NUMBER>" \
-b v2/fix/<ISSUE_NUMBER>-<slug> origin/v2/main # origin/v1/main for v1
cd "../$(basename "$PWD")-<ISSUE_NUMBER>"
npm install
```

- `--no-track` keeps the new branch from tracking `origin/v2/main`, so
`git status` does not report your work as "ahead of v2/main" and the first
push is an explicit `git push -u origin <branch>` to a branch of its own name.
- ⚠️ **The `npm install` is part of the step, not optional.** A worktree starts
with no `node_modules`, and it needs a **real** install — a symlinked
`node_modules` passes lint/test/coverage and then fails all Storybook story
files on Vite's `fs.allow`. Background it if you have edits to make first;
the gate needs it finished.
- Every later step — edits, the gate, commits, the push — runs **inside the
worktree**.

For order-dependent PRs on one issue, **stack** them: each branch is based on the
previous one, not all cut from `v2/main`.
previous one, not all cut from `v2/main` — so the child's worktree is cut from
the parent branch (`git worktree add … -b <child> <parent-branch>`).

## 3. Sign off every commit

Expand Down Expand Up @@ -453,3 +481,16 @@ nothing else.
`Done` is only for work that **shipped** — a merged PR, or a parent whose last
sub-issue closed. Anything else (duplicate, won't fix, not planned, obsolete)
means nothing shipped, so **delete the card** instead; see `/board-ops`.

**Then remove the worktree and its local branch**, from the primary checkout,
once the PR shows as merged (or closed, for work abandoned). A stale worktree
keeps its branch checked out — git refuses to check that branch out anywhere
else — and holds a full `node_modules` on disk per issue:

```sh
git worktree remove "../$(basename "$PWD")-<ISSUE_NUMBER>"
git branch -D v2/fix/<ISSUE_NUMBER>-<slug>
```

`git worktree remove` refuses a worktree with uncommitted or untracked changes;
read what is there before reaching for `--force`.
42 changes: 42 additions & 0 deletions .claude/skills/pre-push-gate/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,21 @@ stale install otherwise passes every check and fails later as a behavioral test
reporting the *old* dependency's behavior as a product bug (#2494). Don't
"fix" that test.

### `verify:install-scripts`

A dependency with an install script is neither allowed nor denied in the
`allowScripts` of the `package.json` beside that lockfile (#2712) — usually a
dependency you just added or bumped. npm 11.x still **runs** such a script, so
this is a review decision, not a typo: add `"<name>": false` to block it, or
`"<name>@<version>": true` if the package genuinely needs it. Each install
reads only its own manifest, so a package held by several installs needs an
entry in each. A **non-registry** dependency (git, file, remote tarball) is
reported even with no flagged script, since npm may run its `prepare`; clear it
with a key equal to its exact `resolved` spec from the lockfile. A **bundled**
one can't be cleared by any key — the fix is the dependency that bundles it.
Don't reach for `ignore-scripts` — it also disables the root
`postinstall` that installs every client.

### `local:dco`

A commit in `origin/v2/main..HEAD` (minus anything already on `origin/main`)
Expand Down Expand Up @@ -178,6 +193,25 @@ lowering the gate. See `/testing` for the acceptable reasons.
Also check the file is inside a gated directory — the web coverage `include` is
a whitelist, so a module placed outside it falls out of the gate silently.

### `verify:coverage-scope`

The last step of `coverage` (#2709). A client's `coverage-summary.json` is
missing files its own coverage `include`/`exclude` declares, so those files
were never judged by the per-file gate. The failure names the client and each
missing file. Two causes:

- **The run's glob matching changed** — typically a Vitest bump. The fix is
the client's `include` patterns (an absolute `path.join(dirname, …)` pattern
means the same thing under every matcher), never an entry that excuses the
files.
- **A file is in scope but the run legitimately drops it.** State it in
`KNOWN_OMISSIONS` in `scripts/verify-coverage-scope.mjs`, with the reason —
or, better, add it to the client's coverage `exclude`, which says the same
thing where the gate reads it.

"no `coverage-summary.json`" means the client's coverage did not run (or ran
without the `json-summary` reporter). Run `npm run coverage`.

### `smoke:web*`

⚠️ **An orphaned prod web server from a previous run fakes a rejection.** It
Expand Down Expand Up @@ -241,6 +275,14 @@ One stage has no GitHub CI counterpart, deliberately:
Firefox. Trialled as a CI job and removed (#2086): across a dozen runs it never
disagreed with Chromium, and `playwright install --with-deps` carries a real
flake surface. Kept in front of a human about to push instead.
⚠️ **On macOS 27 it runs inside the Linux Playwright container** (#2625):
Playwright's Firefox cannot launch there. It needs a running Docker daemon;
without one the stage prints a `SKIPPING … this is NOT a pass` warning and
exits 0 so `local:storybook` still runs — start Docker and re-run
`npm run smoke:web:firefox` before pushing. A container failure is a real
Firefox failure, not an infrastructure one, unless the log shows the image
pull or `npm install` failing. `INSPECTOR_FIREFOX_SMOKE=native|container`
overrides the routing (`scripts/lib/firefox-container.mjs`).

A guard (`scripts/lib/workflow-gate.mjs`, run by `npm run test:scripts`) fails
the suite if a workflow invokes a `local:*` script, a non-Chromium engine pass,
Expand Down
18 changes: 15 additions & 3 deletions .claude/skills/release/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,13 @@ the `pack:verify OK` line) for the ledger below.

**Every contribution closed in the milestone gets driven, not read.** The bar is
observed behavior from the running app — a rendered panel, a status attribute, a
server's own stderr — against a real test server, through whichever clients the
change touches (web, CLI, TUI). "Its tests pass" is not evidence for this step;
the gate already said that. For a change with no observable surface, the
server's own stderr — against a real test server, through whichever surfaces the
change touches: the web client, the one-shot CLI, the TUI, `mcpdo` (the
connection CLI, shipped in the same package since 2.10.0) and the Docker image.
**A change to `core/cli/` is driven through both CLIs** — the one-shot CLI and
`mcpdo` share its method handlers, exit codes, OAuth flow and output styling
(#2461), so passing through one says nothing about the other. "Its tests pass"
is not evidence for this step; the gate already said that. For a change with no observable surface, the
evidence is the thing that holds it — a probe that makes the guard fire, a
counted before/after, a resolved binary path.

Expand All @@ -187,6 +191,14 @@ and link it from PR 2. Shape it like the
- **One section per theme**, each a table of *Issue · What was driven ·
Observed · Status*. One row per closed issue, issue-linked, with the actual
output in the Observed cell.
- **An `mcpdo` row runs against a real connection** — `mcpdo connect …`, the
command under test, then `mcpdo disconnect …` — and its *What was driven*
cell shows all three. ⚠️ The connection daemon (`mcpdod`) outlives a
rebuild and keeps serving the code it started with, so a daemon left over
from before the production build smokes the wrong bundle and the row reads
as a pass. Run `pkill mcpdod` before the first `mcpdo` row (or rebuild with
`npm run build:dev` in `clients/mcpdo`, which stops it); see
`clients/mcpdo/README.md`.
- **Notes / findings** — anything that is a caveat rather than a pass, called
out rather than folded into a row.

Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/test-servers/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ exist whichever one you are in:
cd clients/web && npm run test-servers:build # tsc -p test-servers → test-servers/build/
```

Scripts reach this through `scripts/ensure-test-servers.mjs`, which builds
Scripts reach this through `scripts/lib/ensure-test-servers.mjs`, which builds
**unconditionally** (once per process per repo root).

⚠️ **Unconditional emit is not a clean.** A **deleted** source file leaves its
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,10 @@ jobs:
# This also covers the web integration project: web's `test:coverage`
# runs `--project=unit --project=integration --coverage`, so there is no
# separate integration step anywhere in this workflow.
#
# `coverage` ends with `verify:coverage-scope` (#2709), which fails if
# any client's report measured fewer files than its coverage `include`
# declares — the gate otherwise passes on whatever subset it was handed.
run: npm run coverage

# Publish the single `@modelcontextprotocol/inspector` package to npm on a
Expand Down
5 changes: 3 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -390,12 +390,13 @@ skills; the rules are here.
- **Every v2 board item has a Priority.** Priority is a **board field**, not a label, so an unboarded issue has nowhere to store it. Derive it with the rubric in the `issue-triage` skill rather than asserting it. Board #11 has no Priority field; a v1 issue gets a Status and nothing else.
- **`Incoming` ⇔ no milestone; everything past it ⇔ milestoned — on board #28.** Board #11 is exempt for the reason above: a v1 issue has no bucket to take, so its Status is set on its own and the audit's milestone checks do not apply to it. A `[GHSA-` **advisory draft** on #28 is exempt too, for a different reason: a draft card cannot carry a milestone, so its approval act is **accepting the advisory**, which moves it `Incoming` → `Todo`; its milestone arrives with the public issue after publication. The rest of the invariant is unchanged: assigning the milestone _is_ the approval act, so the two always go together. `Todo` asserts a maintainer signed off, so never park an unreviewed issue there — that erases the distinction and quietly promotes unreviewed work into the queue. An issue created through the documented flow skips `Incoming` entirely, because filing it _was_ the approval.
- **`Done` means the work shipped.** Exactly two things earn a card a place in Done: its **PR merged**, or it is a **parent whose last sub-issue closed**. Anything else — duplicate, won't fix, not planned, obsolete, superseded — means nothing shipped, so the card is **deleted**. Done is read as the record of what a milestone actually delivered; a duplicate sitting there makes that record wrong in a way nobody can detect later. Deleting a card touches the board only — the issue keeps its labels and comments and stays searchable forever.
- **When work begins**, assign the issue to yourself, create a feature branch and set Status to **In Progress**. **Branch names start with the target version segment** — `v2/fix/2071-oauth-resource-metadata`, `v1/fix/proxy-ssrf-pin` — matching the base branches themselves.
- **When work begins**, assign the issue to yourself, set Status to **In Progress**, and create the feature branch **in a new git worktree** — never by switching branches in the primary checkout, which concurrent agent sessions share (#2661); remove the worktree once the PR merges. The recipe is the `pr-flow` skill, step 2. **Branch names start with the target version segment** — `v2/fix/2071-oauth-resource-metadata`, `v1/fix/proxy-ssrf-pin` — matching the base branches themselves.
- **When work is complete**, run `npm run format` then `npm run local:gate`, **sign off every commit** (`git commit -s` — the repo-owned `DCO` check, `.github/workflows/dco.yml`, fails a PR on any unsigned commit with no partial credit; it gates merges into `v2/main` as a **required** status check, set by the `v2/main - DCO` repository ruleset (#2621) and pinned to GitHub Actions so only the workflow can satisfy it; a PR showing the check as missing or "expected" is an outage, not a pass), open a PR against the matching base branch with **`Closes #<ISSUE_NUMBER>` as the body's first line**, and set Status to **In Review**.
- **After opening a PR, run a Copilot review loop to exhaustion — unprompted.** Request a review, wait for the round to post _or_ for Copilot's session to end without one, answer every comment, and request again whenever a fix was pushed. Stop on the **first** clean round (no confirming round "just to be sure"), a round holding only out-of-scope findings, or two rounds in a row where Copilot's session ends without posting. **Weigh each finding against the issue the PR closes and decline scope expansion** — pre-existing behavior, new capabilities, and hardening the issue did not ask for — because that is what turns a review cycle into overbuilding. The recipe is the `pr-flow` skill, step 7.
- **Attach screenshots as proof of functionality** for any web-UI or TUI change. Put them in a **`pr-screenshots/`** folder off the repo root — it is **gitignored**, so the images are staged for upload and never committed — and name them for what they show.
- ⚠️ Closing keywords only auto-link and auto-close for PRs targeting the **default branch** (`main`). A v2 PR targets `v2/main`, so `Closes #N` there is only a cross-reference and the card shows no linked PR. **Link it explicitly** with the `addCloseIssueReferences` GraphQL mutation right after opening the PR (recipe in `pr-flow`, step 6). **On merge, manually close the issue and move the card to Done.** Keep the line anyway, so the issues close if/when `v2/main` reaches `main`.
- **If new tasks are discovered during development, create issues** and add them to the board.
- **Pace bulk GitHub writes: 1 s between requests, never in parallel, under 80 a minute and 500 an hour.** The secondary limit refuses while `gh api rate_limit` still shows quota, and most `gh` writes are GraphQL. After a refusal, wait out `retry-after`, or a minute without one; a refused create can still land, so look before retrying.

### Responding to Code Reviews

Expand All @@ -421,7 +422,7 @@ diagnose a failing gate — is the `testing` skill. These are the rules.
- **Root tooling**: a `scripts/*.mjs` helper with pure logic gets a sibling `*.test.mjs`. Keep that exact filename — `node --test` silently _skips_ a file its glob misses and still exits 0.
- **Render Ink components through the TUI's own `render`** (`clients/tui/__tests__/helpers/renderTui.tsx`), never `ink-testing-library`'s directly. It is the same function with every frame ANSI-stripped, which is what keeps an assertion on styled text from depending on the ambient environment: Ink writes styling _inside_ the styled run, so `<Text underline>I</Text>nfo` reaches the frame buffer with escapes between `I` and `nfo` and `toContain("Info")` fails. It only bites where chalk emits color — a developer whose shell exports `FORCE_COLOR` — so CI is green on a suite that is broken for them (#2207). A test that genuinely needs the raw bytes reads `stdout.lastFrame()` off the returned instance.
- **Render React components through `renderWithMantine`** (`src/test/renderWithMantine.tsx`); do not hand-roll a bare `MantineProvider`, which skips the project theme and the helper's options and drifts from every other test. Pass the `colorScheme` option to exercise a forced scheme rather than hand-rolling `defaultColorScheme`. Use `renderWithMantineTransitions` **only** when a test must assert mid-flight transition state, and read the long comment on the helper before changing anything about it.
- **The web coverage `include` is a whitelist.** It names `components`/`hooks`/`theme`/`lib`/`utils`/`server` plus the browser-consumed `core/*` runtime, so a module placed **outside** those directories falls out of the gate entirely, silently. Place new modules inside a gated directory. The documented exceptions — `src/App.tsx` and the `src/main.tsx` / `src/index.ts` bootstraps — are called out in a comment on the `include` array itself.
- **The web coverage `include` is a whitelist.** It names `components`/`hooks`/`theme`/`lib`/`utils`/`server` plus the browser-consumed `core/*` runtime, so a module placed **outside** those directories falls out of the gate entirely, silently. Place new modules inside a gated directory. The converse — the run measuring **fewer** files than the `include` declares, as web's did under vitest 5 (418 → 11, still green) — is not silent: `npm run verify:coverage-scope`, the last step of `coverage`, fails naming each missing file (#2709). Fix that by fixing the globs, never by excusing the files. The documented exceptions — `src/App.tsx` and the `src/main.tsx` / `src/index.ts` bootstraps — are called out in a comment on the `include` array itself.

### Test-gate timeouts are chosen values, stated once

Expand Down
Loading
Loading