Skip to content

Multi Round-Trip Request (MRTR) Proposal#7

Closed
markdroth wants to merge 2 commits intomodelcontextprotocol:mainfrom
markdroth:mrtr-proposal
Closed

Multi Round-Trip Request (MRTR) Proposal#7
markdroth wants to merge 2 commits intomodelcontextprotocol:mainfrom
markdroth:mrtr-proposal

Conversation

@markdroth
Copy link
Contributor

Initial draft of a proposal for the MRTR problem.

See previous discussion in the original document.

// Similar to existing JSONRPCResultResponse.
// Used in cases where the server needs the results of one or more requests
// of its own before it can complete the client's request.
export interface JSONRPCIncompleteResultResponse {
Copy link
Contributor

Choose a reason for hiding this comment

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

Agree with the proposal for tool calls,

Would like to discuss the Result Response. In #9 I propose two additional message format options, that extend or reuse existing concepts vs adding a new one.

My preference is Option 2 which extends the existing Tool Result Concept to encapsulate this new response type while being able to leverage existing messaging semantics.

Choose a reason for hiding this comment

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

+1 to extending Tool Results. It's already polymorphic so adding new "request" types would be easier to do while maintaining backward compatibility when writing servers.

1. Client sends a CallToolRequest.
2. Server sends back a single response (**not** an SSE stream) indicating
that the request is incomplete and that an elicitation request is required.
3. Client sends a new CallToolRequest, completely independent of the
Copy link

Choose a reason for hiding this comment

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

Edge case to consider: The server sends multiple requests. The client responds with one. Some options:

  1. [Preferred] Return a 400. The client is required by protocol to return all responses at the same time.
  2. The client responds with the requests not answered. This seems less ideal as it's possible a client could answer the same server request multiple times.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The problem is that I don't think the server can tell whether the client responded to all of the requests it was told to, because it doesn't know which server instance told it to send those responses. In upgrade cases, this may be difficult or impossible to tell.

I think it's fine for the server to just respond with whichever dependent requests it doesn't yet have. If the client sees the same request a second time because it didn't answer it the first time, that just means that the client can deal with the result of its own bug. :)

id: RequestId;
// Requests issued by the server that must be complete before the
// client can retry.
dependent_requests: { [key: string]: ServerRequest };
Copy link

@gjz22 gjz22 Jan 28, 2026

Choose a reason for hiding this comment

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

Proposal rather than a key:
Let's use 1685 for this. The goal of 1685 is to allow the server to pass context to the client that is echo'ed back to the server when the response is submitted in order to help the server process the response. That's effectively what is being done here. If the state is passed to the client, they then CAN use a machine readable key but they don't have to in cases where there is only one request (likely the vast majority), which simplifies clients and reduces complexity and allows us to keep this as a list.

Example: state: "github_login"

Separately, a ServerRequest is a JSON RPC request, so it will seem weird to nest them. For example, should the JSON RPC requirements that an id is supplied in the request and the response should mirror that be respected? Should we add a new type here, that is more clear/useful long term?

Choose a reason for hiding this comment

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

+1 not having a unique ID for the dependent requests will be hard to implement in servers

@markdroth
Copy link
Contributor Author

Closing this as a duplicate of #12.

@markdroth markdroth closed this Feb 4, 2026
@markdroth markdroth deleted the mrtr-proposal branch February 4, 2026 00:17
Copy link
Contributor Author

@markdroth markdroth left a comment

Choose a reason for hiding this comment

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

Just responding to one quick comment here that I didn't notice earlier. After this, let's take discussion to #12. Thanks!

1. Client sends a CallToolRequest.
2. Server sends back a single response (**not** an SSE stream) indicating
that the request is incomplete and that an elicitation request is required.
3. Client sends a new CallToolRequest, completely independent of the
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The problem is that I don't think the server can tell whether the client responded to all of the requests it was told to, because it doesn't know which server instance told it to send those responses. In upgrade cases, this may be difficult or impossible to tell.

I think it's fine for the server to just respond with whichever dependent requests it doesn't yet have. If the client sees the same request a second time because it didn't answer it the first time, that just means that the client can deal with the result of its own bug. :)

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.

4 participants