-
Notifications
You must be signed in to change notification settings - Fork 571
Add request options bag to high level requests and include Meta #970
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
| Name = toolName, | ||
| Arguments = ToArgumentsDictionary(arguments, serializerOptions), | ||
| Meta = meta, | ||
| // Must set ProgressToken after Meta |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems like a footgun that maybe we should find a way to avoid.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, the order in which properties are set should never affect behavior.
Why does the order matter?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR introduces a RequestOptions class to consolidate common optional parameters (Meta, JsonSerializerOptions, and ProgressToken) across MCP client and server request methods. This refactoring reduces method signature complexity and enables setting the _meta field in requests, which is needed for new MCP spec features like SEP-1686 (Tasks).
Key Changes
- Added new
RequestOptionsclass to hold optional request parameters - Updated all client and server request method signatures to accept
RequestOptionsinstead of individual parameters - Created
PingRequestParamsprotocol class for structured ping requests - Updated tests to use the new method signatures with named parameters or null for options
Reviewed Changes
Copilot reviewed 32 out of 33 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/ModelContextProtocol.Core/RequestOptions.cs | New options bag class with Meta, JsonSerializerOptions, and ProgressToken properties |
| src/ModelContextProtocol.Core/Protocol/PingRequestParams.cs | New protocol parameter class for ping requests |
| src/ModelContextProtocol.Core/Client/McpClient.Methods.cs | Updated all client methods to accept RequestOptions and properly set Meta in request params |
| src/ModelContextProtocol.Core/Server/McpServer.Methods.cs | Updated SampleAsync and RequestRootsAsync to accept RequestOptions |
| src/ModelContextProtocol.Core/Client/McpClientExtensions.cs | Updated extension methods to wrap individual parameters in RequestOptions |
| src/ModelContextProtocol.Core/Server/McpServerExtensions.cs | Updated extension methods to forward calls with named parameters |
| src/ModelContextProtocol.Core/Client/McpClient*.cs | Updated client wrapper classes to construct RequestOptions when calling client methods |
| src/ModelContextProtocol.Core/McpJsonUtilities.cs | Added PingRequestParams to source generation context |
| tests/**/*.cs | Updated all test call sites to use new signatures with null or named parameters |
| samples/**/*.cs | Updated sample code to use named parameters for cancellationToken |
| IMcpClient client = mockClient.Object; | ||
|
|
||
| var result = await client.ReadResourceAsync("mcp://resource/1", TestContext.Current.CancellationToken); | ||
| var result = await client.ReadResourceAsync("mcp://resource/1", cancellationToken: TestContext.Current.CancellationToken); |
Copilot
AI
Nov 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Call to obsolete method ReadResourceAsync.
| var result = await client.ReadResourceAsync("mcp://resource/1", cancellationToken: TestContext.Current.CancellationToken); | |
| var result = await ((McpClient)client).ReadResourceAsync("mcp://resource/1", cancellationToken: TestContext.Current.CancellationToken); |
|
|
||
| var tool = (await client.ListToolsAsync(options, TestContext.Current.CancellationToken)).First(); | ||
| var tool = (await client.ListToolsAsync(new RequestOptions { JsonSerializerOptions = options }, TestContext.Current.CancellationToken)).First(); | ||
| var originalName = tool.Name; |
Copilot
AI
Nov 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
| ProtocolTool.Name, | ||
| arguments, | ||
| progress, | ||
| new RequestOptions |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It'd be nice to avoid allocating the RequestOptions when serializerOptions is null (which is expected to be the common case)
| /// <summary> | ||
| /// Initializes a new instance of the <see cref="RequestOptions"/> class with the specified metadata. | ||
| /// </summary> | ||
| /// <param name="meta">Optional metadata to include in the request.</param> | ||
| public RequestOptions(JsonObject? meta) | ||
| { | ||
| Meta = meta; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Initializes a new instance of the <see cref="RequestOptions"/> class with the specified options. | ||
| /// </summary> | ||
| /// <param name="meta">Optional metadata to include in the request.</param> | ||
| /// <param name="jsonSerializerOptions">The JSON serializer options to use.</param> | ||
| /// <param name="progressToken">The progress token for tracking operations.</param> | ||
| public RequestOptions(JsonObject? meta = null, JsonSerializerOptions? jsonSerializerOptions = null, ProgressToken? progressToken = null) | ||
| { | ||
| Meta = meta; | ||
| JsonSerializerOptions = jsonSerializerOptions; | ||
| ProgressToken = progressToken; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are these constructors necessary?
| /// <summary> | ||
| /// Gets a default instance with all properties set to null. | ||
| /// </summary> | ||
| public static RequestOptions Default { get; } = new(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any code in the process could do:
RequestOptions.Default.Meta = new();or the like with any of the properties, such that the properties would no longer be null.
This property should be removed.
(Alternatively, you could modify the other properties to all throw if ReferenceEquals(this, Default), but I don't think it's worthwhile. Default should never be needed by consumers, as they should always be able to just pass in null for the options.)
| { | ||
| ThrowIfRootsUnsupported(); | ||
|
|
||
| if (options?.Meta is not null) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this kind of merging will need to be done in more than one place, we should have a helper for it.
Motivation and Context
This PR adds the ability to set fields of the
_metaparameter in requests with the high-level request methods.It also refactored these methods to move several parameters common in request methods -- JsonSerializerOptions, ProgressToken, and the new Meta field -- to an options bag to make these signatures more concise.
How Has This Been Tested?
All tests pass with the revised method signatures.
Breaking Changes
This will be breaking (as currently implemented) for users that specify any of these (uncommonly used) parameters.
Types of changes
Checklist
Additional context
Some new features in the 2025-11-25 version of the MCP spec require setting and reading fields of
_meta, e.g. SEP-1686: Tasks. This change will make it easier for users to access these new features.