Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
233 commits
Select commit Hold shift + click to select a range
fcec17f
fix: key the OAuth clear's active-session check on the storage key (#…
cliffhall Sep 3, 2026
19a3923
fix: terminate the OAuth connection-details refresh promise chain
cliffhall Sep 4, 2026
2ba25d6
fix(web): reset pending OAuth slots during render, not in an effect
cliffhall Sep 4, 2026
3c8fdb0
fix(web): drop the step-up retry when its prompt is cleared
cliffhall Sep 4, 2026
79896b6
fix: state the credential impact, not the disconnect, in the shared-U…
cliffhall Sep 4, 2026
b2bbfcb
fix: key the in-flight clear guard on the OAuth storage key too (#2217)
cliffhall Sep 4, 2026
258e7f1
refactor(web): let trySetPendingStepUp own the step-up retry
cliffhall Sep 4, 2026
0d81cf7
test: cover the App-level shared-key clear suppression (#2217)
cliffhall Sep 4, 2026
f59686c
Merge pull request #2237 from modelcontextprotocol/v2/fix/2223-oauth-…
cliffhall Sep 4, 2026
7975138
fix: only let the newest OAuth state read write, and harden its tests
cliffhall Sep 4, 2026
be86791
test: drop two double casts from the new App case (#2217)
cliffhall Sep 4, 2026
f78a00e
fix: resolve the clear's identity from the live client, in one place …
cliffhall Sep 4, 2026
fb0b795
Merge branch 'v2/main' into v2/fix/2217-oauth-clear-shared-url
cliffhall Sep 4, 2026
a37c068
Merge branch 'v2/main' into v2/fix/2221-oauth-refresh-unhandled-rejec…
cliffhall Sep 4, 2026
b4b750f
Merge pull request #2236 from modelcontextprotocol/v2/fix/2221-oauth-…
cliffhall Sep 4, 2026
7897d68
Merge branch 'v2/main' into v2/fix/2217-oauth-clear-shared-url
cliffhall Sep 4, 2026
e915d4f
Merge pull request #2238 from modelcontextprotocol/v2/fix/2217-oauth-…
cliffhall Sep 4, 2026
7dd9f47
chore(deps): npm audit fix before release bump; monthly npm-outdated …
cliffhall Sep 3, 2026
ee14a9f
chore(deps): move the dependabot.yml change out to #2235
cliffhall Sep 4, 2026
07bd987
chore(deps): address Copilot review round 1 on #2232
cliffhall Sep 4, 2026
ddf2307
test(scripts): stop the repo-guard test depending on the ambient env
cliffhall Sep 4, 2026
6af7442
chore(deps): remove dependabot.yml, fold action bumps into the sweep
cliffhall Sep 4, 2026
dde1736
chore(deps): treat every failed release-list response as fatal
cliffhall Sep 4, 2026
8414685
docs(scripts): correct the release-lookup contract left stale by round 4
cliffhall Sep 4, 2026
0cb12a1
chore(deps): paginate the release list so the highest version is actual
cliffhall Sep 4, 2026
66a3332
chore(deps): sweep Dependabot alerts into board-tracked issues
cliffhall Sep 4, 2026
b53266b
chore(deps): address Copilot review round 1 on #2243
cliffhall Sep 4, 2026
761bdd1
chore(deps): address Copilot review round 2 on #2243
cliffhall Sep 4, 2026
5c65bd2
chore(deps): address Copilot review round 3 on #2243
cliffhall Sep 4, 2026
1e58d2f
chore(deps): address Copilot review round 4 on #2243
cliffhall Sep 4, 2026
a17eace
chore(deps): address Copilot review round 5 on #2243
cliffhall Sep 4, 2026
ff339dc
chore(deps): address Copilot review round 6 on #2243
cliffhall Sep 4, 2026
1d6ea1a
chore(deps): address Copilot review round 7 on #2243
cliffhall Sep 4, 2026
9e516ae
chore(deps): address Copilot review rounds 8-10 on #2243
cliffhall Sep 4, 2026
2336471
chore(deps): address Copilot review round 11 on #2243
cliffhall Sep 4, 2026
bc47fcb
chore(deps): address Copilot review round 12 on #2243
cliffhall Sep 4, 2026
c0d1d56
chore(deps): address Copilot review round 13 on #2243
cliffhall Sep 4, 2026
e846dec
chore(deps): address Copilot review round 14 on #2243
cliffhall Sep 4, 2026
0bf8fbd
chore(deps): address Copilot review round 15 on #2243
cliffhall Sep 4, 2026
1c1e708
Merge pull request #2243 from modelcontextprotocol/v2/chore/2233-depe…
cliffhall Sep 4, 2026
7594097
feat(skills): measure a skill reached from another skill (#2204)
cliffhall Sep 4, 2026
4033523
test(auth): make the revocation fixture a real form-urldecoder
cliffhall Sep 4, 2026
f20bbac
feat(skills): address Copilot review round 1 on #2204
cliffhall Sep 4, 2026
da47506
Merge pull request #2246 from modelcontextprotocol/v2/fix/2222-basic-…
cliffhall Sep 4, 2026
33a1408
Merge branch 'v2/main' into v2/feat/2204-chained-skill-eval
cliffhall Sep 4, 2026
3ec1257
feat(skills): address Copilot review round 2 on #2204
cliffhall Sep 5, 2026
1018d81
chore(deps): refresh fast-uri, qs and browserslist to clear npm audit
cliffhall Sep 4, 2026
37486b7
Merge v2/main sync into the 2204 branch
cliffhall Sep 5, 2026
313a580
feat(skills): address Copilot review round 3 on #2204
cliffhall Sep 5, 2026
dfbd459
docs(skills): record the hand-off measurement honestly after the turn…
cliffhall Sep 5, 2026
63623b7
feat: support the Skills extension (SEP-2640) with digest verification
cliffhall Sep 5, 2026
da8cc16
fix: address Copilot review round 1 on #2251
cliffhall Sep 5, 2026
bfeebd4
fix: address Copilot review round 2 on #2251
cliffhall Sep 5, 2026
6a08c77
fix: address Copilot review round 3 on #2251
cliffhall Sep 5, 2026
1359b02
Merge branch 'v2/main' into v2/chore/2244-npm-audit-advisories
cliffhall Sep 5, 2026
1cb05ca
fix: address Copilot review round 4 on #2251
cliffhall Sep 5, 2026
0373bf9
Merge pull request #2249 from modelcontextprotocol/v2/chore/2244-npm-…
cliffhall Sep 5, 2026
27fafe6
fix(web): make the Connection Info extension sections say something
cliffhall Sep 5, 2026
754ce5b
fix: address Copilot review round 5 on #2251
cliffhall Sep 5, 2026
ff1e027
Merge branch 'v2/main' into v2/feat/2204-chained-skill-eval
cliffhall Sep 5, 2026
4e676a0
fix: address Copilot review round 6 on #2251
cliffhall Sep 5, 2026
1f33ba9
fix: address Copilot review round 7 on #2251
cliffhall Sep 5, 2026
7e291f9
fix: address Copilot review round 8 on #2251
cliffhall Sep 5, 2026
c1a7cfb
fix: address Copilot review round 9 on #2251
cliffhall Sep 5, 2026
9d162f3
fix: address Copilot review round 10 on #2251
cliffhall Sep 5, 2026
d030207
fix: address Copilot review round 11 on #2251
cliffhall Sep 5, 2026
63f89fa
Merge branch 'v2/main' into v2/feat/2234-skills-extension
cliffhall Sep 5, 2026
eb44e6d
Merge pull request #2245 from modelcontextprotocol/v2/feat/2204-chain…
cliffhall Sep 5, 2026
18724b2
Merge branch 'v2/main' into v2/feat/2234-skills-extension
cliffhall Sep 5, 2026
bd28a36
fix: address Copilot review round 12 on #2251
cliffhall Sep 5, 2026
dc2dd2b
fix(web): remove the wall-clock race in the import-JSON debounce guar…
cliffhall Sep 5, 2026
84a65f2
fix(auth): floor the shared revocation budget instead of racing zero
cliffhall Sep 5, 2026
4d7dd18
fix: address Copilot review round 13 on #2251
cliffhall Sep 5, 2026
c736f1d
test(cli): pin the CLI's own minimum-budget floor
cliffhall Sep 5, 2026
927a708
test(auth): stub the clock in both floor regression tests
cliffhall Sep 5, 2026
11ac134
feat: require the modern list envelope on skills/list (review round 14)
cliffhall Sep 5, 2026
a561cd1
fix: address Copilot review round 15 on #2251
cliffhall Sep 5, 2026
1ee9580
feat(skills): address Copilot review round 16 on #2234
cliffhall Sep 5, 2026
abd28bc
Merge pull request #2255 from modelcontextprotocol/v2/fix/2250-import…
cliffhall Sep 5, 2026
7c6a7b7
Merge branch 'v2/main' into v2/fix/2252-revocation-deadline-epsilon
cliffhall Sep 5, 2026
86ef7b1
Merge pull request #2256 from modelcontextprotocol/v2/fix/2252-revoca…
cliffhall Sep 5, 2026
5af5430
Merge branch 'v2/main' into v2/feat/2234-skills-extension
cliffhall Sep 5, 2026
ed2a188
Merge pull request #2251 from modelcontextprotocol/v2/feat/2234-skill…
cliffhall Sep 5, 2026
f5a3cce
fix: type-discriminate progress toast ids, CSPRNG attempt-id fallback
cliffhall Sep 5, 2026
1e6bf64
chore: widen verify:dep-lockstep to declared cross-install copies (#2…
cliffhall Sep 5, 2026
b05e3f5
chore: grant artifact-metadata:write to the GHCR publish job (#2228)
cliffhall Sep 5, 2026
f48cf2a
fix: narrow the crypto-member delete cast in the attempt-id tests
cliffhall Sep 5, 2026
7d0ae9e
Reshape the testing → test-servers pointer into an imperative step
cliffhall Sep 5, 2026
229e715
Merge pull request #2258 from modelcontextprotocol/v2/chore/2228-ghcr…
cliffhall Sep 5, 2026
8ed0bed
fix: call getRandomValues directly, and test true crypto absence
cliffhall Sep 5, 2026
8e2c4d4
chore: address Copilot review round 1 (#2226)
cliffhall Sep 5, 2026
02f094f
Review round 1: gate the hand-off on connecting, not on tier depth
cliffhall Sep 5, 2026
5daa3f5
chore: address Copilot review round 2 (#2226)
cliffhall Sep 5, 2026
cd7fe9a
Review round 2: "an integration test" is not the trigger either; conn…
cliffhall Sep 5, 2026
d9da29d
Merge branch 'v2/main' into v2/fix/2216-progress-toast-id-and-csprng
cliffhall Sep 5, 2026
0894ab3
Review round 3: consuming a fixture is a trigger too; drop the brittl…
cliffhall Sep 5, 2026
95633a2
chore: address Copilot review round 3 (#2226)
cliffhall Sep 5, 2026
e85a78f
Review round 4: key on using the artefact, and split the two trigger …
cliffhall Sep 5, 2026
7f1b8de
Review round 5: scope the opening section's closer to the connecting …
cliffhall Sep 5, 2026
03af5b9
Review round 6: 80% does not clear a strictly-compared 0.8
cliffhall Sep 5, 2026
ec6895a
Remove the build-gate probe accidentally committed to main.tsx
cliffhall Sep 5, 2026
7abc825
Merge pull request #2259 from modelcontextprotocol/v2/fix/2216-progre…
cliffhall Sep 5, 2026
0d947ad
Review round 8: using a fixture, not connecting, is the trigger
cliffhall Sep 5, 2026
066c985
Merge pull request #2260 from modelcontextprotocol/v2/chore/2226-type…
cliffhall Sep 5, 2026
5eb350f
Merge pull request #2261 from modelcontextprotocol/v2/fix/2247-testin…
cliffhall Sep 5, 2026
e67eb34
feat: refactor the Skills detail pane into collapsible sections (#2263)
cliffhall Sep 6, 2026
98b39f9
Merge branch 'v2/main' into v2/feat/2263-skills-detail-pane
cliffhall Sep 6, 2026
0a4e618
fix: cap the re-auth banner width and move its flat CSS into the Pape…
cliffhall Sep 6, 2026
a0f9126
fix: swap the toast ref Set on teardown instead of clearing it (#2219)
cliffhall Sep 6, 2026
5402aea
Merge pull request #2266 from modelcontextprotocol/v2/fix/2218-reauth…
cliffhall Sep 6, 2026
f5a3ebf
feat: make Conformance the one place a skill verdict is reported (#2263)
cliffhall Sep 6, 2026
418448e
fix: address Copilot review round 2 (#2263)
cliffhall Sep 6, 2026
ae33582
fix: let a URI suffix outrank a generic declared MIME (#2263)
cliffhall Sep 6, 2026
d8f0e77
fix: seed the section state on mount, and drop a dead dynamic branch …
cliffhall Sep 6, 2026
fa03c74
fix: let metadata sections shrink to their floor again (#2263)
cliffhall Sep 6, 2026
d780898
fix: address Copilot review round 6 (#2263)
cliffhall Sep 6, 2026
52e8e1b
fix: address Copilot review round 7 (#2263)
cliffhall Sep 6, 2026
e8bbcf1
fix: bound every header string, and make scrollable panels keyboard-r…
cliffhall Sep 6, 2026
1a2e375
fix: bound the resource file name, and move its typography into the t…
cliffhall Sep 6, 2026
10c8f5d
fix: address Copilot review round 10 (#2263)
cliffhall Sep 6, 2026
ede9658
fix: guard the automatic read, and reset panel scroll on skill change…
cliffhall Sep 6, 2026
25255c3
fix(skills): clear the auto-read guard when the selection leaves the …
cliffhall Sep 6, 2026
50a8f5f
Merge branch 'v2/main' into v2/feat/2263-skills-detail-pane
cliffhall Sep 6, 2026
b1e322c
Merge branch 'v2/main' into v2/fix/2219-toast-teardown-set
cliffhall Sep 6, 2026
80a013c
feat: watch the MCP SDK nightly and file an upgrade issue (#1063)
cliffhall Sep 6, 2026
4b611d7
fix: stop the sdk-watch tests depending on the runner's environment
cliffhall Sep 6, 2026
3b3c7e3
fix: address Copilot review round 1 on the SDK watch
cliffhall Sep 6, 2026
6711593
fix: address Copilot review round 2 on the SDK watch
cliffhall Sep 6, 2026
e9a1571
fix: address Copilot review round 3 on the SDK watch
cliffhall Sep 6, 2026
2a6c510
fix: address Copilot review round 4 on the SDK watch
cliffhall Sep 6, 2026
cbf84ce
fix: address Copilot review round 5 on the SDK watch
cliffhall Sep 6, 2026
2c330da
Merge pull request #2265 from modelcontextprotocol/v2/feat/2263-skill…
cliffhall Sep 6, 2026
6d7e67d
Merge branch 'v2/main' into v2/fix/2219-toast-teardown-set
cliffhall Sep 6, 2026
7deb8f2
fix: address Copilot review round 6, and close out the federation fol…
cliffhall Sep 6, 2026
d80bb13
Merge pull request #2268 from modelcontextprotocol/v2/feat/1063-sdk-w…
cliffhall Sep 6, 2026
82ca2cd
Merge branch 'v2/main' into v2/fix/2219-toast-teardown-set
cliffhall Sep 6, 2026
6d93a33
Merge pull request #2267 from modelcontextprotocol/v2/fix/2219-toast-…
cliffhall Sep 6, 2026
99ac467
docs: specify screenshot capture width and Monitor sidebar width in /…
cliffhall Sep 6, 2026
c61a553
docs: scope §5a to web captures and drop the historical-consistency c…
cliffhall Sep 6, 2026
edab149
docs: name the two smokes that set 1280x900, not a wildcard
cliffhall Sep 6, 2026
27bf55e
docs: rule that a wait is a notification, never a tight poll loop (#2…
cliffhall Sep 6, 2026
e8a822b
docs: make the review poll fail loudly, and honor the 30s floor
cliffhall Sep 6, 2026
114717f
docs: exit the poll loop on a jq failure too, not just a gh failure
cliffhall Sep 6, 2026
ed62239
Merge pull request #2272 from modelcontextprotocol/v2/docs/2253-wait-…
cliffhall Sep 6, 2026
f504b89
docs: reply to each review comment in its own thread, not in a rollup…
cliffhall Sep 6, 2026
5a1b590
docs: a reply does not resolve a review thread
cliffhall Sep 6, 2026
ed5e98b
docs: paginate the review-comments fetch
cliffhall Sep 6, 2026
23698af
Merge pull request #2273 from modelcontextprotocol/v2/docs/2254-inlin…
cliffhall Sep 6, 2026
81f2115
fix: decline a union branch requiring a name it never declares (#2224)
cliffhall Sep 6, 2026
ade7b57
docs: add a reusable CLI smoke-testing guide for v2 (#1886)
cliffhall Sep 6, 2026
c80f90e
docs: address Copilot review round 1 on the CLI smoke-testing guide
cliffhall Sep 6, 2026
9b35e53
fix: send an empty-string pagination cursor verbatim on every list ad…
cliffhall Sep 6, 2026
d4f2f2b
docs: address Copilot review round 2 on the CLI smoke-testing guide
cliffhall Sep 6, 2026
3b4eb44
fix: walk past an empty-string cursor in the legacy task refresh (#2220)
cliffhall Sep 6, 2026
4886ecd
docs: address Copilot review round 3 on the CLI smoke-testing guide
cliffhall Sep 6, 2026
ed83bfb
docs: reconcile store isolation with --stored-auth-only in the §8 script
cliffhall Sep 6, 2026
e20559c
docs: correct app-info signaling and the pipefail claim (Copilot roun…
cliffhall Sep 6, 2026
8dfb2c8
docs: harden the Actions example in the CLI smoke-testing guide
cliffhall Sep 6, 2026
0a30935
test: assert a fully-declined union still counts as taking arguments
cliffhall Sep 6, 2026
8bca482
Merge pull request #2275 from modelcontextprotocol/v2/docs/1886-cli-s…
cliffhall Sep 6, 2026
7f4d851
Merge branch 'v2/main' into v2/fix/2224-union-required-undeclared
cliffhall Sep 6, 2026
21d58c0
Merge branch 'v2/main' into v2/fix/2220-empty-string-cursor
cliffhall Sep 6, 2026
42babb7
Merge pull request #2277 from modelcontextprotocol/v2/fix/2220-empty-…
cliffhall Sep 6, 2026
665e8aa
Merge branch 'v2/main' into v2/fix/2224-union-required-undeclared
cliffhall Sep 6, 2026
3153f03
fix: key resource list rows by position so duplicate URIs cannot collide
cliffhall Sep 6, 2026
a3bb679
fix: strip ANSI from TUI test frames so FORCE_COLOR cannot break asse…
cliffhall Sep 7, 2026
eab42d3
Merge pull request #2276 from modelcontextprotocol/v2/fix/2224-union-…
cliffhall Sep 7, 2026
1b5a0b5
Merge branch 'v2/main' into v2/fix/2207-tui-force-color-ansi
cliffhall Sep 7, 2026
339c5f4
fix: duplicate any listed resource URI, not only a registered one
cliffhall Sep 7, 2026
750aa5b
Merge pull request #2279 from modelcontextprotocol/v2/fix/2207-tui-fo…
cliffhall Sep 7, 2026
849eb08
Merge pull request #2281 from modelcontextprotocol/v2/fix/2206-duplic…
cliffhall Sep 7, 2026
3e2546b
feat: seed the MCP org example server as a remote first-run card (#2201)
cliffhall Sep 7, 2026
8fd9e41
docs: refresh the server-list spec's seed contract for the third seed
cliffhall Sep 7, 2026
d476dc5
docs: the catalog is seeded on first read, not at boot
cliffhall Sep 7, 2026
aab6475
Merge pull request #2283 from modelcontextprotocol/v2/feat/2201-seed-…
cliffhall Sep 7, 2026
db122f5
feat(web): collapse the schema-portability section by default (#2205)
cliffhall Sep 7, 2026
4789cb9
fix: preserve CIMD registration provenance across SDK issuer binding …
cliffhall Sep 7, 2026
b785bf3
Merge pull request #2285 from modelcontextprotocol/v2/feat/2205-toggl…
cliffhall Sep 7, 2026
2c25259
Merge branch 'v2/main' into v2/fix/2242-cimd-registration-kind
cliffhall Sep 7, 2026
c8c050b
fix: require a recorded CIMD registration before preserving the kind
cliffhall Sep 7, 2026
f3f68c7
fix: keep CIMD provenance when a resource resolves to a second issuer
cliffhall Sep 7, 2026
4c6a9fb
fix: bind CIMD provenance to the issuer it was discovered for
cliffhall Sep 7, 2026
4297ef8
fix: record CIMD provenance as an issuer-keyed marker, not on the cre…
cliffhall Sep 7, 2026
4350731
docs: correct the saveClientInformation contract comment
cliffhall Sep 7, 2026
abb6a47
fix: earn the CIMD marker, rather than writing it on AS support alone
cliffhall Sep 7, 2026
6273790
fix: read the SDK's own discovery state instead of a marker of our own
cliffhall Sep 7, 2026
be08f6d
test: restore end-to-end coverage of resolveSdkRegistrationKind
cliffhall Sep 7, 2026
aca522d
fix: delegate issuer context and discovery state through the EMA wrapper
cliffhall Sep 7, 2026
98911df
Merge pull request #2287 from modelcontextprotocol/v2/fix/2242-cimd-r…
cliffhall Sep 7, 2026
b4b8249
fix: report a terminal OAuth token-endpoint refusal instead of a dead…
cliffhall Sep 7, 2026
6c1b532
test: drop strictPort and document the port collision instead
cliffhall Sep 7, 2026
f12ce5a
fix: correct two false claims in the terminal-notice copy (review rou…
cliffhall Sep 7, 2026
6650c0b
docs: ALLOWED_ORIGINS recipe for a *.localhost proxy
cliffhall Sep 7, 2026
084a083
fix: usable IPv6 spelling, and drop a SEP label that means something …
cliffhall Sep 7, 2026
0acac24
docs: every state-changing request 403s, not just the POSTs (review r…
cliffhall Sep 7, 2026
a5b356d
Merge pull request #2290 from modelcontextprotocol/v2/docs/2289-allow…
cliffhall Sep 7, 2026
8ca00fa
test: make the not-an-OAuthError test assert its own title (review ro…
cliffhall Sep 7, 2026
c2d566a
refactor: one shared reporter for the terminal refusal (review round 4)
cliffhall Sep 7, 2026
a5a9d4f
fix: the classifier does not survive structuredClone, and the test no…
cliffhall Sep 7, 2026
a16df92
Merge branch 'v2/main' into v2/fix/2280-insecure-token-endpoint-notice
cliffhall Sep 7, 2026
219a08e
Merge pull request #2288 from modelcontextprotocol/v2/fix/2280-insecu…
cliffhall Sep 7, 2026
ff0f5d2
fix: wait for the reopened SkillsScreen layout to settle before compa…
cliffhall Sep 7, 2026
16a743f
fix: give the Ace-worker story a budget that can outlast a loaded mac…
cliffhall Sep 7, 2026
9a84886
feat: Skills extension phase 3 — CLI, TUI, directory reads, frontmatt…
cliffhall Sep 7, 2026
7751077
fix: address Copilot review round 1 on #2248
cliffhall Sep 7, 2026
d8100e8
Merge pull request #2291 from modelcontextprotocol/v2/fix/2278-skills…
cliffhall Sep 7, 2026
4fa00d1
feat: report a skill-name collision across the listing (#2248)
cliffhall Sep 7, 2026
033600e
fix: address Copilot review round 2 on #2248
cliffhall Sep 7, 2026
6b83727
fix: address Copilot review round 3 on #2248
cliffhall Sep 7, 2026
7997635
fix: address Copilot review round 4 on #2248
cliffhall Sep 7, 2026
916b08b
fix: address Copilot review round 5 on #2248
cliffhall Sep 8, 2026
9f28825
Merge branch 'v2/main' into v2/feat/2248-skills-phase3
cliffhall Sep 8, 2026
e5f2fdb
test: pin the reviewer's exact cyclic-alias example
cliffhall Sep 8, 2026
d6b1e36
fix: address Copilot review round 7 on #2248
cliffhall Sep 8, 2026
8ae1a16
fix: address Copilot review round 8 on #2248
cliffhall Sep 8, 2026
88c1b89
fix: address Copilot review round 9 on #2248
cliffhall Sep 8, 2026
50441f4
fix: address Copilot review round 10 on #2248
cliffhall Sep 8, 2026
60d5f40
fix: address Copilot review round 11 on #2248
cliffhall Sep 8, 2026
27f1b2f
fix: address Copilot review round 12 on #2248
cliffhall Sep 8, 2026
4f12d07
fix: address Copilot review round 13 on #2248
cliffhall Sep 8, 2026
01a8f14
fix: address Copilot review round 14 on #2248
cliffhall Sep 8, 2026
89438d1
fix: address Copilot review round 15 on #2248
cliffhall Sep 8, 2026
5a1f0ef
fix: address Copilot review round 16 on #2248
cliffhall Sep 8, 2026
9117f63
fix: address Copilot review round 17 on #2248
cliffhall Sep 8, 2026
a3f36ce
fix: address Copilot review round 18 on #2248
cliffhall Sep 8, 2026
62fd7d1
fix: address Copilot review round 19 on #2248
cliffhall Sep 8, 2026
fb1dd1f
Merge pull request #2293 from modelcontextprotocol/v2/feat/2248-skill…
cliffhall Sep 8, 2026
440a8e2
docs(release): make the two-PR flow, smoke, ledger and UI tag explici…
cliffhall Sep 9, 2026
770fe44
Merge pull request #2299 from modelcontextprotocol/v2/docs/2298-relea…
cliffhall Sep 9, 2026
16ecde2
fix(deps): raise hono floor to ^4.13.7, clearing three moderate advis…
cliffhall Sep 9, 2026
fa4b782
chore(release): bump version to 2.6.0
cliffhall Sep 9, 2026
86f25bd
Merge pull request #2302 from modelcontextprotocol/v2/chore/2300-bump…
cliffhall Sep 9, 2026
af78163
chore: merge v2/main for the v2.6.0 milestone release
cliffhall Sep 9, 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
52 changes: 35 additions & 17 deletions .claude/skills/local-dev/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,8 @@ The point of deleting the client-side copies rather than merely keeping them in
step is that **a package installs only into an install root that declares it**.
Aligned duplicate declarations still drift the next time someone bumps one of
them; no declaration at all cannot. `npm run verify:dep-lockstep` is the detector
for the skew, and consolidation is what removes the opportunity.
for the skew — in both its tiers since #2226 — and consolidation is what removes
the opportunity.

Two consequences that read as bugs and are not:

Expand All @@ -146,7 +147,7 @@ supposed to rule out.
**`react` and `react-dom` are the exception, and stay pinned per client.** They
are a matched pair — `react-dom` reaches into React internals — and `react-dom`
is still web-declared, so npm resolves it and its React peer together inside
`clients/web/node_modules` (19.2.8 today, against the root's 19.2.7). Pointing
`clients/web/node_modules`. Pointing
`react` at the root while `react-dom` resolves from the client would pair a
renderer with a React it was not installed against, which is the same split the
pin exists to prevent, arrived at from the other side. `dedupe` still collapses
Expand Down Expand Up @@ -209,18 +210,27 @@ on disk. The two mechanisms are **not** equally safe, and neither is a guarantee
wide range (`eslint-plugin-react-refresh` accepts `^9 || ^10`) the copies agree
only because npm happens to resolve the same latest in both installs, which is
a coincidence that holds until it doesn't.
- A **transitive** copy is constrained by nothing of ours whatsoever, and one has
already diverged: cli's `@types/node` is `24.13.1` against the root's
`24.13.3`, and was `24.13.1` on `v2/main` too — a declared `^24.12.4` loses to
a nearer transitive.

⚠️ **Nothing gates either of those, and `verify:dep-lockstep` is not it.**
That guard derives its candidate set from what each `tsc` **program** resolves
(see below), so it sees only packages a program loads from two installs. A tool
*binary* — `eslint`, `prettier`, `vitest` — never enters a program, so it is
outside the candidate set no matter how far it drifts, and the cli `@types/node`
skew above passes for a second reason on top of that: no one program sees both
copies. When you change what a client declares, check by hand from that client:
- A **transitive** copy is constrained by nothing of ours whatsoever, and one had
already diverged: cli's `@types/node` was `24.13.1` against the root's
`24.13.3`, on `v2/main` too — a declared `^24.12.4` loses to a nearer
transitive. It is pinned with an `overrides` entry in `clients/cli` since
#2226.

✅ **`verify:dep-lockstep` gates both of those since #2226.** Its second tier
compares every package **any** install *declares* — `dependencies`,
`devDependencies` and `optionalDependencies`, unioned across the root and all
four clients — against every **top-level** copy in every install, independent of
what a `tsc` program resolves. So a tool *binary* that no program loads
(`eslint`, `typescript`, `vitest`) and a transitive copy that no single program
meets (the cli `@types/node` above) are both in scope now, as is a skew between
two **clients** with no root copy involved (`@types/react`, web against tui).

⚠️ **Two gaps remain, and they are why the by-hand check below is still worth
running.** The tier reads **lockfiles**, so a copy you installed by hand and
never committed is invisible to it; and it compares only names some manifest
declares, so a purely transitive package no manifest anywhere names stays the
program tier's business. When you change what a client declares, check by hand
from that client:

```sh
cd clients/web && npm exec -- which eslint prettier tsc vitest
Expand Down Expand Up @@ -307,9 +317,17 @@ recursive-generic surface is exponential. A zod `4.3.6` / `4.4.3` skew exhausted
the 4 GB tsc heap outright with `TS2589` (#1896).

⚠️ **Raising the heap hides the class rather than fixing it.** Align the
versions; `npm run verify:dep-lockstep` is the guard, and it derives its
candidate set from what actually enters each `tsc` program, so a package whose
declarations arrive only through another package's `.d.ts` is still seen.
versions; `npm run verify:dep-lockstep` is the guard, and it runs **two tiers**.
The first derives its candidate set from what actually enters each `tsc`
program, so a package whose declarations arrive only through another package's
`.d.ts` is still seen. The second (#2226) compares every **declared** package's
top-level copies across installs whatever any program loads, so a transitive or
peer-shadow drift no program can meet is caught too.

Aligning a stale install is `npm update <pkg>` there — it moves the lockfile
within the declared range without widening the range, which
`npm install <pkg>@<version>` would. A transitive copy that will not move takes
an `overrides` entry in that install (see the next section).

### Why `overrides` beats `npm audit fix`

Expand Down
153 changes: 143 additions & 10 deletions .claude/skills/pr-flow/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ not:
only defaults the `-s` flag for `git format-patch`; `git commit` never reads it,
and there is no `commit.signoff` equivalent.
- ⚠️ **A `prepare-commit-msg` hook works, but think before installing one.** The
trailer is a certification, and a hook makes it on your behalf for *every*
trailer is a certification, and a hook makes it on your behalf for _every_
commit, including work you merely cherry-picked. Inside that hook,
`git var GIT_AUTHOR_IDENT` returns your config identity rather than the
preserved author, so it cannot even tell it is signing for someone else.
Expand All @@ -90,7 +90,7 @@ access sees only silences the check without anyone certifying anything.
The signoff is a [Developer Certificate of
Origin](https://developercertificate.org/) assertion made in **your own name**. It
does not claim you wrote the code, so signing off a cherry-pick is legitimate.
What is never acceptable is fabricating *someone else's* certification.
What is never acceptable is fabricating _someone else's_ certification.

## 4. Run the gate

Expand All @@ -107,13 +107,85 @@ committed — so attach them to the PR body from there rather than referencing a
in-repo path. Name them for what they show (`tools-tab-before.png`), not
`Screenshot 2026-07-31 at 14.02.11.png`.

### 5a. Capture settings — web

Everything in 5a is about a **browser** capture and assumes Playwright driving
the web client. A **TUI** change has no viewport and no `fullPage` mode: size
the terminal so no line wraps or truncates, and go straight to 5b, which applies
to every image regardless of how it was taken.

**Shoot the web client at 1280×900, full page.** It is the one size already
written down anywhere in the repo — `scripts/smoke-web-tabs.mjs` and
`scripts/smoke-web-elicitation.mjs` set exactly that viewport (the other two web
smokes set none) — and adopting it as the standard here is what makes a reviewer
comparing two PRs compare the same thing. The older shots checked into
`specification/screenshots/` were taken at assorted sizes, which is the problem,
not the precedent. Prefer a full-page shot over a
Playwright `clip` region: a clip sized to one panel cuts off anything placed
beside it, and two clips of different sizes make a before/after pair hard to
read as a pair.

⚠️ **Widening the window does not widen the Monitor sidebar.** The
main/sidebar split is a draggable divider whose width is stored independently of
the viewport (`localStorage["inspector.monitor.width"]`, default **420px**,
clamped to **320–720**), so a bigger screen grows the _content_ column and
leaves the sidebar exactly as clipped as it was. Both levers have to be set, and
only one of them is obvious. On #2234 this cost three full re-captures: the
first set clipped the sidebar, the second still clipped it after only the window
was widened, and the third worked once the divider itself was moved.

**So when a shot includes the Monitor sidebar, set its width explicitly** —
give it enough room that no row truncates, favoring the sidebar over the
left-hand list, which usually has room to give up. Two ways, in order of
preference:

```js
// Deterministic: seed the stored width before the app loads.
await context.addInitScript(() =>
localStorage.setItem("inspector.monitor.width", "640"),
);
```

```js
// Or drive the divider itself — it is a keyboard-operable ARIA separator,
// and ArrowLeft widens the sidebar one 16px step per press.
const handle = page.getByRole("separator", {
name: "Resize monitoring sidebar",
});
await handle.focus();
for (let i = 0; i < 14; i++) await handle.press("ArrowLeft");
```

Two more mechanics worth setting before the shutter:

- **Wait ~900ms after switching the main view.** The Servers→Tools switch is a
crossfade, so an immediate shot renders _both_ views stacked translucently and
reads as a broken app. Waiting on a locator in the incoming view is not enough —
the outgoing one is still fading.
- **Mark focus when the change is about focus.** Tab order and keybinding fixes
look identical at rest, so after driving the keystroke, `page.evaluate` over
`document.activeElement`, outline it, and log its tag + `aria-label` — that
line is the actual assertion and the image is the evidence. **Say in the PR
body that the outline is script-added**, not app UI.

### 5b. Read the shot back before uploading — web and TUI

**Open every image and confirm nothing is cut off at either edge** — no
truncated row, clipped badge, or value running under a panel border, and no
half-faded view. This is a real check with your own eyes, not a formality: a
clipped screenshot is worse than no screenshot, because a reviewer reads the
truncation as a rendering bug in the feature under review and files it back at
you. Re-shoot rather than shipping one that "mostly" shows the change.

### 5c. Upload

To host them, upload to GitHub's attachment endpoint with your `gh` token. Two
mechanics, both of which bite:

- The parameters go in the **query string**, with the raw bytes as the body. A
JSON body fails with a misleading "Invalid name for request".
- ⚠️ **Do not put the token in argv.** `-H "Authorization: token $(gh auth
token)"` puts your credential in curl's command line, where any local user or
token)"` puts your credential in curl's command line, where any local user or
process can read it off the process table while the upload runs (Copilot).
Feed it through `--config -` instead: curl reads its options from stdin, so
the token never becomes an argument.
Expand All @@ -124,7 +196,7 @@ printf 'header = "Authorization: token %s"\n' "$(gh auth token)" | curl -sS --co
"https://uploads.github.com/user-attachments/assets?repository_id=<REPO_ID>&name=tools-tab-after.png&content_type=image/png"
```

(The token is still in the shell's environment and in `printf`'s *stdin*, which
(The token is still in the shell's environment and in `printf`'s _stdin_, which
is not world-readable the way `/proc/<pid>/cmdline` is.)

## 6. Open the PR
Expand Down Expand Up @@ -168,17 +240,78 @@ gh api graphql -f query='
```

Poll for the review with a `startswith` match — the review login carries a
`[bot]` suffix.
`[bot]` suffix. **Put that poll in one backgrounded loop that exits when the
round lands, and wait for its notification** rather than re-fetching once per
turn; a review is remote state the harness cannot observe, which is exactly the
exception described in [Waiting on long-running
work](../../../AGENTS.md#waiting-on-long-running-work) — and exactly where the
poll belongs when one is needed.

```sh
EXPECTED=1 # the review COUNT you are waiting to reach — see below
while :; do
# Capture first, so a gh failure stops the loop instead of being swallowed by
# a pipeline. --slurp cannot be combined with --jq, hence the separate jq.
raw=$(gh api --paginate --slurp \
repos/modelcontextprotocol/inspector/pulls/<N>/reviews) || {
echo "gh api failed ($?) — not retrying blind" >&2; exit 1; }
n=$(jq '[.[][] | select(.user.login | startswith("copilot-pull-request-reviewer"))] | length' <<<"$raw") || {
echo "jq failed ($?) on an unexpected response shape" >&2; exit 1; }
case $n in '' | *[!0-9]*) echo "not a count: '$n'" >&2; exit 1 ;; esac
[ "$n" -ge "$EXPECTED" ] && break
sleep 30
done
```

`EXPECTED` is the review **count** you are waiting to reach, so it is `1` only
on the first round — on round two the first round's review is still there and an
existence check returns immediately. `sleep 30` is the remote-API floor the rule
above sets. **Every step that can fail exits the loop rather than
retrying.** Piping the count straight into `awk` would make an auth or API error
read as a count of `0`; and a `jq` failure on an unexpected shape leaves `n`
empty, whereupon `[ "" -ge 1 ]` exits non-zero, `break` never fires, and the job
sleeps and retries forever — the same unbounded wait, reached from the other
end. A background task that can never succeed is worse than one that never
started, because it looks like progress. Give the inline comments a further ~60s after the body lands; they
arrive late (see step 8).

## 8. Respond to the review

- It is **not** necessary to implement every suggestion. Implementing one a
different way, or declining it with a reason, is fine.
- After making the changes, **respond to each comment** with what was done, or
why it was ignored.
- ⚠️ **Inline replies go hidden once the fix is pushed** (the threads become
outdated), so **mirror each round at PR level** as a summary comment, and always
read the "Suppressed comments" block.
- After making the changes, **reply to each review comment in its own thread**
with what was done, or why it was declined. That inline reply is the primary
response and it is not optional — each review comment is a discussion thread
with its own resolve state, and a reply _in_ the thread is the only thing a
reviewer reading that thread sees. It does **not** resolve the thread:
resolving is a separate act — the "Resolve conversation" button, or the
`resolveReviewThread` GraphQL mutation — and it is the reviewer's to make. The
reply is what makes resolving it defensible.

```sh
# Fetch the round's comments by REVIEW id — the unpaginated /reviews listing
# hides later rounds behind your own replies.
# --paginate: this endpoint returns 30 per page, and a round you only half
# fetch is a round you only half answer.
gh api --paginate repos/modelcontextprotocol/inspector/pulls/<N>/reviews/<REVIEW_ID>/comments \
--jq '.[]|"\(.id) \(.path):\(.line)\n\(.body)"'

# Reply into one thread, keyed by the comment id from above.
gh api repos/modelcontextprotocol/inspector/pulls/<N>/comments/<COMMENT_ID>/replies \
-f body='Fixed in <sha> — …'
```

- ⚠️ **Then mirror the round at PR level, in addition — never instead.** Inline
replies go hidden once the fix is pushed, because the threads become outdated,
so a summary comment is what keeps the round readable afterwards. It does
**not** discharge the per-comment replies: a rollup bullet cannot be connected
back to the thread it answers, so the thread stays open with a finding and
silence in it, and by round three matching bullets to comments is
reconstruction rather than reading.
- ⚠️ Always read the **"Suppressed comments"** block in the review body. Those
findings have no comment id, so they have no thread to reply into — the
PR-level mirror is the only place they can be answered, and it is the one case
where answering there is the whole response.
- ⚠️ **Copilot's inline comments lag its review body.** The body's "generated N
comments" count lands first; fetch by recency and reconcile. Repeated
re-review silence means the session ended.
Expand Down
17 changes: 12 additions & 5 deletions .claude/skills/pre-push-gate/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ not.

⚠️ **There is no `npm run ci`.** The gate was renamed to `local:gate` (#2146)
precisely because `npm ci` is a built-in that clean-installs from the lockfile
and does *not* run this script. `npm run ci` now fails with npm's missing-script
and does _not_ run this script. `npm run ci` now fails with npm's missing-script
error.

## Verify by exit code, not by grepping output
Expand All @@ -50,7 +50,14 @@ npm run local:gate; echo "EXIT=$?"
```

⚠️ If you run it as a background task, the harness's "exit code 0" notification
describes the *wrapper*, not the gate — read the `EXIT=` line.
describes the _wrapper_, not the gate — read the `EXIT=` line.

**Background it and then wait for that notification** — do not spend turns
watching it. The gate takes several minutes, and re-running `tail` or an
`echo ok` once per turn until it lands tells you nothing the completion
notification would not have; see [Waiting on long-running
work](../../../AGENTS.md#waiting-on-long-running-work). Waiting out one run this
way cost ~80 consecutive no-op turns on #2250.

## Diagnosing a failing stage

Expand Down Expand Up @@ -105,7 +112,7 @@ a whitelist, so a module placed outside it falls out of the gate silently.
### `smoke:web*`

⚠️ **An orphaned prod web server from a previous run fakes a rejection.** It
answers the readiness probe with *its* token, and the deep link comes back
answers the readiness probe with _its_ token, and the deep link comes back
`data-deeplink="rejected"` with no error. Assert the port is free before
blaming the change.

Expand All @@ -118,7 +125,7 @@ Vite's `fs.allow`. Do a real `npm install` in the worktree.

⚠️ Two concurrent `npm run local:gate` runs starve each other — ~326 tests time
out at 5s. Run one at a time. (A `pgrep -f "npm run local:gate"` wait loop
matches *itself* and never exits.)
matches _itself_ and never exits.)

## Local-only steps

Expand All @@ -128,7 +135,7 @@ Two stages have no GitHub CI counterpart, each 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.
- **`smoke:tui`** — needs a real TTY. It *is* invoked in CI via `npm run smoke`
- **`smoke:tui`** — needs a real TTY. It _is_ invoked in CI via `npm run smoke`
and self-skips there on `process.env.CI`, so it needs no guarding.

A guard (`scripts/lib/workflow-gate.mjs`, run by `npm run test:scripts`) fails
Expand Down
Loading