Milestone v2.4.0
The fourth v2/main → main milestone merge, cutting 2.4.0. This is step 2 of the release procedure in Cutting a release; step 1 (the version bump on v2/main) is #2141 / #2142.
main currently holds 2.3.0 (merged via #2053 / #2054) and has not moved since — no dependabot PR landed on it directly this cycle. v2/main has accumulated 31 merged PRs (200 non-merge commits) on top of it.
Scope
- Branch from
main, merge origin/v2/main.
- Open a PR against
main and run npm run ci green on the merged tree.
- After merge: tag
origin/main as bare 2.4.0 and draft the GitHub Release — publishing runs pack:verify, asserts the tag matches package.json, and publishes the latest dist-tag.
The version bump is not part of this issue — it lands on v2/main first (#2142), which is the whole point of the #2010 procedure change, and arrives here as part of the payload.
Conflicts
None expected. A trial merge of main with v2/main + the bump went through clean, with no conflicted paths — unlike the v2.3.0 merge, where #2004 (dependabot, npm_and_yarn group) had landed on main only and collided on the version field. Nothing has landed on main since #2054, so main is unchanged from the state v2/main last merged into it.
Re-run the trial merge before opening the PR anyway: a dependabot PR merged to main in the interim would reintroduce exactly the lockfile conflict the last two merges hit, and the security bumps must survive it.
Payload
| Group |
PRs |
| Release mechanics |
#2142 (bump to 2.4.0 — #2141) |
| MCP Apps |
#2100 (dedicated app origin for _meta.ui.domain — #2056), #2083 (negotiated app-rendered form elicitations — #1854), #2098 (read UI resource metadata from _meta.ui — #2055), #2107 (render an App from the installed tarball in pack:verify — #2003) |
| OAuth / secrets |
#2113 (pass the challenge's resource_metadata URL to SDK auth() — #2071), #2136 (keep the server's path in the fallback authorization-server URL — #2110), #2118 (persist the requested scope when the token response omits it — #2117), #2114 (per-server refresh_token opt-out — #2068), #2105 (don't answer token_expired from an unknowable local expiry — #2051), #2115 (open the monitoring sidebar when a connect fails during OAuth — #2108), #2076 (file-backed and in-memory SecretStore for hosts with no keychain — #1950), #2088 (a real cross-process lock on the secrets file — #2082) |
| Protocol / runtime |
#2135 (carry the in-progress SSE frame across chunk boundaries — #2134), #2099 (route the proxy through undici's own fetch and keep undici external — #2067), #2094 (complex JSON values in request _meta — #1910) |
| Tools / forms / UI |
#2121 (flag unportable tool schemas in all three clients — #1005), #2109 (multiline tool string arguments — #2042), #2139 (take the enlarge button out of the tab order — #2138), #2131 (keep the pagination toggle on the last write across a server switch — #2095), #2091 (roll a failed settings write back to what actually landed — #2089), #2087 (surface a failed post-write server-list reload — #1914), #2106 (state the expected shape when dropping a CSP source — #2064) |
| CLI / config |
#2119 (carry a landed stdio env/cwd onto the config it connects with — #2096), #2112 (apply a server's persisted mcp.json metadata — #2093) |
| Lint / tooling / CI |
#2090 (--max-warnings 0 on every lint scope — #2085), #2116 (pin esbuild past GHSA-g7r4-m6w7-qqqr in web/cli/tui — #2062), #2120 (build test-servers unconditionally from one shared helper — #2111), #2092 (three small cleanups flagged in the v2.2.0 merge review — #2000), #2103 (remove the Claude Code GitHub Actions workflow — #2102), #2070 (drop the redundant PR-head checkout from claude.yml — #2069) |
After merge
- Close this issue manually and move its card to Done —
Closes #N does not fire on a PR targeting main from a merge branch until it actually merges there, and the merge PR uses References by convention.
- Close out the v2.4.0 milestone, moving anything still open on it to v2.5.0.
Milestone v2.4.0
The fourth
v2/main→mainmilestone merge, cutting 2.4.0. This is step 2 of the release procedure in Cutting a release; step 1 (the version bump onv2/main) is #2141 / #2142.maincurrently holds 2.3.0 (merged via #2053 / #2054) and has not moved since — no dependabot PR landed on it directly this cycle.v2/mainhas accumulated 31 merged PRs (200 non-merge commits) on top of it.Scope
main, mergeorigin/v2/main.mainand runnpm run cigreen on the merged tree.origin/mainas bare2.4.0and draft the GitHub Release — publishing runspack:verify, asserts the tag matchespackage.json, and publishes thelatestdist-tag.The version bump is not part of this issue — it lands on
v2/mainfirst (#2142), which is the whole point of the #2010 procedure change, and arrives here as part of the payload.Conflicts
None expected. A trial merge of
mainwithv2/main+ the bump went through clean, with no conflicted paths — unlike the v2.3.0 merge, where #2004 (dependabot,npm_and_yarngroup) had landed onmainonly and collided on the version field. Nothing has landed onmainsince #2054, somainis unchanged from the statev2/mainlast merged into it.Re-run the trial merge before opening the PR anyway: a dependabot PR merged to
mainin the interim would reintroduce exactly the lockfile conflict the last two merges hit, and the security bumps must survive it.Payload
_meta.ui.domain— #2056), #2083 (negotiated app-rendered form elicitations — #1854), #2098 (read UI resource metadata from_meta.ui— #2055), #2107 (render an App from the installed tarball inpack:verify— #2003)resource_metadataURL to SDKauth()— #2071), #2136 (keep the server's path in the fallback authorization-server URL — #2110), #2118 (persist the requested scope when the token response omits it — #2117), #2114 (per-serverrefresh_tokenopt-out — #2068), #2105 (don't answertoken_expiredfrom an unknowable local expiry — #2051), #2115 (open the monitoring sidebar when a connect fails during OAuth — #2108), #2076 (file-backed and in-memorySecretStorefor hosts with no keychain — #1950), #2088 (a real cross-process lock on the secrets file — #2082)_meta— #1910)mcp.jsonmetadata — #2093)--max-warnings 0on every lint scope — #2085), #2116 (pin esbuild past GHSA-g7r4-m6w7-qqqr in web/cli/tui — #2062), #2120 (build test-servers unconditionally from one shared helper — #2111), #2092 (three small cleanups flagged in the v2.2.0 merge review — #2000), #2103 (remove the Claude Code GitHub Actions workflow — #2102), #2070 (drop the redundant PR-head checkout fromclaude.yml— #2069)After merge
Closes #Ndoes not fire on a PR targetingmainfrom a merge branch until it actually merges there, and the merge PR usesReferencesby convention.