From 484f719ceff30e45a6b5edad59921ec2bf805044 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 2 Jul 2026 16:26:19 +0000 Subject: [PATCH 1/2] Add SEP-1036 (URL mode elicitation) requirement-traceability YAML Backfills MUST/SHOULD coverage for the first SEP from the released 2025-11-25 spec version. 14 check: rows (wire-observable server and client requirements for mode negotiation, URL mode request shape, completion notifications, and URLElicitationRequiredError) and 25 excluded: rows (UI, out-of-band web channel, and server-internal requirements), quoted from the released 2025-11-25 elicitation page. Also documents the released-version backfill variant in the new-sep skill: changelog-as-inventory, issue-number SEPs whose spec diff is a separate PR, pinning versioned (not draft) spec URLs, and separating co-located SEPs on the same page. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01RxATEKjQrK8ynnphygzFEp --- .claude/skills/new-sep/SKILL.md | 9 +++ src/seps/sep-1036.yaml | 126 ++++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+) create mode 100644 src/seps/sep-1036.yaml diff --git a/.claude/skills/new-sep/SKILL.md b/.claude/skills/new-sep/SKILL.md index fa19a2e1..c936c96c 100644 --- a/.claude/skills/new-sep/SKILL.md +++ b/.claude/skills/new-sep/SKILL.md @@ -185,6 +185,15 @@ rg -A1 'name:|description:' If you find a plausible host, recommend it by path. If nothing fits, say so explicitly — a new scenario file is then the right call. +## Variant: backfilling a SEP from a released spec version + +The steps above assume a draft-era SEP whose number is its spec PR. For SEPs that shipped in a released version (e.g. `2025-11-25`), four things change: + +- **Inventory** — the authoritative SEP list for a version is its changelog, `docs/specification//changelog.mdx` in the spec repo. Diff it against `ls src/seps/` to find gaps (governance SEPs like 932/994/1302/1730 have no protocol requirements — skip them). +- **SEP number ≠ PR number** — pre-draft-era SEPs are issue numbers; the spec diff landed in a separate PR (e.g. SEP-1036's spec text is PR #887, linked from the issue as "closed via"). The CLI's PR lookup fails on an issue number — pass `--spec-url` with the released page URL. +- **Quote the released page, not the draft** — read requirement text from `docs/specification//...`; the draft may have diverged since release (URL-mode elicitation's `elicitationId` and `notifications/elicitation/complete` were later removed from draft). Pin `spec_url` and every row `url:` to the `//` page, never `/draft/`. +- **Separate co-located SEPs** — a released page aggregates several SEPs (elicitation.mdx mixes SEP-1036, SEP-1330, SEP-1034). Diff the page against the previous released version to find what's new, then attribute sentences to the SEP you're covering and skip the neighbors'. + ## Step 9: Hand-off Report to the user, in this order: diff --git a/src/seps/sep-1036.yaml b/src/seps/sep-1036.yaml new file mode 100644 index 00000000..aca376a0 --- /dev/null +++ b/src/seps/sep-1036.yaml @@ -0,0 +1,126 @@ +# SEP-1036: URL mode elicitation (SEP issue #1036; spec changes landed via PR +# #887 plus pre-release refinements, e.g. #1863 for mode backwards +# compatibility). Part of the released 2025-11-25 spec version. Requirement +# text is quoted from the released page +# (docs/specification/2025-11-25/client/elicitation.mdx), not the draft — the +# draft has since diverged (elicitationId and notifications/elicitation/complete +# were removed from the draft in June 2026), so every URL below pins the +# 2025-11-25 version. +sep: 1036 +spec_url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation +requirements: + # ── Capabilities ────────────────────────────────────────────────────────── + - check: sep-1036-client-supports-declared-mode + text: 'Clients declaring the `elicitation` capability MUST support at least one mode (`form` or `url`).' + url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#capabilities + + - check: sep-1036-server-no-undeclared-mode + text: 'Servers MUST NOT send elicitation requests with modes that are not supported by the client.' + url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#capabilities + + # ── Elicitation Requests ────────────────────────────────────────────────── + - check: sep-1036-request-required-params + text: 'All elicitation requests MUST include the following parameters: mode (string, "form" or "url"; optional for form mode, defaults to "form" if omitted) and message (a human-readable message explaining why the interaction is needed).' + url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#elicitation-requests + + - check: sep-1036-client-modeless-is-form + text: 'Clients MUST treat requests without a `mode` field as form mode.' + url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#elicitation-requests + + - check: sep-1036-form-request-shape + text: 'Form mode elicitation requests MUST either specify mode: "form" or omit the mode field, and include these additional parameters: requestedSchema (a JSON Schema defining the structure of the expected response).' + url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#form-mode-elicitation-requests + + # ── URL Mode Elicitation Requests ───────────────────────────────────────── + - check: sep-1036-url-request-shape + text: 'URL mode elicitation requests MUST specify mode: "url", a message, and include these additional parameters: url (the URL that the user should navigate to) and elicitationId (a unique identifier for the elicitation).' + url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#url-mode-elicitation-requests + + - check: sep-1036-url-param-valid + text: 'The `url` parameter MUST contain a valid URL.' + url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#url-mode-elicitation-requests + + # ── Completion Notifications for URL Mode Elicitation ──────────────────── + - check: sep-1036-complete-notification-initiator-only + text: 'Servers sending notifications MUST only send the notification to the client that initiated the elicitation request.' + url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#completion-notifications-for-url-mode-elicitation + + - check: sep-1036-complete-notification-elicitation-id + text: 'Servers sending notifications MUST include the `elicitationId` established in the original `elicitation/create` request.' + url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#completion-notifications-for-url-mode-elicitation + + # ── URL Elicitation Required Error ──────────────────────────────────────── + - check: sep-1036-error-lists-elicitations + text: 'The error MUST include a list of elicitations that are required to complete before the original can be retried.' + url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#url-elicitation-required-error + + - check: sep-1036-error-elicitations-url-mode + text: 'Any elicitations returned in the error MUST be URL mode elicitations and have an `elicitationId` property.' + url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#url-elicitation-required-error + + # ── Error Handling ──────────────────────────────────────────────────────── + - check: sep-1036-url-elicitation-required-error-code + text: 'Servers MUST return standard JSON-RPC errors for common failure cases: When a request cannot be processed until an elicitation is completed: -32042 (URLElicitationRequiredError)' + url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#error-handling + + - check: sep-1036-client-rejects-undeclared-mode + text: 'Clients MUST return standard JSON-RPC errors for common failure cases: Server sends an elicitation/create request with a mode not declared in client capabilities: -32602 (Invalid params)' + url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#error-handling + + # ── Safe URL Handling (client) ──────────────────────────────────────────── + - check: sep-1036-client-no-prefetch + text: 'When handling URL mode elicitation requests, MCP clients MUST NOT automatically pre-fetch the URL or any of its metadata.' + url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#safe-url-handling + + # ── Excluded requirements ───────────────────────────────────────────────── + + - text: 'Servers MUST NOT use form mode elicitation to request sensitive information such as passwords, API keys, access tokens, or payment credentials / Servers MUST NOT request sensitive information (passwords, API keys, etc.) via form mode' + excluded: 'whether requested data is "sensitive information" is semantic; not decidable at the protocol level' + - text: 'Servers MUST use URL mode for interactions involving such sensitive information' + excluded: 'whether an interaction involves sensitive information is semantic; not decidable at the protocol level' + - text: 'MCP clients MUST: Provide UI that makes it clear which server is requesting information; Respect user privacy and provide clear decline and cancel options; For form mode, allow users to review and modify their responses before sending; For URL mode, clearly display the target domain/host and gather user consent before navigation to the target URL' + excluded: 'host UI behavior; not observable at the protocol level' + - text: 'The server MUST NOT return this error [URLElicitationRequiredError] except when URL mode elicitation is required.' + excluded: 'whether an elicitation is "required" is server-internal; only the error shape is observable (covered by the adjacent check rows)' + - text: 'Clients MUST ignore notifications referencing unknown or already-completed IDs.' + excluded: 'client-internal handling; JSON-RPC notifications produce no response, so "ignoring" has no wire-observable signal' + - text: 'Clients SHOULD still provide manual controls that let the user retry or cancel the original request (or otherwise resume interacting with the client) if the notification never arrives.' + excluded: 'host UI behavior; not observable at the protocol level' + - text: 'Servers implementing elicitation MUST securely associate this state with individual users following the guidelines in the security best practices document. / State MUST NOT be associated with session IDs alone / State storage MUST be protected against unauthorized access / For remote MCP servers, user identification MUST be derived from credentials acquired via MCP authorization when possible (e.g. sub claim)' + excluded: 'internal server state management; not observable at the protocol level' + - text: 'MCP servers MUST NOT rely on URL mode elicitation to authorize users for themselves.' + excluded: 'out-of-band authorization semantics; the harness cannot observe what the server uses the elicitation result for' + - text: "The third-party credentials MUST NOT transit through the MCP client / The MCP server MUST NOT use the client's credentials for the third-party service / The user MUST authorize the MCP server directly" + excluded: 'the harness cannot classify payloads as third-party credentials or observe the out-of-band authorization channel' + - text: 'The MCP server MUST NOT transmit credentials obtained through URL mode elicitation to the MCP client.' + excluded: 'the harness cannot classify payloads as credentials obtained via URL mode elicitation' + - text: 'Servers MUST bind elicitation requests to the client and user identity' + excluded: 'internal server state; the binding is not observable at the protocol level' + - text: 'MCP servers requesting elicitation MUST NOT include sensitive information about the end-user, including credentials, personal identifiable information, etc., in the URL sent to the client in a URL elicitation request.' + excluded: 'whether URL contents constitute sensitive end-user information is semantic; not decidable at the protocol level' + - text: 'MCP servers requesting elicitation MUST NOT provide a URL which is pre-authenticated to access a protected resource, as the URL could be used to impersonate the user by a malicious client.' + excluded: 'pre-authorization is a property of the out-of-band resource, not observable from the URL on the wire' + - text: 'MCP servers requesting elicitation SHOULD NOT include URLs intended to be clickable in any field of a form mode elicitation request.' + excluded: '"intended to be clickable" is authorial intent; not decidable at the protocol level' + - text: 'MCP servers requesting elicitation SHOULD use HTTPS URLs for non-development environments.' + excluded: 'the harness cannot distinguish development from production environments, so a non-HTTPS URL is not necessarily a violation' + - text: 'When handling URL mode elicitation requests, MCP clients MUST NOT open the URL without explicit consent from the user.' + excluded: 'host UI behavior; user consent is not observable at the protocol level' + - text: 'When handling URL mode elicitation requests, MCP clients MUST show the full URL to the user for examination before consent.' + excluded: 'host UI behavior; not observable at the protocol level' + - text: 'When handling URL mode elicitation requests, MCP clients MUST open the URL provided by the server in a secure manner that does not enable the client or LLM to inspect the content or user inputs.' + excluded: 'host/user-agent behavior outside the MCP wire; not observable at the protocol level' + - text: 'When handling URL mode elicitation requests, MCP clients SHOULD highlight the domain of the URL to mitigate subdomain spoofing.' + excluded: 'host UI behavior; not observable at the protocol level' + - text: 'When handling URL mode elicitation requests, MCP clients SHOULD have warnings for ambiguous/suspicious URIs (i.e., containing Punycode).' + excluded: 'host UI behavior; not observable at the protocol level' + - text: 'When handling URL mode elicitation requests, MCP clients SHOULD NOT render URLs as clickable in any field of an elicitation request, except for the `url` field in a URL elicitation request (with the restrictions detailed above).' + excluded: 'host UI rendering; not observable at the protocol level' + - text: 'Servers MUST NOT rely on client-provided user identification without server verification, as this can be forged. Instead, servers SHOULD follow security best practices.' + excluded: 'internal server verification policy; not observable at the protocol level' + - text: 'The MCP Server MUST verify the identity of the user who opens the URL before accepting information.' + excluded: 'occurs on the out-of-band web channel, outside the MCP wire' + - text: 'The server MUST ensure that the user who started the elicitation request (the end-user who is accessing the server via the MCP client) is the same user who completes the authorization flow.' + excluded: 'occurs on the out-of-band web channel, outside the MCP wire' + - text: "In all implementations, the server MUST ensure that the mechanism to determine the user's identity is resilient to attacks where an attacker can modify the elicitation URL." + excluded: 'internal server design property; not observable at the protocol level' From b3758a794ff4458898cdd0751b5cebcfdadb2f90 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 2 Jul 2026 18:39:17 +0000 Subject: [PATCH 2/2] Add missing diff rows, scope -32042 check, clarify exclusion rationales and SKILL.md variant --- .claude/skills/new-sep/SKILL.md | 18 +++++- src/seps/sep-1036.yaml | 101 ++++++++++++++++++++++++++++---- 2 files changed, 103 insertions(+), 16 deletions(-) diff --git a/.claude/skills/new-sep/SKILL.md b/.claude/skills/new-sep/SKILL.md index c936c96c..3a73685d 100644 --- a/.claude/skills/new-sep/SKILL.md +++ b/.claude/skills/new-sep/SKILL.md @@ -38,6 +38,8 @@ Extract from the user's input: - **sep-number** (required): the SEP number, e.g. `2164`. This is also the PR number in `modelcontextprotocol/modelcontextprotocol` by convention. +If the SEP shipped in a released spec version (a backfill), see the [Variant](#variant-backfilling-a-sep-from-a-released-spec-version) section — use `--spec-url` (`--spec-path` only accepts `docs/specification/draft/` paths). + ## Step 2: Generate the skeleton Run the CLI: @@ -51,7 +53,7 @@ node dist/index.js new-sep The CLI writes `src/seps/sep-.yaml` with `sep`, `spec_url`, and two TODO `requirements[]` rows. Capture the output path from the CLI's `Wrote …` line and remember it as `$YAML`. -If the CLI errors with "does not change any docs/specification/draft/\*.mdx", the SEP's spec changes landed in a separate PR — ask the user for the spec file path and rerun with `--spec-path docs/specification/draft/`. Do not guess. +If the CLI errors with "does not change any docs/specification/draft/\*.mdx", the SEP's spec changes landed in a separate PR — ask the user for the spec file path and rerun with `--spec-path docs/specification/draft/`. Do not guess. For a released-version backfill, use `--spec-url` instead — `--spec-path` only accepts `docs/specification/draft/` paths — see the [Variant](#variant-backfilling-a-sep-from-a-released-spec-version) section. ## Step 3: Fetch the spec diff @@ -190,9 +192,19 @@ If you find a plausible host, recommend it by path. If nothing fits, say so expl The steps above assume a draft-era SEP whose number is its spec PR. For SEPs that shipped in a released version (e.g. `2025-11-25`), four things change: - **Inventory** — the authoritative SEP list for a version is its changelog, `docs/specification//changelog.mdx` in the spec repo. Diff it against `ls src/seps/` to find gaps (governance SEPs like 932/994/1302/1730 have no protocol requirements — skip them). -- **SEP number ≠ PR number** — pre-draft-era SEPs are issue numbers; the spec diff landed in a separate PR (e.g. SEP-1036's spec text is PR #887, linked from the issue as "closed via"). The CLI's PR lookup fails on an issue number — pass `--spec-url` with the released page URL. +- **SEP number ≠ PR number** — pre-draft-era SEPs are issue numbers; the spec diff landed in a separate PR (e.g. SEP-1036's spec text is PR #887, linked from the issue as "closed via"). Always pass `--spec-url` for released-version backfills; never rely on the PR lookup (a same-numbered unrelated PR can silently succeed with a wrong `spec_url`). - **Quote the released page, not the draft** — read requirement text from `docs/specification//...`; the draft may have diverged since release (URL-mode elicitation's `elicitationId` and `notifications/elicitation/complete` were later removed from draft). Pin `spec_url` and every row `url:` to the `//` page, never `/draft/`. -- **Separate co-located SEPs** — a released page aggregates several SEPs (elicitation.mdx mixes SEP-1036, SEP-1330, SEP-1034). Diff the page against the previous released version to find what's new, then attribute sentences to the SEP you're covering and skip the neighbors'. +- **Separate co-located SEPs** — a released page aggregates several SEPs (elicitation.mdx mixes SEP-1036, SEP-1330, SEP-1034). Diff the page against the previous released version to find what's new, then attribute sentences to the SEP you're covering and skip the neighbors'. Concretely, fetch both versions' page and diff them: + + ```bash + base=https://raw.githubusercontent.com/modelcontextprotocol/modelcontextprotocol/main/docs/specification + curl -sf "$base/2025-06-18/client/elicitation.mdx" -o /tmp/old.mdx + curl -sf "$base/2025-11-25/client/elicitation.mdx" -o /tmp/new.mdx + git diff --no-index /tmp/old.mdx /tmp/new.mdx + ``` + +- **Exclusion sign-off moves to PR review** — Step 6's interactive `AskUserQuestion` sign-off is replaced by maintainer review of the draft PR for backfills: write the proposed `excluded:` rows with their rationales into the yaml and let maintainers approve or flip them on the PR. +- **Disposition reworded sentences explicitly** — diff sentences that were reworded but can't be attributed to a specific prior sentence (e.g. a SHOULD→MUST upgrade, or one old sentence split into two) must be dispositioned explicitly — a YAML comment on the row or a note in the PR description — so they don't fall through the traceability net. ## Step 9: Hand-off diff --git a/src/seps/sep-1036.yaml b/src/seps/sep-1036.yaml index aca376a0..1d5da42d 100644 --- a/src/seps/sep-1036.yaml +++ b/src/seps/sep-1036.yaml @@ -10,7 +10,10 @@ sep: 1036 spec_url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation requirements: # ── Capabilities ────────────────────────────────────────────────────────── - - check: sep-1036-client-supports-declared-mode + # Both capability checks must honor the backwards-compatibility rule (spec + # PR #1863): an empty `elicitation: {}` capability object is equivalent to + # declaring `form` mode only — treat it as form-only, never as "no modes". + - check: sep-1036-client-supports-at-least-one-mode text: 'Clients declaring the `elicitation` capability MUST support at least one mode (`form` or `url`).' url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#capabilities @@ -19,8 +22,11 @@ requirements: url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#capabilities # ── Elicitation Requests ────────────────────────────────────────────────── + # The net-testable assertion is: `message` always present; `mode`, when + # present, is "form" or "url" (the table makes `mode` optional for form + # mode). - check: sep-1036-request-required-params - text: 'All elicitation requests MUST include the following parameters: mode (string, "form" or "url"; optional for form mode, defaults to "form" if omitted) and message (a human-readable message explaining why the interaction is needed).' + text: 'All elicitation requests MUST include the following parameters: `mode` (string, options `form`, `url`): The mode of the elicitation. Optional for form mode (defaults to `"form"` if omitted). `message` (string): A human-readable message explaining why the interaction is needed.' url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#elicitation-requests - check: sep-1036-client-modeless-is-form @@ -28,12 +34,12 @@ requirements: url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#elicitation-requests - check: sep-1036-form-request-shape - text: 'Form mode elicitation requests MUST either specify mode: "form" or omit the mode field, and include these additional parameters: requestedSchema (a JSON Schema defining the structure of the expected response).' + text: 'Form mode elicitation requests MUST either specify `mode: "form"` or omit the `mode` field, and include these additional parameters: `requestedSchema` (object): A JSON Schema defining the structure of the expected response.' url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#form-mode-elicitation-requests # ── URL Mode Elicitation Requests ───────────────────────────────────────── - check: sep-1036-url-request-shape - text: 'URL mode elicitation requests MUST specify mode: "url", a message, and include these additional parameters: url (the URL that the user should navigate to) and elicitationId (a unique identifier for the elicitation).' + text: 'URL mode elicitation requests MUST specify `mode: "url"`, a `message`, and include these additional parameters: `url` (string): The URL that the user should navigate to. `elicitationId` (string): A unique identifier for the elicitation.' url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#url-mode-elicitation-requests - check: sep-1036-url-param-valid @@ -41,6 +47,17 @@ requirements: url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#url-mode-elicitation-requests # ── Completion Notifications for URL Mode Elicitation ──────────────────── + # Version-locked: both checks below apply only when the negotiated + # protocolVersion is 2025-11-25 — `elicitationId` and + # `notifications/elicitation/complete` were removed from the draft in June + # 2026. Both also need a fixture that triggers a completion: the + # notification is optional and server-initiated, so nothing in the base + # flow forces one to appear. + + # Intended assertion: two clients connected over HTTP; one initiates the + # URL mode elicitation; the harness asserts the completion notification is + # observed at the initiating client and absent at the non-initiating + # client. No multi-client harness infrastructure exists yet. - check: sep-1036-complete-notification-initiator-only text: 'Servers sending notifications MUST only send the notification to the client that initiated the elicitation request.' url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#completion-notifications-for-url-mode-elicitation @@ -59,12 +76,18 @@ requirements: url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#url-elicitation-required-error # ── Error Handling ──────────────────────────────────────────────────────── + # Scoping: the governing section (#url-elicitation-required-error) says the + # server MAY return a URLElicitationRequiredError, so this check is + # conditional — when a server elects the pattern, the error MUST be `-32042` + # with the URLElicitationRequiredError shape. The scenario needs a fixture + # that elects the pattern; servers that never use it must not fail this + # check. - check: sep-1036-url-elicitation-required-error-code - text: 'Servers MUST return standard JSON-RPC errors for common failure cases: When a request cannot be processed until an elicitation is completed: -32042 (URLElicitationRequiredError)' + text: 'Servers MUST return standard JSON-RPC errors for common failure cases: When a request cannot be processed until an elicitation is completed: `-32042` (`URLElicitationRequiredError`)' url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#error-handling - check: sep-1036-client-rejects-undeclared-mode - text: 'Clients MUST return standard JSON-RPC errors for common failure cases: Server sends an elicitation/create request with a mode not declared in client capabilities: -32602 (Invalid params)' + text: 'Clients MUST return standard JSON-RPC errors for common failure cases: Server sends an `elicitation/create` request with a mode not declared in client capabilities: `-32602` (Invalid params)' url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#error-handling # ── Safe URL Handling (client) ──────────────────────────────────────────── @@ -72,55 +95,107 @@ requirements: text: 'When handling URL mode elicitation requests, MCP clients MUST NOT automatically pre-fetch the URL or any of its metadata.' url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#safe-url-handling + # ── Form Mode Security ──────────────────────────────────────────────────── + # WARNING severity (SHOULD keyword). Wire-testable: the harness, acting as + # the client, returns an elicitation response that violates the + # `requestedSchema` and observes how the server handles it. Needs a + # scenario/fixture that elicits and then violates the schema. + - check: sep-1036-server-validates-received-data + text: 'Servers SHOULD validate received data matches the requested schema' + url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#form-mode-security + # ── Excluded requirements ───────────────────────────────────────────────── + # The first sentence is from the User Interaction Model warning; the second + # is its Form Mode Security restatement (#form-mode-security). - text: 'Servers MUST NOT use form mode elicitation to request sensitive information such as passwords, API keys, access tokens, or payment credentials / Servers MUST NOT request sensitive information (passwords, API keys, etc.) via form mode' excluded: 'whether requested data is "sensitive information" is semantic; not decidable at the protocol level' + url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#user-interaction-model - text: 'Servers MUST use URL mode for interactions involving such sensitive information' excluded: 'whether an interaction involves sensitive information is semantic; not decidable at the protocol level' + url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#user-interaction-model - text: 'MCP clients MUST: Provide UI that makes it clear which server is requesting information; Respect user privacy and provide clear decline and cancel options; For form mode, allow users to review and modify their responses before sending; For URL mode, clearly display the target domain/host and gather user consent before navigation to the target URL' excluded: 'host UI behavior; not observable at the protocol level' + url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#user-interaction-model - text: 'The server MUST NOT return this error [URLElicitationRequiredError] except when URL mode elicitation is required.' excluded: 'whether an elicitation is "required" is server-internal; only the error shape is observable (covered by the adjacent check rows)' + url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#url-elicitation-required-error - text: 'Clients MUST ignore notifications referencing unknown or already-completed IDs.' - excluded: 'client-internal handling; JSON-RPC notifications produce no response, so "ignoring" has no wire-observable signal' + excluded: 'compliance produces no positive signal; only gross violations (error response, disconnect, spurious retry) are wire-observable' + url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#completion-notifications-for-url-mode-elicitation - text: 'Clients SHOULD still provide manual controls that let the user retry or cancel the original request (or otherwise resume interacting with the client) if the notification never arrives.' excluded: 'host UI behavior; not observable at the protocol level' - - text: 'Servers implementing elicitation MUST securely associate this state with individual users following the guidelines in the security best practices document. / State MUST NOT be associated with session IDs alone / State storage MUST be protected against unauthorized access / For remote MCP servers, user identification MUST be derived from credentials acquired via MCP authorization when possible (e.g. sub claim)' + url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#completion-notifications-for-url-mode-elicitation + - text: 'Servers implementing elicitation MUST securely associate this state with individual users following the guidelines in the security best practices document. / State MUST NOT be associated with session IDs alone / State storage MUST be protected against unauthorized access / For remote MCP servers, user identification MUST be derived from credentials acquired via MCP authorization when possible (e.g. `sub` claim)' excluded: 'internal server state management; not observable at the protocol level' + url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#statefulness - text: 'MCP servers MUST NOT rely on URL mode elicitation to authorize users for themselves.' excluded: 'out-of-band authorization semantics; the harness cannot observe what the server uses the elicitation result for' + url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#url-mode-elicitation-for-oauth-flows - text: "The third-party credentials MUST NOT transit through the MCP client / The MCP server MUST NOT use the client's credentials for the third-party service / The user MUST authorize the MCP server directly" - excluded: 'the harness cannot classify payloads as third-party credentials or observe the out-of-band authorization channel' + excluded: 'testable via a credential-canary fixture (harness authors the credential and asserts it never appears on any wire message); scenario deferred' + url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#understanding-the-distinction - text: 'The MCP server MUST NOT transmit credentials obtained through URL mode elicitation to the MCP client.' - excluded: 'the harness cannot classify payloads as credentials obtained via URL mode elicitation' + excluded: 'testable via a credential-canary fixture (harness authors the credential and asserts it never appears on any wire message); scenario deferred' + url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#understanding-the-distinction - text: 'Servers MUST bind elicitation requests to the client and user identity' excluded: 'internal server state; the binding is not observable at the protocol level' + url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#security-considerations + # New in 2025-11-25: the 2025-06-18 page had this as SHOULD ("Clients SHOULD + # provide clear indication of which server is requesting information"); the + # SHOULD→MUST upgrade pulls the sentence into this SEP's diff. + - text: 'Clients MUST provide clear indication of which server is requesting information' + excluded: 'host UI behavior; not observable at the protocol level' + url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#security-considerations - text: 'MCP servers requesting elicitation MUST NOT include sensitive information about the end-user, including credentials, personal identifiable information, etc., in the URL sent to the client in a URL elicitation request.' excluded: 'whether URL contents constitute sensitive end-user information is semantic; not decidable at the protocol level' + url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#safe-url-handling - text: 'MCP servers requesting elicitation MUST NOT provide a URL which is pre-authenticated to access a protected resource, as the URL could be used to impersonate the user by a malicious client.' excluded: 'pre-authorization is a property of the out-of-band resource, not observable from the URL on the wire' + url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#safe-url-handling - text: 'MCP servers requesting elicitation SHOULD NOT include URLs intended to be clickable in any field of a form mode elicitation request.' excluded: '"intended to be clickable" is authorial intent; not decidable at the protocol level' + url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#safe-url-handling - text: 'MCP servers requesting elicitation SHOULD use HTTPS URLs for non-development environments.' excluded: 'the harness cannot distinguish development from production environments, so a non-HTTPS URL is not necessarily a violation' + url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#safe-url-handling + # Chapeau for the numbered client-side Safe URL Handling rules. + - text: 'Clients implementing URL mode elicitation MUST handle URLs carefully to prevent users from unknowingly clicking malicious links.' + excluded: 'umbrella obligation; its operative content is covered by the numbered Safe URL Handling rows (the pre-fetch check plus the excluded UI rows below)' + url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#safe-url-handling - text: 'When handling URL mode elicitation requests, MCP clients MUST NOT open the URL without explicit consent from the user.' excluded: 'host UI behavior; user consent is not observable at the protocol level' + url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#safe-url-handling - text: 'When handling URL mode elicitation requests, MCP clients MUST show the full URL to the user for examination before consent.' excluded: 'host UI behavior; not observable at the protocol level' + url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#safe-url-handling - text: 'When handling URL mode elicitation requests, MCP clients MUST open the URL provided by the server in a secure manner that does not enable the client or LLM to inspect the content or user inputs.' excluded: 'host/user-agent behavior outside the MCP wire; not observable at the protocol level' + url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#safe-url-handling - text: 'When handling URL mode elicitation requests, MCP clients SHOULD highlight the domain of the URL to mitigate subdomain spoofing.' excluded: 'host UI behavior; not observable at the protocol level' + url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#safe-url-handling - text: 'When handling URL mode elicitation requests, MCP clients SHOULD have warnings for ambiguous/suspicious URIs (i.e., containing Punycode).' excluded: 'host UI behavior; not observable at the protocol level' + url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#safe-url-handling - text: 'When handling URL mode elicitation requests, MCP clients SHOULD NOT render URLs as clickable in any field of an elicitation request, except for the `url` field in a URL elicitation request (with the restrictions detailed above).' excluded: 'host UI rendering; not observable at the protocol level' + url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#safe-url-handling - text: 'Servers MUST NOT rely on client-provided user identification without server verification, as this can be forged. Instead, servers SHOULD follow security best practices.' excluded: 'internal server verification policy; not observable at the protocol level' + url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#identifying-the-user + # Reworks 2025-06-18's "Both parties SHOULD validate elicitation content + # against the provided schema" — this is the client half of that split; the + # server half is the sep-1036-server-validates-received-data check above. + - text: 'Clients SHOULD validate all responses against the provided schema' + excluded: 'client-internal validation; whether the client validated before responding is not observable on the wire' + url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#form-mode-security - text: 'The MCP Server MUST verify the identity of the user who opens the URL before accepting information.' - excluded: 'occurs on the out-of-band web channel, outside the MCP wire' - - text: 'The server MUST ensure that the user who started the elicitation request (the end-user who is accessing the server via the MCP client) is the same user who completes the authorization flow.' - excluded: 'occurs on the out-of-band web channel, outside the MCP wire' + excluded: 'web-flow interaction not standardized; needs fixture cooperation' + url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#phishing + - text: 'To prevent this attack, the server MUST ensure that the user who started the elicitation request (the end-user who is accessing the server via the MCP client) is the same user who completes the authorization flow.' + excluded: 'web-flow interaction not standardized; needs fixture cooperation' + url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#phishing - text: "In all implementations, the server MUST ensure that the mechanism to determine the user's identity is resilient to attacks where an attacker can modify the elicitation URL." excluded: 'internal server design property; not observable at the protocol level' + url: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#phishing