chore: back-merge main into v2/main so the first milestone merge is clean - #1868
Closed
cliffhall wants to merge 224 commits into
Closed
chore: back-merge main into v2/main so the first milestone merge is clean#1868cliffhall wants to merge 224 commits into
cliffhall wants to merge 224 commits into
Conversation
When failing to connect to an MCP server, its very hard to understand why. There is only an opaque "Connection Error" message with no additional info. This also doesn't change at all on repeated attempts, so there is no indication we attempted again and failed. This change introduces a `toast` to visualize the error, and adds the `cause` into the error message for further debugging
Guard against calling controller.close() when the stream has already been closed by an external cancellation. This can happen when the SDK cancels the stream before the underlying Node stream emits its 'end' event. - Add `closed` flag to track controller state - Guard all controller operations with closed check - Add `cancel()` callback to handle external cancellation - Properly destroy the Node stream on cancellation
zod4 compatibility fixed for CI
1. createWebReadableStream: Add closed flag and cancel() callback to prevent double-close crashes when SSE streams end. This fixes the "Controller is already closed" error that occurs when the SDK calls response.body.cancel() on 202 responses. 2. DELETE handler: Call serverTransport.close() after terminateSession() to properly cleanup the transport and cancel pending reconnections. - terminateSession() notifies the server (sends DELETE request) - close() cleans up client-side resources (abort controller, timeouts) - Both are needed for a complete disconnect
…eam-double-close Fix ReadableStream controller double-close crash
…-debug fix: proper stream cleanup and transport close on disconnect
mcp: add icon + website for testing SEP-973
In DynamicJsonForm.tsx,
- Support all five enum shapes used by MCP SDK:
- Titled single-select via `oneOf`/`anyOf` with `{ const, title }`
- Untitled single-select via `enum`
- Titled legacy single-select with optional `enumNames` for labels
- Titled multi-select via `items.anyOf`/`oneOf`
- Untitled multi-select via `items.enum`
- Show field descriptions for string select fields and boolean checkboxes (consistent help text above inputs).
- Prefer schema property `title` for object field labels; fall back to the JSON key when missing.
- Allow top‑level form rendering for objects with properties, arrays with items, and primitive types (was overly strict before).
- Multi-select UI: sensible list size and `minItems`/`maxItems` helper text when present.
- JSON editor fallback, copy/format controls, and debounced parsing preserved.
- apply defaults for optional fields during form init
In schemaUtils.ts
- `generateDefaultValue` now includes optional properties that declare a `default`, ensuring fields like strings show their defaults on first render.
In jsonUtils.ts
- Add legacy `enumNames?: string[]` and array constraints `minItems?`/`maxItems?`.
- Align tests with new form-first rendering and UI behavior:
- Labels prefer schema `title` over property key.
- Descriptions shown for boolean checkboxes and select fields.
- Explicit mode switching between Form/JSON when needed.
- Add comprehensive coverage for enum schema variants:
- Titled single-select via `oneOf`/`anyOf` with `{ const, title }`.
- Untitled single-select via `enum` (with legacy `enumNames` labels).
- Untitled multi-select via `items.enum` with `minItems`/`maxItems` helper text.
- Titled multi-select via `items.anyOf`/`oneOf` with `{ const, title }`.
- Adjust complex/JSON-mode tests to click “Switch to JSON” before asserting textarea and clipboard interactions.
- Fix debounced JSON update expectations to assert parsed objects rather than raw text.
Files updated:
- `client/src/components/__tests__/DynamicJsonForm.test.tsx`
- `client/src/components/__tests__/DynamicJsonForm.array.test.tsx`
Bump version to 0.17.5
Bumps shell-quote from ^1.8.3 to ^1.8.4 in the root and server packages to resolve a critical security advisory. Adds an npm override so concurrency's pinned shell-quote@1.8.3 also resolves to a patched version, leaving no vulnerable copy in the tree. Claude-Session: https://claude.ai/code/session_01HiccCEh9mwCfVzE8qYcop1 Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Resolves Dependabot alert #130. Part of #1706. Claude-Session: https://claude.ai/code/session_01HiccCEh9mwCfVzE8qYcop1 Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Resolves Dependabot alert #132. Uses a version-targeted override (@babel/core@<=7.29.0) so all copies of the vulnerable range are bumped. Part of #1706. Claude-Session: https://claude.ai/code/session_01HiccCEh9mwCfVzE8qYcop1 Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
npm does not reliably apply these transitive overrides to an existing lockfile (bare and targeted overrides via install/update leave residual vulnerable copies). This regenerates the lockfile from scratch with version-targeted overrides so every copy of the affected packages resolves to a patched version. Resolves Dependabot alerts: - esbuild #121 (-> 0.28.1) - minimatch #69, #66, #61 (3.x -> 3.1.5) - @babel/core #132 (-> 7.29.7; completes the partial fix from #1712) Also pins js-yaml overrides (3.15.0 / 4.2.0) to prevent regression. Supersedes #1713, #1714, #1715. Part of #1706. Verified: 0 vulnerable copies across all advisories; build + client (535) + cli tests pass; lockfile internally consistent. Claude-Session: https://claude.ai/code/session_01HiccCEh9mwCfVzE8qYcop1 Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ta (#53) (#1717) * fix(server): guard the /fetch proxy against SSRF to link-local/metadata The /fetch proxy forwarded any user-supplied http/https URL straight into fetch(), so a malicious remote MCP server could advertise OAuth metadata pointing at the cloud metadata endpoint (169.254.169.254) and have the proxy exfiltrate instance credentials (CodeQL js/request-forgery, alert #53). Add a targeted SSRF guard: resolve the target host and reject link-local / cloud-metadata addresses (169.254.0.0/16, IPv6 link-local, AWS IPv6 IMDS). Loopback and RFC1918/private LAN targets stay reachable, since connecting to local and self-hosted MCP servers is a core Inspector use case. Redirects are now followed manually so every hop is re-validated, closing the redirect-to-internal bypass. Returns 403 on a blocked target. Adds endpoint tests for a direct metadata target, a redirect into a blocked address, and normal redirects between allowed hosts. Resolves code-scanning alert #53. Part of #1706. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HiccCEh9mwCfVzE8qYcop1 * fix(server): block IPv4-mapped IPv6 form of metadata IP in /fetch guard The IPv4-mapped IPv6 branch of isBlockedProxyAddress only matched the dotted-decimal form (::ffff:169.254.169.254), but the WHATWG URL parser serializes IPv4-mapped addresses in hex (::ffff:a9fe:a9fe), so http://[::ffff:169.254.169.254]/ resolved past the guard and still reached the cloud metadata service on dual-stack hosts — the exact vector this guard targets. Extract the embedded IPv4 from both the hex and dotted forms and re-check it. Adds a regression test for the IPv4-mapped IPv6 metadata address. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HiccCEh9mwCfVzE8qYcop1 --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Phase 4 of the v2 go-live runbook (#1804 §5). `main` becomes the v2 tree while keeping its own history: this is a true merge recording `v2/main` as a second parent, not a reset, so no force-push is needed and the default branch's history and PR trail survive intact. Mechanically: `-s ours` to take no tree from the merge, then the index is replaced wholesale with `v2/main`'s. `git diff HEAD origin/v2/main` is empty afterwards. Note the runbook's command needed one addition — `main` and `v2/main` have genuinely unrelated histories (different root commits, no merge base), so `--allow-unrelated-histories` is required or the merge refuses outright. All 125 open PRs previously targeting `main` were re-pointed at `v1/main` first, so none of them are stranded against a tree that no longer exists. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Txmv2qqv3yeKgRzoqXytzD
chore: replace main's tree with v2
CodeQL alert #64 (`actions/missing-workflow-permissions`, medium) on `.github/workflows/main.yml`: no `permissions` block, so every job inherits the repository's default GITHUB_TOKEN scope, which is broader than anything here needs. It matters more than the severity suggests because this is the workflow that publishes to npm under OIDC — an over-permissioned token in a job that mints publish credentials is worth tightening before 2.0.0 ships (#1818). Adds a workflow-level `permissions: contents: read`. The `publish` and `publish-github-container-registry` jobs already declare their own blocks (`id-token: write` and friends) and are unaffected: job-level permissions override the workflow-level default outright rather than merging with it. The comment records that, since it means each publish job must keep listing every scope it needs — including `contents: read` — and a future edit that trims one "because it's inherited" would break the publish. Surfaced by the v2 tree swap (#1817): `main` had never scanned this workflow before. Pre-existing on `v2/main`, not introduced by that merge. Claude-Session: https://claude.ai/code/session_01Txmv2qqv3yeKgRzoqXytzD Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* ci: set a least-privilege default GITHUB_TOKEN scope CodeQL alert #64 (`actions/missing-workflow-permissions`, medium) on `.github/workflows/main.yml`: no `permissions` block, so every job inherits the repository's default GITHUB_TOKEN scope, which is broader than anything here needs. It matters more than the severity suggests because this is the workflow that publishes to npm under OIDC — an over-permissioned token in a job that mints publish credentials is worth tightening before 2.0.0 ships (#1818). Adds a workflow-level `permissions: contents: read`. The `publish` and `publish-github-container-registry` jobs already declare their own blocks (`id-token: write` and friends) and are unaffected: job-level permissions override the workflow-level default outright rather than merging with it. The comment records that, since it means each publish job must keep listing every scope it needs — including `contents: read` — and a future edit that trims one "because it's inherited" would break the publish. Surfaced by the v2 tree swap (#1817): `main` had never scanned this workflow before. Pre-existing on `v2/main`, not introduced by that merge. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Txmv2qqv3yeKgRzoqXytzD * chore(deps): upgrade @hono/node-server to 2.0.12 Clears GHSA-frvp-7c67-39w9 (2 Dependabot alerts): path traversal in `serve-static` on Windows via an encoded backslash, affecting < 2.0.5. The Inspector's prod web server calls the flagged function directly (`clients/web/server/server.ts` mounts `serveStatic` at `/*`). Worth being precise about the actual exposure, since the summary line reads worse than the flaw is: `..` escapes remain blocked, so it only reaches files *inside* the configured root, by slipping past prefix-mounted middleware. Here `root` is the built SPA — everything in it is public by design — and the only prefix middleware (`/api/*`) is a separate route, not a subdirectory of that root. So there was no auth bypass and no arbitrary file read to fix; this is hygiene, not an incident. The 1.x → 2.x majors turn out to be a non-event for this codebase: v2 drops Node 18 (the repo already requires >=22.19.0) and removes the Vercel adapter (unused). `serve`, `serveStatic`, and `ServerType` — the entire import surface here, across the prod server and ~15 integration tests — are unchanged. `npm run validate` passes on all four clients. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Txmv2qqv3yeKgRzoqXytzD --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
… latest (#1834) `npm publish` defaults to `--tag latest` regardless of semver prerelease status, and the publish step passed no `--tag`. So cutting the `2.0.0-rc.1` release that #1818 calls for would have published the release candidate to `latest` — pointing every `npx @modelcontextprotocol/inspector` at an RC. That is the same class of failure #1816 fixed for v1, except triggered deliberately by following the runbook. Derives the tag from the version: a hyphen after the patch component means a prerelease (`2.0.0-rc.1` → `next`), anything else is a release (`2.0.0` → `latest`). Build metadata (`2.0.0+build.5`) is correctly not a prerelease. Implemented as a shell `case` rather than with `semver`, which is only a transitive dependency here and should not be relied on in CI. Also makes the RC step of #1818 possible at all — there was previously no way to pass a dist-tag through a release-triggered publish. Claude-Session: https://claude.ai/code/session_01Txmv2qqv3yeKgRzoqXytzD Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Release candidate for the 2.0.0 go-live (#1818, §6). Publishes under the `next` dist-tag via the derivation added in #1834 — verified: `2.0.0-rc.1` contains a hyphen after the patch component, so it resolves to `next`, leaving `latest` on 1.0.1 untouched. The RC exists to exercise what only exists against the live registry: the `next`-tag publish path itself (newly written in #1834), provenance/OIDC minting, the `files` allowlist as npm actually packs it, and the postinstall cascade's early-exit under a real dependency install on a clean machine. Claude-Session: https://claude.ai/code/session_01Txmv2qqv3yeKgRzoqXytzD Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…TOKEN (#1836) * fix(ci): publish via OIDC trusted publishing, not a non-existent NPM_TOKEN The 2.0.0-rc.1 publish failed with `npm error code ENEEDAUTH`. Two causes, both in the v2 publish job, which had never actually executed before — every prior release was cut from the v1 workflow. 1. `NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}` pointed at a secret that does not exist (the repo has no secrets at repo or environment level — publishing moved to OIDC trusted publishing). `setup-node` therefore wrote an *empty* `_authToken` into its generated `.npmrc`, and npm failed ENEEDAUTH before OIDC was ever attempted. Removed, with a comment saying why it must not be "restored". 2. The job never upgraded the npm CLI. Trusted publishing requires npm >= 11.5.1 and Node 22 bundles 10.x, so this would have failed even with the token line gone. The v1 workflow has this step; v2 was missing it. The RC did its job: it caught both against the real registry, and consumed nothing — the run failed before `npm publish` wrote anything, so no version was burned and the dist-tags are untouched. Also confirms #1834 works: the log shows `Publishing 2.0.0-rc.1 under dist-tag 'next'` before the auth failure. README corrected — it documented `NPM_TOKEN` as part of the publish setup. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Txmv2qqv3yeKgRzoqXytzD * docs: restructure the test-servers section into navigable subsections The section had grown into eight undifferentiated paragraphs, the longest 1,965 characters, each describing one or two showcase configs. The content is good reference material — the problem was purely that you could not find anything in it or tell where one config's description ended and the next began. Restructured, not rewritten. No facts removed: - A summary table of all nine showcase configs, with what each demonstrates and its tracking issue, so the set is visible at a glance. - One `####` subsection per config family, so each is linkable and skimmable. - Enumerations that were buried in prose are now tables: the six MRTR presets, the four `trigger_*` spec-error tools and their status/code pairs. - Step sequences (advertised extensions) and era contrasts (logging, subscriptions, tasks) are now bullets rather than run-on sentences. - Two caveats that were parenthetical asides — browser `Mcp-Param-*` skipping, and `collect_elicitation` erroring on the modern leg — are now blockquotes, since both are things you hit and then have to go hunting for. Longest line drops 1,965 → 620 characters. Verified every previously-documented config and all technical identifiers survive. Noted while auditing: `demo.json`, `oauth-step-up-demo.json`, `url-elicitation-form.json` and `xaa-ema-http.json` exist in `test-servers/configs/` but have never been documented here. Left alone — that is a pre-existing gap, not a regression from this change. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Txmv2qqv3yeKgRzoqXytzD --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sweeps every Dependabot alert that reaches users, then bumps to rc.2 so the swept tree gets the same live-registry validation rc.1 got. Deliberate: rc.1 validated a specific dependency tree, and changing it invalidates that proof. Result: **zero prod-scope high/critical vulnerabilities** across all five manifests (root + four clients). Achieved with lockfile changes ONLY — no package.json touched, no declared range widened, no major upgrade. Every one of these was a stale lockfile pin sitting inside an existing caret range: hono → 4.12.32 (needed 4.12.27) fast-uri → 3.1.4 (needed 3.1.3) postcss → 8.5.23 (needed 8.5.18) brace-expansion → 1.1.16 (needed 1.1.16) js-yaml → 4.3.0 (needed 4.3.0) ws → 8.21.0/1 (needed 8.21.0) flatted → 3.4.3 (needed 3.4.2) Two dev-scope clusters remain, both deliberately untouched — neither ships (the `files` allowlist is `clients/*/build`, `clients/web/dist`, and `scripts/install-clients.mjs`), and both need real work that does not belong immediately before a release: - eslint (5 alerts × 5 lockfiles): a `brace-expansion` DoS via `minimatch`, fixable only by eslint@10 — a major bump across every package, likely requiring rule migration. The glob patterns involved come from the repo's own config, never attacker-controlled. - vitest (3 critical, clients/web): a circular exact-pin knot — `@vitest/browser-playwright@4.1.0` requires `@vitest/browser@"4.1.0"` exactly, `vitest@4.1.0` requires `@vitest/browser-playwright@"4.1.0"` exactly, and `@storybook/addon-vitest` constrains the set further. `npm i` fails ERESOLVE; untangling means moving Storybook too. `npm run ci` passes on the swept tree — full chain including the coverage gate, build gate, smokes, and 462 Storybook tests. Claude-Session: https://claude.ai/code/session_01Txmv2qqv3yeKgRzoqXytzD Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…visories; 2.0.0-rc.3 (#1841) The #1837 sweep moved vite to 8.0.16 in the root and tui manifests but left `clients/web` pinned at **8.0.0** — `npm update` reported "up to date" and only an explicit install would move it. That left five open advisories, three high: GHSA-fx2h-pf6j-xcff high `server.fs.deny` bypass via Windows ADS GHSA-v2wj-q39q-566r high `server.fs.deny` bypassed with queries GHSA-p9ff-h696-f583 high arbitrary file read via the dev server GHSA-v6wh-96g9-6wx3 medium launch-editor NTLMv2 hash disclosure GHSA-4w7w-66w2-5vf9 medium path traversal in optimized deps These are worth fixing rather than dismissing as "dev-only". Unlike the other remaining dev-scope alerts, `server.fs.deny` bypass is *remotely triggerable*: a malicious page can read arbitrary files from anyone running `npm run dev`. Published-package users are unaffected — they get the built `dist` and never run vite — but contributors are. Also raises the declared floor to `^8.1.5` in all three manifests that declare vite. The root previously declared `^8.0.0`, which still *permitted* the vulnerable 8.0.0 on a fresh resolve, so pinning the lockfile alone would have left a regression path open. Bumped to rc.3 rather than folding this into 2.0.0: vite builds the shipped bundle, so changing it changes the artifact, and the tree that ships should be the tree that was validated against the live registry. rc.2 validated a different tree. `npm run ci` passes — full chain including the coverage gate, build gate, smokes, and 462 Storybook tests. Claude-Session: https://claude.ai/code/session_01Txmv2qqv3yeKgRzoqXytzD Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
The v2 go-live release (#1818, phase 5 of #1804). This is byte-identical to 2.0.0-rc.3 apart from dropping the prerelease suffix, which is what makes rc.3's validation meaningful: the tree that ships is the tree that was validated against the live registry. `2.0.0` has no hyphen, so the derivation added in #1834 resolves it to `latest` — this is the release that takes the tag from 1.0.1. Validated across three release candidates: - rc.1 caught two publish-path defects invisible to every local check — `NODE_AUTH_TOKEN` pointing at a non-existent secret (shadowing OIDC trusted publishing) and a missing npm CLI upgrade (trusted publishing needs >= 11.5.1; Node 22 bundles 10.x). Both fixed in #1836. - rc.2 validated the dependency sweep (#1837) that cleared every prod-scope advisory using lockfile-only changes. - rc.3 validated the vite 8.1.5 bump (#1841) closing three high-severity dev-server file-read advisories. Each RC was verified with a cold `node:22` container install driving the published tarball end to end — install, `--help`, and a real `--cli tools/list` against a live stdio server. `latest` remained on 1.0.1 throughout, proving the `--tag` derivation. Zero open Dependabot alerts at time of release. Claude-Session: https://claude.ai/code/session_01Txmv2qqv3yeKgRzoqXytzD Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
`SECURITY.md` existed on the pre-swap `main` (ac3c1a1) and still exists on `v1/main`, but the v2 tree never had one — so #1817 silently removed the security policy from the default branch. That is the wrong file to be missing right now: it is where private vulnerability reporting is advertised, and it disappeared in the same window as 2.0.0 shipping and external pull requests being turned off (#1820). Losing the PR path and the security-report path together would leave an outside reporter with no documented route at all. Restored from `v1/main` with the additions #1820 asks for: - A supported-versions table covering all four package names — v2 supported, the v1 line security-fixes-only under the `v1-latest` dist-tag, anything below 1.0.0 unsupported. The three sub-packages are named explicitly since they exist only on v1 and are deprecated. - A note that the repository does not accept outside pull requests, but that this explicitly does NOT apply to security reports, which must go through the advisory process rather than any public channel. Without that, the new issues-only policy reads as "no way to reach us". - "Whether it affects v2, v1, or both" added to the report checklist, now that two lines are live. Verified private vulnerability reporting is enabled on the repo, so the advisory link is a working route rather than an aspiration. Claude-Session: https://claude.ai/code/session_01Txmv2qqv3yeKgRzoqXytzD Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ture) Prepares the milestone-merge workflow (#1821, task 1). `v2/main` and `main` already share history — the merge base is 4d30d1c, established by the go-live merge (#1830) — but the two had diverged on README.md, so the first v2/main -> main milestone merge would have conflicted. Recording main as merged here means that merge is now a clean fast-forward: main's tip becomes an ancestor of v2/main, so the release side contributes no changes to reconcile. Brings from main: the README restructure (#1836), SECURITY.md (#1843), the 2.0.0 release/version commits, the workflow dist-tag change (#1834), and the dependency bumps that shipped with the rc series. README.md conflict resolution: took main's restructured "Test servers" section (headings + config table + per-config subsections) and carried v2/main's #1846 correction into it. main's copy still claimed `Mcp-Param-*` mirroring is skipped in the browser so a web `get_weather` call answers -32020; that stopped being true when the Inspector took over building the mirrored headers itself, so the callout now says mirroring works on every client, web included. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YAt8rqxysNbhYWLhoRm3fU
This was referenced Jul 31, 2026
Closed
cliffhall
added a commit
that referenced
this pull request
Aug 2, 2026
…#1904) main's copy of .github/workflows/main.yml carried three release fixes v2/main never took -- #1831 (least-privilege default GITHUB_TOKEN scope), #1834 (derive the npm dist-tag from the version) and #1836 (publish via npm OIDC trusted publishing). Diffing the file both directions shows v2/main has NOTHING main lacks: its only unique content is the superseded publish step, run: npm publish --access public --provenance env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} which is exactly what #1836 replaced. Every other line already matched. So this is a verbatim copy of main's file rather than a hunk-by-hunk forward-port -- fewer ways to get it wrong, and it leaves the two branches byte-identical (`git diff origin/main -- .github/workflows` is now empty). Not a back-merge: only this one file is taken, so none of main's pre-swap v1 lineage enters v2/main's ancestry (see #1868). Claude-Session: https://claude.ai/code/session_01YAt8rqxysNbhYWLhoRm3fU Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1821
Task 1 of #1821 — "Merges from v2/main into main enabled for milestone development release workflow". Analysis in this comment; this is the mechanical half.
Why
v2/mainandmainalready share history — merge base4d30d1cd, established by the go-live merge (#1830) — so milestone merges work without any graft. But the two had diverged onREADME.md, so the firstv2/main→mainmerge would have conflicted:mainrestructured the whole "Test servers" section in fix(ci): publish via OIDC trusted publishing, not a non-existent NPM_TOKEN #1836 (headings, config table, per-config subsections).v2/maincorrected one paragraph inside that same region in tools/call omits SEP-2243 Mcp-Param-* headers (x-mcp-header mirroring), rejected by strict modern servers #1846.Copying main's text onto
v2/mainwould not have fixed this — both sides would still show overlapping edits to the same region and conflict again. Recording main as merged is what fixes it:main's tip becomes an ancestor ofv2/main, so the release side contributes nothing to reconcile.Verified
What it brings from main
README.mdrestructure (fix(ci): publish via OIDC trusted publishing, not a non-existent NPM_TOKEN #1836)SECURITY.md(docs: restore SECURITY.md, lost in the v2 tree swap #1843) — overlaps docs: restore SECURITY.md on v2/main, so the next tree swap can't drop it #1867, see belowREADME conflict resolution
Took main's restructured section and carried
v2/main's #1846 correction into it. main's copy still claimed:That stopped being true when the Inspector took over building the mirrored headers itself. The callout now says mirroring works on every client, web included, since the web client's upstream request is issued by the Node backend rather than the browser.
This is not a docs-only change
It lands on
v2/mainthe rc-series bumps that had only ever reachedmain:@hono/node-server^1.19.14^2.0.12(major)vite^8.0.0/^8.0.16^8.1.5@modelcontextprotocol/sdkThe lockfiles auto-merged consistently — a subsequent
npm installproduced no changes.npm run cipasses (validate → coverage → verify:build-gate → smoke → Storybook), which is what gives confidence in the major@hono/node-serverbump against the web backend.Sequencing with #1867
#1867 (SECURITY.md on
v2/main) overlaps this PR — the back-merge necessarily brings that file across. Merging #1867 first is cleanest: the file is then identical on both sides and this PR's diff simply no longer contains it. Alternatively #1867 can be closed as subsumed. Either order works; there's no conflict.🤖 Generated with Claude Code
https://claude.ai/code/session_01YAt8rqxysNbhYWLhoRm3fU