Commit graph

2,202 commits

Author SHA1 Message Date
Cliff Hall
c2bc6a6a63
Merge pull request #1603 from modelcontextprotocol/1550-ci-coverage-gate
ci: enforce the ≥90% per-file coverage gate in CI
2026-07-02 12:49:20 -04:00
Cliff Hall
747148fac3
Merge pull request #1597 from modelcontextprotocol/v2/1596-test-stability
test(web): eliminate timeout flakiness in the web test suite
2026-07-02 12:46:53 -04:00
cliffhall
fa274fae06 chore: retarget #1597 onto 1579-wave-1 rollup (empty commit enables base change; tree unchanged) 2026-07-02 12:46:47 -04:00
Cliff Hall
7d4caf8081
Merge pull request #1537 from modelcontextprotocol/chore/1517-contributors-md
docs: add CONTRIBUTORS.md issues-only policy (#1517)
2026-07-02 12:46:31 -04:00
cliffhall
9f0e4d88e2 chore: retarget #1537 onto 1579-wave-1 rollup (empty commit enables base change; tree unchanged) 2026-07-02 12:46:25 -04:00
Cliff Hall
7e1496a338
Merge pull request #1592 from modelcontextprotocol/v2/1548-web-remote-oauth-storage
Web: migrate auth store to shared /store API (RemoteOAuthStorage parity with TUI/CLI)
2026-07-02 12:46:16 -04:00
cliffhall
ca00935d1e chore: retarget #1592 onto 1579-wave-1 rollup (empty commit enables base change; tree unchanged) 2026-07-02 12:46:11 -04:00
Cliff Hall
8b8e46ffee
Merge pull request #1591 from modelcontextprotocol/v2/1559-hostcontext-utils
feat(web): extract hostContext utilities for the Apps host
2026-07-02 12:45:50 -04:00
cliffhall
1fdf03e2ec chore: retarget #1591 onto 1579-wave-1 rollup (empty commit enables base change; tree unchanged) 2026-07-02 12:45:46 -04:00
Cliff Hall
42fb853038
Merge pull request #1590 from modelcontextprotocol/v2/1563-node-proxy
feat(core): honor HTTPS_PROXY/HTTP_PROXY/NO_PROXY in the Node transport
2026-07-02 12:45:30 -04:00
cliffhall
30dc370ddf chore: retarget #1590 onto 1579-wave-1 rollup (empty commit enables base change; tree unchanged) 2026-07-02 12:45:23 -04:00
Cliff Hall
d307639354
Merge pull request #1589 from modelcontextprotocol/v2/1562-oauth-state-hardening
auth hardening: generateOAuthState requires WebCrypto; OAuth callback rejects unparseable state
2026-07-02 12:45:04 -04:00
cliffhall
56ca566296 chore: retarget #1589 onto 1579-wave-1 rollup (empty commit enables base change; tree unchanged) 2026-07-02 12:44:58 -04:00
Cliff Hall
3de93b9beb
Merge pull request #1588 from modelcontextprotocol/v2/1558-sandbox-csp
feat(web): add sandbox CSP builder library (closes #1558)
2026-07-02 12:44:43 -04:00
cliffhall
060b64af1d chore: retarget #1588 onto 1579-wave-1 rollup (empty commit enables base change; tree unchanged) 2026-07-02 12:44:37 -04:00
Cliff Hall
b96fd6eb0d
Merge pull request #1587 from modelcontextprotocol/v2/1557-mcp-app-demo
feat(test-servers): mcp_app_demo preset + _meta on tool/resource defs
2026-07-02 12:44:17 -04:00
cliffhall
3b4c958426 chore: retarget #1587 onto 1579-wave-1 rollup (empty commit enables base change; tree unchanged) 2026-07-02 12:44:12 -04:00
Cliff Hall
53cca10323
Merge pull request #1586 from modelcontextprotocol/v2/1560-downloadfile
feat(web): downloadFile.ts enhancements (downloadBlob, fileNameFromUri, isHttpUrl)
2026-07-02 12:43:52 -04:00
cliffhall
949bc3b514 chore: retarget #1586 onto 1579-wave-1 rollup (empty commit enables base change; tree unchanged) 2026-07-02 12:43:48 -04:00
Cliff Hall
98dff8b0d3
Merge pull request #1585 from modelcontextprotocol/v2/1561-redact-headers
feat(core): redact sensitive headers in the fetch log
2026-07-02 12:43:29 -04:00
cliffhall
ff9269c417 chore: retarget #1585 onto 1579-wave-1 rollup (empty commit enables base change; tree unchanged) 2026-07-02 12:43:24 -04:00
Cliff Hall
72ae119d09
Merge pull request #1584 from modelcontextprotocol/v2/1556-core-appinfo
feat(core): add AppInfo + extractAppInfo() to core/mcp/apps.ts
2026-07-02 12:43:04 -04:00
cliffhall
985ef32de0 chore: retarget #1584 onto 1579-wave-1 rollup (empty commit enables base change; tree unchanged) 2026-07-02 12:42:59 -04:00
Cliff Hall
0fe9c4e4d9
Merge pull request #1583 from modelcontextprotocol/v2/1564-cli-exit-codes
feat(cli): exit-code map + structured JSON error envelopes
2026-07-02 12:42:49 -04:00
cliffhall
436257b17f chore: retarget #1583 onto 1579-wave-1 rollup (empty commit enables base change; tree unchanged) 2026-07-02 12:42:26 -04:00
cliffhall
61ca22003f ci: enforce the ≥90% per-file coverage gate in CI (closes #1550)
Add a CI step that runs `npm run coverage` so a PR that drops any file
below 90% on lines/statements/functions/branches fails the job. Remove
the now-redundant standalone `Run web integration tests` step, since
web's `test:coverage` already runs `--project=unit --project=integration
--coverage`, and update AGENTS.md to reflect that CI now enforces the gate.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S3fTN8H3R8YV4yUGvZjYnX
2026-07-02 11:59:32 -04:00
cliffhall
e19d11070a merge: #1599 gate src/lib coverage (#1594) 2026-07-01 22:48:03 -04:00
cliffhall
4b180d919a merge: #1598 redact bodies+URL query (#1593) 2026-07-01 22:48:00 -04:00
cliffhall
775b98a019 docs(core): clarify redaction scope + add nested request-body test
Address round-1 review feedback on fetchTracking redaction:
- Cross-reference REDACTED_VALUE / REDACTED_HEADER_VALUE so a reader
  understands why two identical "[REDACTED]" constants coexist.
- Document that redactBody deliberately scopes to form-encoded + JSON
  (multipart/binary bodies pass through; OAuth never uses multipart).
- Add a tracker-path test asserting a nested sensitive key in a JSON
  request body is redacted in the recorded copy while the live outbound
  body stays byte-identical.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S3fTN8H3R8YV4yUGvZjYnX
2026-07-01 22:34:40 -04:00
cliffhall
1fd1313c96 test(web): gate src/lib/** under the coverage include globs (closes #1594)
Broaden the web vitest `coverage.include` from the single-file
`src/lib/sandbox-csp.{ts,tsx}` entry to `src/lib/**/*.{ts,tsx}` so the
per-file >=90 four-dimension gate applies to every library module under
`src/lib`, not just sandbox-csp.

- Add unit tests for the previously-ungated `environmentFactory.ts`
  (createWebEnvironment) and `types/customHeaders.ts` value helpers,
  bringing both to 100% on all four dimensions.
- Annotate downloadFile.ts's provably-dead `?? ""` fallback (String.split
  always returns a non-empty array so .pop() is never undefined) with a
  justified `v8 ignore`, closing its last uncovered branch (92.3 -> 100).

All five src/lib files now report 100/100/100/100.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S3fTN8H3R8YV4yUGvZjYnX
2026-07-01 22:23:43 -04:00
cliffhall
524bf2d543 feat(core): redact sensitive body + URL-query fields in fetch log (closes #1593)
Extends the header redaction from #1585. Before a fetch entry reaches any
sink, mask known-sensitive credentials in the request/response bodies and
the URL query string, in addition to headers:

- redactBody(): form-urlencoded + JSON bodies, recursive over nested
  objects/arrays, best-effort (never throws), values-only.
- redactUrlQuery(): masks sensitive query params, preserves path,
  non-sensitive params, and any fragment.
- Sensitive fields: client_secret, code, refresh_token, access_token,
  id_token, code_verifier, client_assertion, assertion, password, token
  (case-insensitive), reusing the [REDACTED] sentinel.

Applied to the request success + error entries and the async response-body
callback. Live outbound requests are byte-identical — only the logged copy
is redacted.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S3fTN8H3R8YV4yUGvZjYnX
2026-07-01 22:20:42 -04:00
cliffhall
b2ff34a901 merge: chore/1517-contributors-md (#1537) 2026-07-01 22:06:17 -04:00
cliffhall
c6b5af3b81 merge: v2/1596-test-stability (#1597) 2026-07-01 22:05:57 -04:00
cliffhall
e425602295 merge: v2/1548-web-remote-oauth-storage (#1592)
# Conflicts:
#	clients/web/src/test/core/auth/utils.test.ts
2026-07-01 22:05:52 -04:00
cliffhall
cc37a755ae merge: v2/1562-oauth-state-hardening (#1589) 2026-07-01 22:04:22 -04:00
cliffhall
52cd90bd50 merge: v2/1560-downloadfile (#1586) 2026-07-01 22:04:18 -04:00
cliffhall
3f22299b14 merge: v2/1559-hostcontext-utils (#1591) 2026-07-01 22:04:18 -04:00
cliffhall
e55867cd45 merge: v2/1558-sandbox-csp (#1588) 2026-07-01 22:04:12 -04:00
cliffhall
9257c849b9 merge: v2/1557-mcp-app-demo (#1587) 2026-07-01 22:04:07 -04:00
cliffhall
4c5036e032 merge: v2/1564-cli-exit-codes (#1583) 2026-07-01 22:04:01 -04:00
cliffhall
4e3cd591a4 merge: v2/1563-node-proxy (#1590) 2026-07-01 22:03:55 -04:00
cliffhall
2d1a99ab37 merge: v2/1561-redact-headers (#1585) 2026-07-01 22:03:51 -04:00
cliffhall
8bc32c85d7 merge: v2/1556-core-appinfo (#1584) 2026-07-01 22:03:46 -04:00
cliffhall
dd7812063c test(web): make the debounce-cancellation test load-bearing (review round 1)
The "cancels a pending debounce timer when the input is re-focused" test
passed trivially after the delay:null change: synchronous typing meant the
assertion ran at t≈0, before the 300ms debounce could ever fire, so it
passed whether or not handleFocus's clearTimeout worked.

Rewrote it with fake timers so the debounce window elapses deterministically
(advance the clock by 400ms directly). The interaction is driven with
fireEvent rather than userEvent because userEvent's async internals deadlock
under vitest fake timers with the Mantine/happy-dom stack. Verified
load-bearing: removing the clearTimeout in handleFocus makes it fail
(expected 1 to be 0), and it passes once restored.

Also tightened the sibling-context comment (with delay:null the sibling is
reliably "es"); the tolerant /^es?$/ regex is left as-is.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S3fTN8H3R8YV4yUGvZjYnX
2026-07-01 21:22:04 -04:00
cliffhall
4bad110942 test(web): eliminate timeout flakiness in the web test suite (closes #1596)
Root-cause and deterministically fix the recurring 5s-timeout flakes that
surfaced under v8-instrumented, concurrent load. All fixes are test-only; no
product source changed. No test was skipped or disabled, and the per-file
coverage gate (>=90 on all four dims) still holds.

Common root cause across the modal/form/screen suites: userEvent.setup()
schedules a real setTimeout between keystrokes. Under CPU contention those
yields balloon, so multi-field interactions blew past the 5s per-test
timeout. Fix: userEvent.setup({ delay: null }) removes the per-keystroke
real-timer dependence (typing dispatches synchronously), making the suites
load-independent.

Per file:
- ServerConfigModal / ServerImportConfigModal / ServerImportJsonModal /
  ResourcesScreen / InspectorView: userEvent.setup({ delay: null }).
- PromptArgumentsForm (completions): replaced wall-clock sleeps sized just
  past the 300ms completion debounce (await setTimeout(400)) — which race
  the debounce timer under load — with awaited conditions (findBy/waitFor)
  on the real rendered outcome, plus delay:null. Negative assertions now
  lean on the component's synchronous state/timer teardown instead of a
  timed window, so they are deterministic regardless of machine speed.
- inspectorClient integration "tracks stderr logs": the child's stderr is
  piped out-of-band from the tool's JSON-RPC response, so reading the log
  synchronously after callTool raced the stderr chunk. Wrapped the assertion
  in vi.waitFor so it polls until the line lands.

Verified: web validate + 6x test:coverage (4 sequential + 2 concurrent
under load) + standalone test:integration, all green (229 files / 3237
tests per coverage run; 799 integration tests), zero intermittent failures.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S3fTN8H3R8YV4yUGvZjYnX
2026-07-01 21:11:11 -04:00
cliffhall
3df4f0e7e2 Merge remote-tracking branch 'origin/v2/main' into merge-1537 2026-07-01 20:57:34 -04:00
cliffhall
79ca8f05a7 docs: add version-board/label table to CONTRIBUTORS.md (closes #1595)
Completes requirement #2 of #1517: a table mapping each active version to
its base branch, project board, and version label, plus a "Label by
version" note mirroring AGENTS.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S3fTN8H3R8YV4yUGvZjYnX
2026-07-01 20:25:28 -04:00
cliffhall
588fc3f8ea docs(auth): note getClientRegistrationKind's hydration invariant like getScope
Round-3 @claude review of #1592 (optional nit): getClientRegistrationKind is
the other synchronous getter that, like getScope, is safe only because its
sole caller (buildOAuthConnectionState) awaits getClientInformation/
getServerMetadata first, flushing hydration before this runs on the
post-redirect callback path. Add a docstring mirroring getScope's so a future
refactor doesn't read it without a preceding awaited storage read.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S3fTN8H3R8YV4yUGvZjYnX
2026-07-01 19:31:10 -04:00
cliffhall
4e149719bd fix(auth): route clearClientInformation through clearAfterHydration too
Round-2 @claude review of #1592 caught a seventh member of the clear
family that the first pass missed: clearClientInformation still wrote to
the store synchronously, carrying the same pre-hydration clobber risk the
clearAfterHydration helper was written for (a clear before hydration lands
persists a near-empty blob, overwriting the whole on-disk oauth.json).
Wrap its mutation the same way and add a clear-before-hydration test
proving a sibling token (and thus every other server's blob) survives.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S3fTN8H3R8YV4yUGvZjYnX
2026-07-01 19:26:25 -04:00
cliffhall
8059a3d120 docs(test-servers): note custom resource handlers must re-add _meta
Address round-3 code-review note on PR #1587: resource `_meta` is applied
only by the default read handler; a customHandler from onRegisterResource
replaces the contents wholesale and would drop it. Document this on
ResourceDefinition._meta so a future App UI resource with a custom read
handler knows to re-add _meta itself.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S3fTN8H3R8YV4yUGvZjYnX
2026-07-01 19:23:57 -04:00