* feat: add URL-mode elicitation support
The MCP spec (2025-11-25) added URL-mode elicitation alongside form mode,
allowing servers to direct users to external URLs for out-of-band
interactions (auth flows, payments, sensitive data). This implements
client-side support for rendering and handling URL-mode elicitation
requests, and announces the capability during initialization.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add consent dialog for URL elicitation and separate Accept button
Replace the clickable URL link with a consent dialog that displays the
URL as plain text when "Open URL" is clicked, letting the user confirm
before navigating. Add a separate "Accept" button that resolves the
elicitation without the content field, per the MCP spec.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: preserve structured McpError data in request history
When a tool call returns an MCP error (e.g. -32042 URLElicitationRequired),
the catch block was only capturing error.message (a string), discarding the
structured error.code and error.data fields.
Now McpError instances push the full JSON-RPC error structure to history:
{ error: { code, message, data } }
This means the Response panel will show the complete error including
data.elicitations for -32042, rather than just a message string.
* Revert "fix: preserve structured McpError data in request history"
This reverts commit 86f6d093f6596d6a9a52b85df24b66fa2e354d07.
* fix: enforce HTTPS-only for URL elicitation per SEP-1036
Address Claude review on #1423:
- Validate the server-supplied URL before opening it; refuse non-https
schemes (http/file/javascript/data) and malformed URLs, disabling the
"Open URL" button and showing an error state instead of calling
window.open (SEP-1036 URL Security Requirements, a spec MUST).
- Display the parsed destination host prominently in the consent dialog
to surface look-alike/embedded-credential URLs.
- Document that elicitation/complete is surfaced via the notification
panel and resolved manually (no auto-correlation), a conscious choice
per the spec's MAY/SHOULD.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: evalstate <1936278+evalstate@users.noreply.github.com>
Resolves 15 of 16 Dependabot alerts via lockfile-only updates (no
breaking major bumps): handlebars (critical), fast-uri, flatted, hono,
path-to-regexp, rollup, vite, express-rate-limit, @hono/node-server,
ajv, brace-expansion, ip-address, picomatch, postcss, qs, ws, yaml,
and @tootallnate/once.
The remaining minimatch@3.1.2 advisory comes from @eslint/config-array
(dev/lint-only, not shipped) and will clear when ESLint bumps it.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Per review feedback on PR #1270: replace the three-way `==` OR chain in
each of the four trigger branches with a single contains(fromJSON(...))
check against a shared list. Same semantics, less duplication, and the
allowed-roles list is now defined once per branch instead of three times.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Previously the workflow's `if:` only checked the event type and the
presence of `@claude` in the body. The job would start for any commenter
and only later fail when the action attempted privileged operations on
behalf of a user without write access. That produced noisy red runs and
wasted runner minutes for what is effectively an authorization rejection.
Add an `author_association` check (OWNER, MEMBER, or COLLABORATOR) to
each of the four trigger branches (issue_comment, pull_request_review_comment,
pull_request_review, issues), so the job is short-circuited at workflow
evaluation time and never starts for unauthorized invokers.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Previous fix only added repository.url to the root package.json, but npm
publish --workspaces publishes each workspace using its own package.json.
The provenance check runs per-package, so each published workspace package
also needs repository.url to match the GitHub repo URL. Also adds type: "git"
to the root and directory fields to the workspaces for correct monorepo
linking on npm/GitHub.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Upgrade npm to ^11.5.1 in the publish job (Node 22 bundles npm 10.x,
which lacks OIDC trusted publishing support)
- Drop NODE_AUTH_TOKEN / NPM_TOKEN secret in favor of OIDC
- Enable provenance attestation via NPM_CONFIG_PROVENANCE
The publish job already had id-token: write and registry-url configured.
* fix(server): sanitize error responses to prevent stack trace exposure
Replace raw error objects passed to res.json() with generic sanitized
messages so internal error details are not leaked to clients. Full
errors continue to be logged server-side via console.error.
Also adds a missing return in the /sse ECONNREFUSED branch, which
previously fell through and attempted a second response after headers
had already been sent.
Resolves CodeQL js/stack-trace-exposure alerts in server/src/index.ts.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(server): address review feedback on error sanitization
- Sanitize /fetch route catch block: previously leaked error.message to
clients and silently swallowed errors with no server-side logging.
Now logs via console.error and returns a generic sanitized response.
- Replace JSON.stringify(error).includes("ECONNREFUSED") in the /sse
handler with a check against error.message and String(error.cause).
Error fields are non-enumerable so JSON.stringify(new Error(...))
produces "{}" — the old check only worked by accident when the error
happened to carry enumerable properties.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Ola Hungerford <olahungerford@gmail.com>
* fix: validate serverInfo.websiteUrl before rendering as link
A connected MCP server's serverInfo.websiteUrl was rendered directly
as an <a href> with no protocol check, allowing a malicious server to
supply javascript: (or other unsafe) URLs that would execute on click.
Run the value through validateRedirectUrl and, on failure, show a
warning-colored "Potentially malicious websiteURL field" message
instead of a link. The offending URL is still surfaced via tooltip
for inspection.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: render websiteUrl warning below server name
Move the "Potentially malicious websiteURL field" message onto its
own row beneath the icon+name row so it doesn't crowd the server
name horizontally in the narrow sidebar.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When the MCP server is at a non-root path (e.g. /mcp), path-aware
discovery (/.well-known/oauth-protected-resource/mcp) may 404 if the
server only serves metadata at the root. The SDK's direct-mode
discovery already falls back to root-level URLs in this case. This
adds the same fallback to the proxy discovery functions.
The `redirect_uris` getter used `this.redirectUrl`, which is overridden
by `DebugInspectorOAuthClientProvider` to return `/oauth/callback/debug`.
This caused the `Set` deduplication to collapse both URIs into one,
so DCR only registered `/oauth/callback/debug`. The normal connection
flow then sent `/oauth/callback` in the authorize request, which was
never registered — causing spec-compliant OAuth servers to reject it.
Use the base callback URLs directly instead of the polymorphic getter
so both URIs are always registered regardless of which subclass
initiates DCR.
Fixes#930
Add server-side proxy endpoints for OAuth discovery, client registration,
and token exchange to avoid CORS issues when using proxy connection mode.
Server proxy endpoints:
- GET /oauth/resource-metadata - proxies OAuth protected resource metadata
- GET /oauth/metadata - proxies OAuth authorization server metadata
- POST /oauth/register - proxies dynamic client registration
- POST /oauth/token - proxies token exchange
Client changes:
- Construct correct RFC 9728/8414 path-aware well-known URLs client-side
- Route all OAuth discovery through proxy when in proxy connection mode
- Eliminate direct browser fetches that fail with CORS in proxy mode