Skip to content
Open
2 changes: 1 addition & 1 deletion samples/EverythingServer/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ await ctx.Server.SampleAsync([
new ChatMessage(ChatRole.System, "You are a helpful test server"),
new ChatMessage(ChatRole.User, $"Resource {uri}, context: A new subscription was started"),
],
options: new ChatOptions
chatOptions: new ChatOptions
{
MaxOutputTokens = 100,
Temperature = 0.7f,
Expand Down
2 changes: 1 addition & 1 deletion samples/EverythingServer/Tools/SampleLlmTool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public static async Task<string> SampleLLM(
CancellationToken cancellationToken)
{
var samplingParams = CreateRequestSamplingParams(prompt ?? string.Empty, "sampleLLM", maxTokens);
var sampleResult = await server.SampleAsync(samplingParams, cancellationToken);
var sampleResult = await server.SampleAsync(samplingParams, cancellationToken: cancellationToken);

return $"LLM sampling result: {sampleResult.Content.OfType<TextContentBlock>().FirstOrDefault()?.Text}";
}
Expand Down
2 changes: 1 addition & 1 deletion samples/TestServerWithHosting/Tools/SampleLlmTool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public static async Task<string> SampleLLM(
CancellationToken cancellationToken)
{
var samplingParams = CreateRequestSamplingParams(prompt ?? string.Empty, "sampleLLM", maxTokens);
var sampleResult = await thisServer.SampleAsync(samplingParams, cancellationToken);
var sampleResult = await thisServer.SampleAsync(samplingParams, cancellationToken: cancellationToken);

return $"LLM sampling result: {sampleResult.Content.OfType<TextContentBlock>().FirstOrDefault()?.Text}";
}
Expand Down
124 changes: 76 additions & 48 deletions src/ModelContextProtocol.Core/Client/McpClient.Methods.cs

Large diffs are not rendered by default.

36 changes: 18 additions & 18 deletions src/ModelContextProtocol.Core/Client/McpClientExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public static class McpClientExtensions
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.PingAsync)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public static Task PingAsync(this IMcpClient client, CancellationToken cancellationToken = default)
=> AsClientOrThrow(client).PingAsync(cancellationToken);
=> AsClientOrThrow(client).PingAsync(null, cancellationToken).AsTask();

/// <summary>
/// Retrieves a list of available tools from the server.
Expand Down Expand Up @@ -86,7 +86,7 @@ public static ValueTask<IList<McpClientTool>> ListToolsAsync(
this IMcpClient client,
JsonSerializerOptions? serializerOptions = null,
CancellationToken cancellationToken = default)
=> AsClientOrThrow(client).ListToolsAsync(serializerOptions, cancellationToken);
=> AsClientOrThrow(client).ListToolsAsync(new RequestOptions { JsonSerializerOptions = serializerOptions }, cancellationToken);

/// <summary>
/// Creates an enumerable for asynchronously enumerating all available tools from the server.
Expand Down Expand Up @@ -126,7 +126,7 @@ public static IAsyncEnumerable<McpClientTool> EnumerateToolsAsync(
this IMcpClient client,
JsonSerializerOptions? serializerOptions = null,
CancellationToken cancellationToken = default)
=> AsClientOrThrow(client).EnumerateToolsAsync(serializerOptions, cancellationToken);
=> AsClientOrThrow(client).EnumerateToolsAsync(new RequestOptions { JsonSerializerOptions = serializerOptions }, cancellationToken);

/// <summary>
/// Retrieves a list of available prompts from the server.
Expand All @@ -149,7 +149,7 @@ public static IAsyncEnumerable<McpClientTool> EnumerateToolsAsync(
[EditorBrowsable(EditorBrowsableState.Never)]
public static ValueTask<IList<McpClientPrompt>> ListPromptsAsync(
this IMcpClient client, CancellationToken cancellationToken = default)
=> AsClientOrThrow(client).ListPromptsAsync(cancellationToken);
=> AsClientOrThrow(client).ListPromptsAsync(null, cancellationToken);

/// <summary>
/// Creates an enumerable for asynchronously enumerating all available prompts from the server.
Expand Down Expand Up @@ -182,7 +182,7 @@ public static ValueTask<IList<McpClientPrompt>> ListPromptsAsync(
[EditorBrowsable(EditorBrowsableState.Never)]
public static IAsyncEnumerable<McpClientPrompt> EnumeratePromptsAsync(
this IMcpClient client, CancellationToken cancellationToken = default)
=> AsClientOrThrow(client).EnumeratePromptsAsync(cancellationToken);
=> AsClientOrThrow(client).EnumeratePromptsAsync(null, cancellationToken);

/// <summary>
/// Retrieves a specific prompt from the MCP server.
Expand Down Expand Up @@ -217,7 +217,7 @@ public static ValueTask<GetPromptResult> GetPromptAsync(
IReadOnlyDictionary<string, object?>? arguments = null,
JsonSerializerOptions? serializerOptions = null,
CancellationToken cancellationToken = default)
=> AsClientOrThrow(client).GetPromptAsync(name, arguments, serializerOptions, cancellationToken);
=> AsClientOrThrow(client).GetPromptAsync(name, arguments, new RequestOptions { JsonSerializerOptions = serializerOptions }, cancellationToken);

/// <summary>
/// Retrieves a list of available resource templates from the server.
Expand All @@ -240,7 +240,7 @@ public static ValueTask<GetPromptResult> GetPromptAsync(
[EditorBrowsable(EditorBrowsableState.Never)]
public static ValueTask<IList<McpClientResourceTemplate>> ListResourceTemplatesAsync(
this IMcpClient client, CancellationToken cancellationToken = default)
=> AsClientOrThrow(client).ListResourceTemplatesAsync(cancellationToken);
=> AsClientOrThrow(client).ListResourceTemplatesAsync(null, cancellationToken);

/// <summary>
/// Creates an enumerable for asynchronously enumerating all available resource templates from the server.
Expand Down Expand Up @@ -273,7 +273,7 @@ public static ValueTask<IList<McpClientResourceTemplate>> ListResourceTemplatesA
[EditorBrowsable(EditorBrowsableState.Never)]
public static IAsyncEnumerable<McpClientResourceTemplate> EnumerateResourceTemplatesAsync(
this IMcpClient client, CancellationToken cancellationToken = default)
=> AsClientOrThrow(client).EnumerateResourceTemplatesAsync(cancellationToken);
=> AsClientOrThrow(client).EnumerateResourceTemplatesAsync(null, cancellationToken);

/// <summary>
/// Retrieves a list of available resources from the server.
Expand Down Expand Up @@ -308,7 +308,7 @@ public static IAsyncEnumerable<McpClientResourceTemplate> EnumerateResourceTempl
[EditorBrowsable(EditorBrowsableState.Never)]
public static ValueTask<IList<McpClientResource>> ListResourcesAsync(
this IMcpClient client, CancellationToken cancellationToken = default)
=> AsClientOrThrow(client).ListResourcesAsync(cancellationToken);
=> AsClientOrThrow(client).ListResourcesAsync(null, cancellationToken);

/// <summary>
/// Creates an enumerable for asynchronously enumerating all available resources from the server.
Expand Down Expand Up @@ -341,7 +341,7 @@ public static ValueTask<IList<McpClientResource>> ListResourcesAsync(
[EditorBrowsable(EditorBrowsableState.Never)]
public static IAsyncEnumerable<McpClientResource> EnumerateResourcesAsync(
this IMcpClient client, CancellationToken cancellationToken = default)
=> AsClientOrThrow(client).EnumerateResourcesAsync(cancellationToken);
=> AsClientOrThrow(client).EnumerateResourcesAsync(null, cancellationToken);

/// <summary>
/// Reads a resource from the server.
Expand All @@ -356,7 +356,7 @@ public static IAsyncEnumerable<McpClientResource> EnumerateResourcesAsync(
[EditorBrowsable(EditorBrowsableState.Never)]
public static ValueTask<ReadResourceResult> ReadResourceAsync(
this IMcpClient client, string uri, CancellationToken cancellationToken = default)
=> AsClientOrThrow(client).ReadResourceAsync(uri, cancellationToken);
=> AsClientOrThrow(client).ReadResourceAsync(uri, null, cancellationToken);

/// <summary>
/// Reads a resource from the server.
Expand All @@ -370,7 +370,7 @@ public static ValueTask<ReadResourceResult> ReadResourceAsync(
[EditorBrowsable(EditorBrowsableState.Never)]
public static ValueTask<ReadResourceResult> ReadResourceAsync(
this IMcpClient client, Uri uri, CancellationToken cancellationToken = default)
=> AsClientOrThrow(client).ReadResourceAsync(uri, cancellationToken);
=> AsClientOrThrow(client).ReadResourceAsync(uri, null, cancellationToken);

/// <summary>
/// Reads a resource from the server.
Expand All @@ -386,7 +386,7 @@ public static ValueTask<ReadResourceResult> ReadResourceAsync(
[EditorBrowsable(EditorBrowsableState.Never)]
public static ValueTask<ReadResourceResult> ReadResourceAsync(
this IMcpClient client, string uriTemplate, IReadOnlyDictionary<string, object?> arguments, CancellationToken cancellationToken = default)
=> AsClientOrThrow(client).ReadResourceAsync(uriTemplate, arguments, cancellationToken);
=> AsClientOrThrow(client).ReadResourceAsync(uriTemplate, arguments, null, cancellationToken);

/// <summary>
/// Requests completion suggestions for a prompt argument or resource reference.
Expand Down Expand Up @@ -450,7 +450,7 @@ public static ValueTask<CompleteResult> CompleteAsync(this IMcpClient client, Re
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.SubscribeToResourceAsync)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public static Task SubscribeToResourceAsync(this IMcpClient client, string uri, CancellationToken cancellationToken = default)
=> AsClientOrThrow(client).SubscribeToResourceAsync(uri, cancellationToken);
=> AsClientOrThrow(client).SubscribeToResourceAsync(uri, null, cancellationToken);

/// <summary>
/// Subscribes to a resource on the server to receive notifications when it changes.
Expand Down Expand Up @@ -479,7 +479,7 @@ public static Task SubscribeToResourceAsync(this IMcpClient client, string uri,
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.SubscribeToResourceAsync)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public static Task SubscribeToResourceAsync(this IMcpClient client, Uri uri, CancellationToken cancellationToken = default)
=> AsClientOrThrow(client).SubscribeToResourceAsync(uri, cancellationToken);
=> AsClientOrThrow(client).SubscribeToResourceAsync(uri, null, cancellationToken);

/// <summary>
/// Unsubscribes from a resource on the server to stop receiving notifications about its changes.
Expand Down Expand Up @@ -508,7 +508,7 @@ public static Task SubscribeToResourceAsync(this IMcpClient client, Uri uri, Can
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.UnsubscribeFromResourceAsync)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public static Task UnsubscribeFromResourceAsync(this IMcpClient client, string uri, CancellationToken cancellationToken = default)
=> AsClientOrThrow(client).UnsubscribeFromResourceAsync(uri, cancellationToken);
=> AsClientOrThrow(client).UnsubscribeFromResourceAsync(uri, null, cancellationToken);

/// <summary>
/// Unsubscribes from a resource on the server to stop receiving notifications about its changes.
Expand Down Expand Up @@ -536,7 +536,7 @@ public static Task UnsubscribeFromResourceAsync(this IMcpClient client, string u
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.UnsubscribeFromResourceAsync)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public static Task UnsubscribeFromResourceAsync(this IMcpClient client, Uri uri, CancellationToken cancellationToken = default)
=> AsClientOrThrow(client).UnsubscribeFromResourceAsync(uri, cancellationToken);
=> AsClientOrThrow(client).UnsubscribeFromResourceAsync(uri, null, cancellationToken);

/// <summary>
/// Invokes a tool on the server.
Expand Down Expand Up @@ -582,7 +582,7 @@ public static ValueTask<CallToolResult> CallToolAsync(
IProgress<ProgressNotificationValue>? progress = null,
JsonSerializerOptions? serializerOptions = null,
CancellationToken cancellationToken = default)
=> AsClientOrThrow(client).CallToolAsync(toolName, arguments, progress, serializerOptions, cancellationToken);
=> AsClientOrThrow(client).CallToolAsync(toolName, arguments, progress, new RequestOptions { JsonSerializerOptions = serializerOptions }, cancellationToken);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
#pragma warning disable CS0618 // Type or member is obsolete
Expand Down
2 changes: 1 addition & 1 deletion src/ModelContextProtocol.Core/Client/McpClientPrompt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,6 @@ public async ValueTask<GetPromptResult> GetAsync(
arguments as IReadOnlyDictionary<string, object?> ??
arguments?.ToDictionary();

return await _client.GetPromptAsync(ProtocolPrompt.Name, argDict, serializerOptions, cancellationToken: cancellationToken).ConfigureAwait(false);
return await _client.GetPromptAsync(ProtocolPrompt.Name, argDict, new RequestOptions(){JsonSerializerOptions = serializerOptions}, cancellationToken).ConfigureAwait(false);
}
}
4 changes: 2 additions & 2 deletions src/ModelContextProtocol.Core/Client/McpClientResource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,10 @@ public McpClientResource(McpClient client, Resource resource)
/// <returns>A <see cref="ValueTask{ReadResourceResult}"/> containing the resource's result with content and messages.</returns>
/// <remarks>
/// <para>
/// This is a convenience method that internally calls <see cref="McpClient.ReadResourceAsync(string, CancellationToken)"/>.
/// This is a convenience method that internally calls <see cref="McpClient.ReadResourceAsync(string, RequestOptions, CancellationToken)"/>.
/// </para>
/// </remarks>
public ValueTask<ReadResourceResult> ReadAsync(
CancellationToken cancellationToken = default) =>
_client.ReadResourceAsync(Uri, cancellationToken);
_client.ReadResourceAsync(Uri, cancellationToken: cancellationToken);
}
Original file line number Diff line number Diff line change
Expand Up @@ -84,5 +84,5 @@ public McpClientResourceTemplate(McpClient client, ResourceTemplate resourceTemp
public ValueTask<ReadResourceResult> ReadAsync(
IReadOnlyDictionary<string, object?> arguments,
CancellationToken cancellationToken = default) =>
_client.ReadResourceAsync(UriTemplate, arguments, cancellationToken);
_client.ReadResourceAsync(UriTemplate, arguments, cancellationToken: cancellationToken);
}
10 changes: 9 additions & 1 deletion src/ModelContextProtocol.Core/Client/McpClientTool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,15 @@ public ValueTask<CallToolResult> CallAsync(
IProgress<ProgressNotificationValue>? progress = null,
JsonSerializerOptions? serializerOptions = null,
CancellationToken cancellationToken = default) =>
_client.CallToolAsync(ProtocolTool.Name, arguments, progress, serializerOptions, cancellationToken);
_client.CallToolAsync(
ProtocolTool.Name,
arguments,
progress,
serializerOptions is null ? null : new RequestOptions
{
JsonSerializerOptions = serializerOptions
},
cancellationToken);

/// <summary>
/// Creates a new instance of the tool but modified to return the specified name from its <see cref="Name"/> property.
Expand Down
2 changes: 1 addition & 1 deletion src/ModelContextProtocol.Core/McpEndpointExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ public static Task NotifyProgressAsync(
ProgressToken progressToken,
ProgressNotificationValue progress,
CancellationToken cancellationToken = default)
=> AsSessionOrThrow(endpoint).NotifyProgressAsync(progressToken, progress, cancellationToken);
=> AsSessionOrThrow(endpoint).NotifyProgressAsync(progressToken, progress, cancellationToken: cancellationToken);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
#pragma warning disable CS0618 // Type or member is obsolete
Expand Down
1 change: 1 addition & 0 deletions src/ModelContextProtocol.Core/McpJsonUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ internal static bool IsValidMcpToolSchema(JsonElement element)
[JsonSerializable(typeof(ListRootsResult))]
[JsonSerializable(typeof(ListToolsRequestParams))]
[JsonSerializable(typeof(ListToolsResult))]
[JsonSerializable(typeof(PingRequestParams))]
[JsonSerializable(typeof(PingResult))]
[JsonSerializable(typeof(ReadResourceRequestParams))]
[JsonSerializable(typeof(ReadResourceResult))]
Expand Down
3 changes: 3 additions & 0 deletions src/ModelContextProtocol.Core/McpSession.Methods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ internal Task SendNotificationAsync<TParameters>(
/// </summary>
/// <param name="progressToken">The token that identifies the operation for which progress is being reported.</param>
/// <param name="progress">The progress update to send, containing information such as percentage complete or status message.</param>
/// <param name="options">Optional request options including metadata, serialization settings, and progress tracking.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
/// <returns>A task representing the completion of the notification operation (not the operation being tracked).</returns>
/// <exception cref="ArgumentNullException">The current session instance is <see langword="null"/>.</exception>
Expand All @@ -168,6 +169,7 @@ internal Task SendNotificationAsync<TParameters>(
public Task NotifyProgressAsync(
ProgressToken progressToken,
ProgressNotificationValue progress,
RequestOptions? options = null,
CancellationToken cancellationToken = default)
{
return SendNotificationAsync(
Expand All @@ -176,6 +178,7 @@ public Task NotifyProgressAsync(
{
ProgressToken = progressToken,
Progress = progress,
Meta = options?.Meta,
},
McpJsonUtilities.JsonContext.Default.ProgressNotificationParams,
cancellationToken);
Expand Down
11 changes: 11 additions & 0 deletions src/ModelContextProtocol.Core/Protocol/PingRequestParams.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace ModelContextProtocol.Protocol;

/// <summary>
/// Represents the parameters used with a <see cref="RequestMethods.Ping"/> request to verify
/// server connectivity.
/// </summary>
/// <remarks>
/// The server responds with a <see cref="PingResult"/>.
/// See the <see href="https://github.com/modelcontextprotocol/specification/blob/main/schema/">schema</see> for details.
/// </remarks>
public sealed class PingRequestParams : RequestParams;
18 changes: 1 addition & 17 deletions src/ModelContextProtocol.Core/Protocol/RequestParams.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ private protected RequestParams()
public JsonObject? Meta { get; set; }

/// <summary>
/// Gets or sets an opaque token that will be attached to any subsequent progress notifications.
/// Gets the opaque token that will be attached to any subsequent progress notifications.
/// </summary>
[JsonIgnore]
public ProgressToken? ProgressToken
Expand All @@ -48,21 +48,5 @@ public ProgressToken? ProgressToken

return null;
}
set
{
if (value is null)
{
Meta?.Remove("progressToken");
}
else
{
(Meta ??= [])["progressToken"] = value.Value.Token switch
{
string s => JsonValue.Create(s),
long l => JsonValue.Create(l),
_ => throw new InvalidOperationException("ProgressToken must be a string or a long.")
};
}
}
}
}
6 changes: 3 additions & 3 deletions src/ModelContextProtocol.Core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ foreach (var tool in await client.ListToolsAsync())
var result = await client.CallToolAsync(
"echo",
new Dictionary<string, object?>() { ["message"] = "Hello MCP!" },
cancellationToken:CancellationToken.None);
cancellationToken: CancellationToken.None);

// echo always returns one and only one text content object
Console.WriteLine(result.Content.First(c => c.Type == "text").Text);
Expand Down Expand Up @@ -83,13 +83,13 @@ using System.ComponentModel;
var serverOptions = new McpServerOptions();

// Add tools directly
serverOptions.Capabilities.Tools = new()
serverOptions.Capabilities.Tools = new()
{
ListChanged = true,
ToolCollection = [
McpServerTool.Create((string message) => $"hello {message}", new()
{
Name = "echo",
Name = "echo",
Description = "Echoes the message back to the client."
})
]
Expand Down
Loading
Loading