Skip to content

Route MCP elicitation IDs across managers#29944

Open
jif-oai wants to merge 1 commit into
jif/prepare-selected-capability-snapshotsfrom
jif/route-mcp-elicitation-ids
Open

Route MCP elicitation IDs across managers#29944
jif-oai wants to merge 1 commit into
jif/prepare-selected-capability-snapshotsfrom
jif/route-mcp-elicitation-ids

Conversation

@jif-oai

@jif-oai jif-oai commented Jun 25, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • prefix surfaced MCP elicitation IDs with a manager-unique route ID
  • keep native request IDs for server-side review while routing client responses by the surfaced ID
  • cover simultaneous managers that emit the same server-local request ID

Why

Runtime snapshot preparation can briefly keep an active MCP manager and a candidate manager alive together. MCP request IDs are connection-local, so responses need a manager discriminator to avoid being delivered to the wrong generation.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a70665711b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +224 to +227
let response_id = RequestId::String(Arc::from(format!("{route_id}:{id}")));
{
let mut lock = elicitation_requests.lock().await;
lock.insert((server_name.clone(), id.clone()), tx);
lock.insert((server_name.clone(), response_id.clone()), tx);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Badge Route responses to the originating manager

When a refreshed/candidate manager emits an elicitation before refresh_mcp_servers swaps it in, or a superseded manager still has an unanswered prompt, the client returns this routed ID but Session::resolve_elicitation still calls mcp_connection_manager.load_full().resolve_elicitation(...) on only the current manager. Because the routed ID is stored only in the originating manager's local requests map here, the prefix does not actually route across managers and the response is rejected as elicitation request not found; please keep a session-level registry or dispatch by the route prefix to the owning manager.

Useful? React with 👍 / 👎.

},
};
let (tx, rx) = oneshot::channel();
let response_id = RequestId::String(Arc::from(format!("{route_id}:{id}")));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Badge Preserve request ID variant in routed keys

If an MCP server has overlapping elicitations whose JSON-RPC IDs are 1 and "1", this stringified routed ID makes both entries use the same key (<route>:1), so the second insert overwrites the first responder and one request can never be resolved. The previous typed RequestId key distinguished numeric and string IDs, so the route wrapper should encode the variant as well as the value.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant