Skip to content

Commit 6fafdf2

Browse files
halter73Copilot
andcommitted
Rebase MRTR onto main (squash merge with conflict resolution)
Resolves conflicts from rebasing the MRTR work (originally branched from 4140c6d) onto the current main (b8c4d95). Key conflict resolutions: - McpClientImpl.SendRequestAsync: combine SEP-2243 tool-context attachment with MRTR retry loop for IncompleteResult. - McpSessionHandler.SendRequestAsync: take MRTR's outgoing filter and request logging. - McpServerImpl.InvokeHandlerAsync: take MRTR's CreateDestinationBoundServer. - docs/concepts/index.md: combine main's Tasks entry with MRTR additions. - MapMcpTests.cs: keep main's new IncomingFilter/OutgoingFilter tests in full, drop MRTR's outdated overload usage by going through configureClient. - MrtrIntegrationTests.cs: gate with #if !NET472 (uses ReadLineAsync(CT)). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent b8c4d95 commit 6fafdf2

51 files changed

Lines changed: 6326 additions & 91 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/concepts/elicitation/elicitation.md

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,82 @@ Here's an example implementation of how a console application might handle elici
170170

171171
[!code-csharp[](samples/client/Program.cs?name=snippet_ElicitationHandler)]
172172

173+
### Multi Round-Trip Requests (MRTR)
174+
175+
When both the client and server opt in to the experimental [MRTR](xref:mrtr) protocol, elicitation requests are handled via incomplete result / retry instead of a direct JSON-RPC request. This is transparent — the existing `ElicitAsync` API works identically regardless of whether MRTR is active.
176+
177+
#### High-level API
178+
179+
No code changes are needed. `ElicitAsync` automatically uses MRTR when both sides have opted in, and falls back to legacy JSON-RPC requests otherwise:
180+
181+
```csharp
182+
// This code works the same with or without MRTR — the SDK handles it transparently.
183+
var result = await server.ElicitAsync(new ElicitRequestParams
184+
{
185+
Message = "Please confirm the action",
186+
RequestedSchema = new()
187+
{
188+
Properties = new Dictionary<string, ElicitRequestParams.PrimitiveSchemaDefinition>
189+
{
190+
["confirm"] = new ElicitRequestParams.BooleanSchema
191+
{
192+
Description = "Confirm the action"
193+
}
194+
}
195+
}
196+
}, cancellationToken);
197+
```
198+
199+
#### Low-level API
200+
201+
For stateless servers or scenarios requiring manual control, throw <xref:ModelContextProtocol.Protocol.IncompleteResultException> with an elicitation input request. On retry, read the client's response from <xref:ModelContextProtocol.Protocol.RequestParams.InputResponses>:
202+
203+
```csharp
204+
[McpServerTool, Description("Tool that elicits via low-level MRTR")]
205+
public static string ElicitWithMrtr(
206+
McpServer server,
207+
RequestContext<CallToolRequestParams> context)
208+
{
209+
// On retry, process the client's elicitation response
210+
if (context.Params!.InputResponses?.TryGetValue("user_input", out var response) is true)
211+
{
212+
var elicitResult = response.ElicitationResult;
213+
return elicitResult?.Action == "accept"
214+
? $"User accepted: {elicitResult.Content?.FirstOrDefault().Value}"
215+
: "User declined.";
216+
}
217+
218+
if (!server.IsMrtrSupported)
219+
{
220+
return "This tool requires MRTR support.";
221+
}
222+
223+
// First call — request user input
224+
throw new IncompleteResultException(
225+
inputRequests: new Dictionary<string, InputRequest>
226+
{
227+
["user_input"] = InputRequest.ForElicitation(new ElicitRequestParams
228+
{
229+
Message = "Please confirm the action",
230+
RequestedSchema = new()
231+
{
232+
Properties = new Dictionary<string, ElicitRequestParams.PrimitiveSchemaDefinition>
233+
{
234+
["confirm"] = new ElicitRequestParams.BooleanSchema
235+
{
236+
Description = "Confirm the action"
237+
}
238+
}
239+
}
240+
})
241+
},
242+
requestState: "awaiting-confirmation");
243+
}
244+
```
245+
246+
> [!TIP]
247+
> See [Multi Round-Trip Requests (MRTR)](xref:mrtr) for the full protocol details, including multiple round trips, concurrent input requests, and the compatibility matrix.
248+
173249
### URL Elicitation Required Error
174250

175251
When a tool cannot proceed without first completing a URL-mode elicitation (for example, when third-party OAuth authorization is needed), and calling `ElicitAsync` is not practical (for example in [stateless](xref:stateless) mode where server-to-client requests are disabled), the server may throw a <xref:ModelContextProtocol.UrlElicitationRequiredException>. This is a specialized error (JSON-RPC error code `-32042`) that signals to the client that one or more URL-mode elicitations must be completed before the original request can be retried.

docs/concepts/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Install the SDK and build your first MCP client and server.
1818
| [Progress tracking](progress/progress.md) | Learn how to track progress for long-running operations through notification messages. |
1919
| [Cancellation](cancellation/cancellation.md) | Learn how to cancel in-flight MCP requests using cancellation tokens and notifications. |
2020
| [Tasks](tasks/tasks.md) | Learn how to use task-based execution for long-running operations that can be polled for status and results. |
21+
| [Multi Round-Trip Requests (MRTR)](mrtr/mrtr.md) | Learn how servers request client input during tool execution using input-required results and retries. |
2122

2223
### Client Features
2324

0 commit comments

Comments
 (0)