Skip to content

Conversation

@nbarbettini
Copy link
Contributor

@nbarbettini nbarbettini commented Jul 1, 2025

This PR is the specification proposal for SEP #1036.

This PR introduces an elicitation mode for secure out-of-band interactions that bypass the MCP client.

There are some important use cases that require the MCP server to interact with the end-user in a secure way:

  • Gathering sensitive data, like API keys
  • Authorization and step-up auth for external (3rd-party) resource servers
  • Payments and subscriptions

These interactions are highly sensitive in nature. Web applications have long avoided directly requesting third-party passwords or credentials by using flows like OAuth, and we can take inspiration from this solution.

The new elicitation mode proposed here requires that the MCP client obtain consent from the user, and then facilitate navigation to a URL in a user-agent (aka browser) where these interactions can occur securely and avoid transmitting sensitive data through the client.

Motivation and Context

One of the hot topics discussed but not addressed in #284 was the idea of fine-grained authorization for specific tools or resources in a third-party "downstream" API. This is not in scope for MCP authorization, which establishes authorization between the MCP client and MCP server only. Furthermore, the Security Best Practices document explains why MCP servers cannot be "simple" token passthrough servers.

In conversations with the community, it became clear that a mechanism for "downstream" authorization challenges and other sensitive flows was needed. @wdawson and I discussed a narrow version of this idea in #234, and proposed a broader user interaction mechanism in #475.

In the meantime, elicitation was added to the spec as a mechanism to request non-sensitive information from the user via in-band requests. In discussions with @bhosmer-ant and @pcarleton, we decided to reformat our ideas into a new mode of elicitation, instead of introducing a similar-but-different mechanism for out-of-band interactions.

This PR rolls up all of the feedback we received on #475. Thank you to everyone who helped review the first draft!

How Has This Been Tested?

TODO: Sample app showing both the client and server side of out-of-band elicitation.

Breaking Changes

  1. Clients must now describe which modes of elicitation they support during initialization:
{
  "capabilities": {
    "elicitation": {
      // One or both of:
      "form": {},
      "oob": {}
    }
  }
}
  1. elicitation/create requests must now specify the mode field (either form or oob)

Reference Implementation

Client/server implementation in TypeScript: feat/url-elicitation

Explainer video: https://drive.google.com/file/d/1llCFS9wmkK_RUgi5B-zHfUUgy-CNb0n0/view?usp=sharing

Acknowledgements

Huge thanks to @localden, @siwachabhi, @connor4312, @pwwpche, @aaronpk, @btiernay, @ggoodman, @chhamilton, @patwhite, @adranwit, @LucaButBoring, @max-stytch, @mcguinness, and many others who have helped publicly and privately to refine this proposal.

@nbarbettini
Copy link
Contributor Author

nbarbettini commented Jul 1, 2025

(Comment reserved for future use)

- `"form"`: In-band structured data collection with optional schema validation. Data is exposed to the client.
- `"oob"`: Out-of-band interaction via URL navigation. Data is **not** exposed to the client.

### Form Elicitation Requests
Copy link
Contributor Author

@nbarbettini nbarbettini Jul 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note to reviewers: This section is not new, but re-organized so that we can clearly describe form mode elicitation here, and URL mode elicitation in the next sub-section.

| ----------------- | ------ | -------------------------------------------------------------- |
| `requestedSchema` | object | A JSON Schema defining the structure of the expected response. |

#### Requested Schema
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note to reviewers: No changes here! (just moved)

}
```

Clients declaring the `elicitation` capability **MUST** support at least one mode (`form` or `oob`).
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We considered allowing elicitation: {} to imply elicitation: { form: {} } for backwards compatibility with the 2025-06-18 spec version, at the cost of more logic when parsing capabilities. For now, we've proposed this small breaking change since we're already targeting a new spec version. Open to feedback from the community here.

@nbarbettini nbarbettini changed the title feat: Add out-of-band elicitation mode feat: Secure (out-of-band) elicitation Jul 1, 2025
@nbarbettini
Copy link
Contributor Author

Updated the title to be less jargony, thanks for the suggestion @localden!

/**
* @category `elicitation/create`
*/
export interface ElicitRequestURLParams extends ElicitRequestParams {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently, how the interfaces are structured, the ElicitRequestURLParams would also have the requestedSchema in it, because it extends ElicitRequestParams defined above - understand from this SEP that requestedSchema should only be present for form types and not for url elicitation mode.

pcarleton
pcarleton previously approved these changes Nov 13, 2025
Copy link
Member

@pcarleton pcarleton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

overall looks good. I'm approving, but let's get the suggested typescript schema changes in.

I'd also like to discuss in a follow-up adjusting the language around not providing URLs in other fields since the default implementation of that I think will be overly restrictive.

This is with my conformance hat on, where we'd want some way to enforce the MUST, and I think the enforcement would be too restrictive.

- Servers **MUST NOT** use elicitation to request sensitive information.
- Servers **MUST NOT** use form mode elicitation to request sensitive information
- Servers **MUST** use URL mode for interactions involving sensitive information, such as credentials
- URLs **MUST NOT** appear in any field of an elicitation request, other than the `url` field in an URL mode request
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we'll want to change this to something like "Clients SHOULD NOT render URLs as clickable in any other field of an elicitation request". (can be in a follow-up, I'd like to get the bulk of this in).

A strict interpretation of this would have clients rejecting elicitation requests that have URLs in other parts of the elicitation request as invalid, but there are valid reasons to have it in other fields. For example, an email drafting server may send the email body as a "default" value for the use to edit before sending. The email body might contain links. Or a research mode might list the URL's it searched over in a message in order to "show its work" before getting accept/reject from a client.

@nbarbettini
Copy link
Contributor Author

@pcarleton

I think we'll want to change this to something like "Clients SHOULD NOT render URLs as clickable in any other field of an elicitation request". (can be in a follow-up, I'd like to get the bulk of this in).

That is very much in the spirit of what my initial language meant to achieve. I totally agree, I can do a fast-follow to add this!

@KKonstantinov
Copy link

Thanks for the quick resolution of the typescript schemas! All good now!

@pcarleton pcarleton dismissed dsp-ant’s stale review November 13, 2025 14:46

reivisiting the URL should/must language mentioned in review in a follow up

@pcarleton pcarleton merged commit 4528444 into modelcontextprotocol:main Nov 13, 2025
2 checks passed
@nbarbettini nbarbettini deleted the feature/elicitation-out-of-band branch November 13, 2025 14:52
cbcoutinho added a commit to cbcoutinho/python-sdk that referenced this pull request Nov 13, 2025
…actions

This commit adds support for URL mode elicitation as specified in SEP-1036,
enabling servers to direct users to external URLs for sensitive interactions
that must not pass through the MCP client.

Key changes:

Types (src/mcp/types.py):
- Add ELICITATION_REQUIRED error code (-32000)
- Update ElicitationCapability to support form and url modes
- Add ElicitTrackRequest and ElicitTrackResult for progress tracking
- Add UrlElicitationInfo and ElicitationRequiredErrorData types
- Update ElicitRequestParams with mode field and URL mode parameters

Server (src/mcp/server/):
- Add elicit_url() helper function in elicitation.py
- Add elicit_form() and elicit_url() methods to ServerSession
- Maintain backward compatibility with existing elicit() method

Client (src/mcp/client/session.py):
- Update capability negotiation for form and URL modes
- Add track_elicitation() method for progress monitoring

Tests:
- Comprehensive test coverage for URL mode elicitation
- Verify backward compatibility with form mode
- All 311 existing tests pass

Use cases enabled:
- OAuth authorization flows with third-party services
- Secure credential collection (API keys, passwords)
- Payment and subscription flows
- Any sensitive interaction requiring out-of-band handling

Breaking changes:
- ElicitRequestParams now requires mode field ("form" or "url")
- Clients must declare which elicitation modes they support

Closes: modelcontextprotocol/modelcontextprotocol#887
connor4312 added a commit to microsoft/vscode that referenced this pull request Nov 13, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

accepted SEP accepted by core maintainers, but still requires final wording and reference implementation. auth draft SEP proposal with a sponsor. security SEP

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SEP-1036: URL Mode Elicitation for secure out-of-band interactions