-
Notifications
You must be signed in to change notification settings - Fork 194
Description
Is your feature request related to a problem? Please describe.
When building interactive workflows with MCP Apps, there is currently no protocol-level way to pause an agent until a user completes a UI interaction. A tool call that includes _meta.ui.resourceUri renders a rich UI, but the tool returns immediately — the agent continues without waiting for the user. The only workaround is instructing the agent via tool description text to "wait for the user", which is fragile and LLM-dependent.
Elicitation (elicitation/create) does block the server while waiting for user input, but the client renders only a flat form derived from the JSON schema. This makes elicitation unsuitable for interactions that require rich UI — multi-step flows, visual pickers, data tables, custom confirmation dialogs, and so on.
The result is a gap: there is no way to say "show the user this rich UI, collect their input, and only then let the server continue."
Describe the solution you'd like
Allow a server to include a _meta.ui.resourceUri hint on an elicitation/create request. When present, a host that supports both MCP Apps and elicitation renders the referenced UI resource instead of the default flat form. The UI collects the user interaction and resolves the elicitation with a response conforming to requestedSchema, unblocking the server.
{
"method": "elicitation/create",
"params": {
"message": "Please review the portfolio and confirm the account manager assignment.",
"requestedSchema": {
"type": "object",
"properties": {
"confirmed": { "type": "boolean", "title": "Confirm" },
"selectedManagerId": { "type": "string", "title": "Account Manager ID" }
},
"required": ["confirmed", "selectedManagerId"]
},
"_meta": {
"ui": {
"resourceUri": "ui://customer-portfolio/assign-manager"
}
}
}
}The flow would be:
- Server issues
elicitation/createwith bothrequestedSchemaand_meta.ui.resourceUri. - Host fetches and renders the UI resource in a sandboxed iframe (standard MCP Apps flow).
- Host passes the elicitation context to the UI (e.g. via
app.ontoolresultor a newapp.onelicitationevent). - User completes the interaction; the UI calls back with data satisfying
requestedSchema(e.g. viaapp.callServerTool()or a newapp.resolveElicitation(data)method). - Host sends the
elicitation/createresponse to the server, which unblocks and completes the tool call.
Hosts that do not support MCP Apps fall back gracefully to the flat form from requestedSchema — fully backwards compatible.
Describe alternatives you've considered
- Tool description instructions — telling the LLM agent to "wait for the user to interact with the UI before proceeding." This works in practice but is fragile, model-dependent, and not a protocol guarantee.
- Having the UI call a dedicated follow-up tool — the UI triggers a second tool call via
app.callServerTool()after the user completes the interaction, effectively signalling completion. This bypasses the agent entirely and works today, but means the original tool call has already returned, so the server cannot use the user's input to complete the original operation and return a result to the agent. - SEP-1686 Tasks (
input_requiredstate) — the Tasks proposal models a server pausing to wait for elicitation during a long-running operation. This is complementary but a heavier primitive; attaching a UI resource to a standard elicitation request is a simpler, more targeted solution for the interactive UI use case.
Additional context
A concrete real-world scenario: an MCP server exposes a tool that retrieves a customer portfolio and asks the user to assign an account manager. The ideal UX is a rich dashboard (cards, health indicators, a dropdown to select the manager) rendered inline in the agent chat. Today this requires either accepting that the agent won't wait for the user, or working around it with tool description hacks. Rich UI elicitation would make this a first-class, reliable pattern.
This proposal composes two existing MCP primitives rather than introducing new ones — the elicitation blocking mechanism stays unchanged, and the _meta.ui pattern follows what MCP Apps already does for tool calls. The main open design question is whether the UI resolves the elicitation via an existing app.callServerTool() call to a server-side endpoint, or via a new host-level API like app.resolveElicitation(data).
Related:
- MCP Elicitation spec: [specification/2025-06-18/client/elicitation.mdx](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/specification/2025-06-18/client/elicitation.mdx)
- SEP-1036 URL Mode Elicitation: [modelcontextprotocol#1036](SEP-1036: URL Mode Elicitation for secure out-of-band interactions modelcontextprotocol#1036)
- SEP-1686 Tasks: [modelcontextprotocol#1686](SEP-1686: Tasks modelcontextprotocol#1686)
- MCP Apps spec (SEP-1865): [specification/draft/apps.mdx](https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/draft/apps.mdx)