diff --git a/src/ModelContextProtocol/Client/McpClientOptions.cs b/src/ModelContextProtocol/Client/McpClientOptions.cs
index 9b070e92..de61f18f 100644
--- a/src/ModelContextProtocol/Client/McpClientOptions.cs
+++ b/src/ModelContextProtocol/Client/McpClientOptions.cs
@@ -7,25 +7,25 @@ namespace ModelContextProtocol.Client;
/// protocol version.
/// See the protocol specification for details on capability negotiation
///
-public record McpClientOptions
+public class McpClientOptions
{
///
/// Information about this client implementation.
///
- public required Implementation ClientInfo { get; init; }
+ public required Implementation ClientInfo { get; set; }
///
/// Client capabilities to advertise to the server.
///
- public ClientCapabilities? Capabilities { get; init; }
+ public ClientCapabilities? Capabilities { get; set; }
///
/// Protocol version to request from the server.
///
- public string ProtocolVersion { get; init; } = "2024-11-05";
+ public string ProtocolVersion { get; set; } = "2024-11-05";
///
/// Timeout for initialization sequence.
///
- public TimeSpan InitializationTimeout { get; init; } = TimeSpan.FromSeconds(60);
+ public TimeSpan InitializationTimeout { get; set; } = TimeSpan.FromSeconds(60);
}
diff --git a/src/ModelContextProtocol/Configuration/McpServerOptionsSetup.cs b/src/ModelContextProtocol/Configuration/McpServerOptionsSetup.cs
index 687a534b..c2ebbf62 100644
--- a/src/ModelContextProtocol/Configuration/McpServerOptionsSetup.cs
+++ b/src/ModelContextProtocol/Configuration/McpServerOptionsSetup.cs
@@ -25,22 +25,14 @@ public void Configure(McpServerOptions options)
// Configure the option's server information based on the current process,
// if it otherwise lacks server information.
- var assemblyName = (Assembly.GetEntryAssembly() ?? Assembly.GetCallingAssembly()).GetName();
- if (options.ServerInfo is not { } serverInfo ||
- serverInfo.Name is null ||
- serverInfo.Version is null)
+ if (options.ServerInfo is not { } serverInfo)
{
- options.ServerInfo = options.ServerInfo is null ?
- new()
- {
- Name = assemblyName.Name ?? "McpServer",
- Version = assemblyName.Version?.ToString() ?? "1.0.0",
- } :
- options.ServerInfo with
- {
- Name = options.ServerInfo.Name ?? assemblyName.Name ?? "McpServer",
- Version = options.ServerInfo.Version ?? assemblyName.Version?.ToString() ?? "1.0.0",
- };
+ var assemblyName = (Assembly.GetEntryAssembly() ?? Assembly.GetCallingAssembly()).GetName();
+ options.ServerInfo = new()
+ {
+ Name = assemblyName.Name ?? "McpServer",
+ Version = assemblyName.Version?.ToString() ?? "1.0.0",
+ };
}
// Collect all of the provided tools into a tools collection. If the options already has
@@ -55,14 +47,9 @@ options.ServerInfo with
if (!toolsCollection.IsEmpty)
{
- options.Capabilities = options.Capabilities is null ?
- new() { Tools = new() { ToolCollection = toolsCollection } } :
- options.Capabilities with
- {
- Tools = options.Capabilities.Tools is null ?
- new() { ToolCollection = toolsCollection } :
- options.Capabilities.Tools with { ToolCollection = toolsCollection },
- };
+ options.Capabilities ??= new();
+ options.Capabilities.Tools ??= new();
+ options.Capabilities.Tools.ToolCollection = toolsCollection;
}
// Apply custom server handlers.
diff --git a/src/ModelContextProtocol/Protocol/Types/Capabilities.cs b/src/ModelContextProtocol/Protocol/Types/Capabilities.cs
index a82afee0..9be4fdd5 100644
--- a/src/ModelContextProtocol/Protocol/Types/Capabilities.cs
+++ b/src/ModelContextProtocol/Protocol/Types/Capabilities.cs
@@ -7,62 +7,62 @@ namespace ModelContextProtocol.Protocol.Types;
/// Represents the capabilities that a client may support.
/// See the schema for details
///
-public record ClientCapabilities
+public class ClientCapabilities
{
///
/// Experimental, non-standard capabilities that the client supports.
///
[JsonPropertyName("experimental")]
- public Dictionary? Experimental { get; init; }
+ public Dictionary? Experimental { get; set; }
///
/// Present if the client supports listing roots.
///
[JsonPropertyName("roots")]
- public RootsCapability? Roots { get; init; }
+ public RootsCapability? Roots { get; set; }
///
/// Present if the client supports sampling from an LLM.
///
[JsonPropertyName("sampling")]
- public SamplingCapability? Sampling { get; init; }
+ public SamplingCapability? Sampling { get; set; }
}
///
/// Represents the roots capability configuration.
/// See the schema for details
///
-public record RootsCapability
+public class RootsCapability
{
///
/// Whether the client supports notifications for changes to the roots list.
///
[JsonPropertyName("listChanged")]
- public bool? ListChanged { get; init; }
+ public bool? ListChanged { get; set; }
/// Gets or sets the handler for sampling requests.
[JsonIgnore]
- public Func>? RootsHandler { get; init; }
+ public Func>? RootsHandler { get; set; }
}
///
/// Represents the sampling capability configuration.
/// See the schema for details
///
-public record SamplingCapability
+public class SamplingCapability
{
// Currently empty in the spec, but may be extended in the future
/// Gets or sets the handler for sampling requests.
[JsonIgnore]
- public Func>? SamplingHandler { get; init; }
+ public Func>? SamplingHandler { get; set; }
}
///
/// Represents the logging capability configuration.
/// See the schema for details
///
-public record LoggingCapability
+public class LoggingCapability
{
// Currently empty in the spec, but may be extended in the future
@@ -71,106 +71,106 @@ public record LoggingCapability
/// Gets or sets the handler for set logging level requests.
///
[JsonIgnore]
- public Func, CancellationToken, Task>? SetLoggingLevelHandler { get; init; }
+ public Func, CancellationToken, Task>? SetLoggingLevelHandler { get; set; }
}
///
/// Represents the prompts capability configuration.
/// See the schema for details
///
-public record PromptsCapability
+public class PromptsCapability
{
///
/// Whether this server supports notifications for changes to the prompt list.
///
[JsonPropertyName("listChanged")]
- public bool? ListChanged { get; init; }
+ public bool? ListChanged { get; set; }
///
/// Gets or sets the handler for list prompts requests.
///
[JsonIgnore]
- public Func, CancellationToken, Task>? ListPromptsHandler { get; init; }
+ public Func, CancellationToken, Task>? ListPromptsHandler { get; set; }
///
/// Gets or sets the handler for get prompt requests.
///
[JsonIgnore]
- public Func, CancellationToken, Task>? GetPromptHandler { get; init; }
+ public Func, CancellationToken, Task>? GetPromptHandler { get; set; }
}
///
/// Represents the resources capability configuration.
/// See the schema for details
///
-public record ResourcesCapability
+public class ResourcesCapability
{
///
/// Whether this server supports subscribing to resource updates.
///
[JsonPropertyName("subscribe")]
- public bool? Subscribe { get; init; }
+ public bool? Subscribe { get; set; }
///
/// Whether this server supports notifications for changes to the resource list.
///
[JsonPropertyName("listChanged")]
- public bool? ListChanged { get; init; }
+ public bool? ListChanged { get; set; }
///
/// Gets or sets the handler for list resource templates requests.
///
[JsonIgnore]
- public Func, CancellationToken, Task>? ListResourceTemplatesHandler { get; init; }
+ public Func, CancellationToken, Task>? ListResourceTemplatesHandler { get; set; }
///
/// Gets or sets the handler for list resources requests.
///
[JsonIgnore]
- public Func, CancellationToken, Task>? ListResourcesHandler { get; init; }
+ public Func, CancellationToken, Task>? ListResourcesHandler { get; set; }
///
/// Gets or sets the handler for read resources requests.
///
[JsonIgnore]
- public Func, CancellationToken, Task>? ReadResourceHandler { get; init; }
+ public Func, CancellationToken, Task>? ReadResourceHandler { get; set; }
///
/// Gets or sets the handler for subscribe to resources messages.
///
[JsonIgnore]
- public Func, CancellationToken, Task>? SubscribeToResourcesHandler { get; init; }
+ public Func, CancellationToken, Task>? SubscribeToResourcesHandler { get; set; }
///
/// Gets or sets the handler for unsubscribe from resources messages.
///
[JsonIgnore]
- public Func, CancellationToken, Task>? UnsubscribeFromResourcesHandler { get; init; }
+ public Func, CancellationToken, Task>? UnsubscribeFromResourcesHandler { get; set; }
}
///
/// Represents the tools capability configuration.
/// See the schema for details
///
-public record ToolsCapability
+public class ToolsCapability
{
///
/// Gets or sets whether this server supports notifications for changes to the tool list.
///
[JsonPropertyName("listChanged")]
- public bool? ListChanged { get; init; }
+ public bool? ListChanged { get; set; }
///
/// Gets or sets the handler for list tools requests.
///
[JsonIgnore]
- public Func, CancellationToken, Task>? ListToolsHandler { get; init; }
+ public Func, CancellationToken, Task>? ListToolsHandler { get; set; }
///
/// Gets or sets the handler for call tool requests.
///
[JsonIgnore]
- public Func, CancellationToken, Task>? CallToolHandler { get; init; }
+ public Func, CancellationToken, Task>? CallToolHandler { get; set; }
/// Gets or sets a collection of tools served by the server.
///
@@ -182,5 +182,5 @@ public record ToolsCapability
/// will be invoked as a fallback.
///
[JsonIgnore]
- public McpServerToolCollection? ToolCollection { get; init; }
+ public McpServerToolCollection? ToolCollection { get; set; }
}
\ No newline at end of file
diff --git a/src/ModelContextProtocol/Protocol/Types/Implementation.cs b/src/ModelContextProtocol/Protocol/Types/Implementation.cs
index 23f44552..81fe8c01 100644
--- a/src/ModelContextProtocol/Protocol/Types/Implementation.cs
+++ b/src/ModelContextProtocol/Protocol/Types/Implementation.cs
@@ -6,17 +6,17 @@ namespace ModelContextProtocol.Protocol.Types;
/// Describes the name and version of an MCP implementation.
/// See the schema for details
///
-public record Implementation
+public class Implementation
{
///
/// Name of the implementation.
///
[JsonPropertyName("name")]
- public required string Name { get; init; }
+ public required string Name { get; set; }
///
/// Version of the implementation.
///
[JsonPropertyName("version")]
- public required string Version { get; init; }
+ public required string Version { get; set; }
}
\ No newline at end of file
diff --git a/src/ModelContextProtocol/Protocol/Types/ServerCapabilities.cs b/src/ModelContextProtocol/Protocol/Types/ServerCapabilities.cs
index 15b486f6..6890674c 100644
--- a/src/ModelContextProtocol/Protocol/Types/ServerCapabilities.cs
+++ b/src/ModelContextProtocol/Protocol/Types/ServerCapabilities.cs
@@ -6,35 +6,35 @@ namespace ModelContextProtocol.Protocol.Types;
/// Represents the capabilities that a server may support.
/// See the schema for details
///
-public record ServerCapabilities
+public class ServerCapabilities
{
///
/// Experimental, non-standard capabilities that the server supports.
///
[JsonPropertyName("experimental")]
- public Dictionary? Experimental { get; init; }
+ public Dictionary? Experimental { get; set; }
///
/// Present if the server supports sending log messages to the client.
///
[JsonPropertyName("logging")]
- public LoggingCapability? Logging { get; init; }
+ public LoggingCapability? Logging { get; set; }
///
/// Present if the server offers any prompt templates.
///
[JsonPropertyName("prompts")]
- public PromptsCapability? Prompts { get; init; }
+ public PromptsCapability? Prompts { get; set; }
///
/// Present if the server offers any resources to read.
///
[JsonPropertyName("resources")]
- public ResourcesCapability? Resources { get; init; }
+ public ResourcesCapability? Resources { get; set; }
///
/// Present if the server offers any tools to call.
///
[JsonPropertyName("tools")]
- public ToolsCapability? Tools { get; init; }
+ public ToolsCapability? Tools { get; set; }
}
diff --git a/src/ModelContextProtocol/Server/McpServer.cs b/src/ModelContextProtocol/Server/McpServer.cs
index a7779947..64e332d2 100644
--- a/src/ModelContextProtocol/Server/McpServer.cs
+++ b/src/ModelContextProtocol/Server/McpServer.cs
@@ -263,25 +263,14 @@ private void SetToolsHandler(ref McpServerOptions options)
return tool.InvokeAsync(request, cancellationToken);
};
- toolsCapability = toolsCapability is null ?
- new()
- {
- CallToolHandler = callToolHandler,
- ListToolsHandler = listToolsHandler,
- ToolCollection = tools,
- ListChanged = true,
- } :
- toolsCapability with
- {
- CallToolHandler = callToolHandler,
- ListToolsHandler = listToolsHandler,
- ToolCollection = tools,
- ListChanged = true,
- };
-
- options.Capabilities = options.Capabilities is null ?
- new() { Tools = toolsCapability } :
- options.Capabilities with { Tools = toolsCapability };
+ toolsCapability ??= new();
+ toolsCapability.CallToolHandler = callToolHandler;
+ toolsCapability.ListToolsHandler = listToolsHandler;
+ toolsCapability.ToolCollection = tools;
+ toolsCapability.ListChanged = true;
+
+ options.Capabilities ??= new();
+ options.Capabilities.Tools = toolsCapability;
tools.Changed += delegate
{
diff --git a/src/ModelContextProtocol/Server/McpServerHandlers.cs b/src/ModelContextProtocol/Server/McpServerHandlers.cs
index 32deca49..e472a7ae 100644
--- a/src/ModelContextProtocol/Server/McpServerHandlers.cs
+++ b/src/ModelContextProtocol/Server/McpServerHandlers.cs
@@ -72,91 +72,47 @@ internal void OverwriteWithSetHandlers(McpServerOptions options)
PromptsCapability? promptsCapability = options.Capabilities?.Prompts;
if (ListPromptsHandler is not null || GetPromptHandler is not null)
{
- promptsCapability = promptsCapability is null ?
- new()
- {
- ListPromptsHandler = ListPromptsHandler,
- GetPromptHandler = GetPromptHandler,
- } :
- promptsCapability with
- {
- ListPromptsHandler = ListPromptsHandler ?? promptsCapability.ListPromptsHandler,
- GetPromptHandler = GetPromptHandler ?? promptsCapability.GetPromptHandler,
- };
+ promptsCapability ??= new();
+ promptsCapability.ListPromptsHandler = ListPromptsHandler ?? promptsCapability.ListPromptsHandler;
+ promptsCapability.GetPromptHandler = GetPromptHandler ?? promptsCapability.GetPromptHandler;
}
ResourcesCapability? resourcesCapability = options.Capabilities?.Resources;
if (ListResourcesHandler is not null ||
ReadResourceHandler is not null)
{
- resourcesCapability = resourcesCapability is null ?
- new()
- {
- ListResourceTemplatesHandler = ListResourceTemplatesHandler,
- ListResourcesHandler = ListResourcesHandler,
- ReadResourceHandler = ReadResourceHandler
- } :
- resourcesCapability with
- {
- ListResourceTemplatesHandler = ListResourceTemplatesHandler ?? resourcesCapability.ListResourceTemplatesHandler,
- ListResourcesHandler = ListResourcesHandler ?? resourcesCapability.ListResourcesHandler,
- ReadResourceHandler = ReadResourceHandler ?? resourcesCapability.ReadResourceHandler
- };
+ resourcesCapability ??= new();
+ resourcesCapability.ListResourceTemplatesHandler = ListResourceTemplatesHandler ?? resourcesCapability.ListResourceTemplatesHandler;
+ resourcesCapability.ListResourcesHandler = ListResourcesHandler ?? resourcesCapability.ListResourcesHandler;
+ resourcesCapability.ReadResourceHandler = ReadResourceHandler ?? resourcesCapability.ReadResourceHandler;
if (SubscribeToResourcesHandler is not null || UnsubscribeFromResourcesHandler is not null)
{
- resourcesCapability = resourcesCapability with
- {
- SubscribeToResourcesHandler = SubscribeToResourcesHandler ?? resourcesCapability.SubscribeToResourcesHandler,
- UnsubscribeFromResourcesHandler = UnsubscribeFromResourcesHandler ?? resourcesCapability.UnsubscribeFromResourcesHandler,
- Subscribe = true
- };
+ resourcesCapability.SubscribeToResourcesHandler = SubscribeToResourcesHandler ?? resourcesCapability.SubscribeToResourcesHandler;
+ resourcesCapability.UnsubscribeFromResourcesHandler = UnsubscribeFromResourcesHandler ?? resourcesCapability.UnsubscribeFromResourcesHandler;
+ resourcesCapability.Subscribe = true;
}
}
ToolsCapability? toolsCapability = options.Capabilities?.Tools;
if (ListToolsHandler is not null || CallToolHandler is not null)
{
- toolsCapability = toolsCapability is null ?
- new()
- {
- ListToolsHandler = ListToolsHandler,
- CallToolHandler = CallToolHandler,
- } :
- toolsCapability with
- {
- ListToolsHandler = ListToolsHandler ?? toolsCapability.ListToolsHandler,
- CallToolHandler = CallToolHandler ?? toolsCapability.CallToolHandler,
- };
+ toolsCapability ??= new();
+ toolsCapability.ListToolsHandler = ListToolsHandler ?? toolsCapability.ListToolsHandler;
+ toolsCapability.CallToolHandler = CallToolHandler ?? toolsCapability.CallToolHandler;
}
LoggingCapability? loggingCapability = options.Capabilities?.Logging;
if (SetLoggingLevelHandler is not null)
{
- loggingCapability = loggingCapability is null ?
- new()
- {
- SetLoggingLevelHandler = SetLoggingLevelHandler,
- } :
- loggingCapability with
- {
- SetLoggingLevelHandler = SetLoggingLevelHandler ?? loggingCapability.SetLoggingLevelHandler,
- };
+ loggingCapability ??= new();
+ loggingCapability.SetLoggingLevelHandler = SetLoggingLevelHandler;
}
- options.Capabilities = options.Capabilities is null ?
- new()
- {
- Prompts = promptsCapability,
- Resources = resourcesCapability,
- Tools = toolsCapability,
- } :
- options.Capabilities with
- {
- Prompts = promptsCapability,
- Resources = resourcesCapability,
- Tools = toolsCapability,
- };
+ options.Capabilities ??= new();
+ options.Capabilities.Prompts = promptsCapability;
+ options.Capabilities.Resources = resourcesCapability;
+ options.Capabilities.Tools = toolsCapability;
options.GetCompletionHandler = GetCompletionHandler ?? options.GetCompletionHandler;
}
diff --git a/tests/ModelContextProtocol.Tests/SseServerIntegrationTestFixture.cs b/tests/ModelContextProtocol.Tests/SseServerIntegrationTestFixture.cs
index 2702ed83..75c727d1 100644
--- a/tests/ModelContextProtocol.Tests/SseServerIntegrationTestFixture.cs
+++ b/tests/ModelContextProtocol.Tests/SseServerIntegrationTestFixture.cs
@@ -15,7 +15,6 @@ public class SseServerIntegrationTestFixture : IAsyncDisposable
private readonly DelegatingTestOutputHelper _delegatingTestOutputHelper = new();
private readonly ILoggerFactory _redirectingLoggerFactory;
- public McpClientOptions DefaultOptions { get; }
public McpServerConfig DefaultConfig { get; }
public SseServerIntegrationTestFixture()
@@ -26,11 +25,6 @@ public SseServerIntegrationTestFixture()
builder.AddProvider(new XunitLoggerProvider(_delegatingTestOutputHelper));
});
- DefaultOptions = new()
- {
- ClientInfo = new() { Name = "IntegrationTestClient", Version = "1.0.0" },
- };
-
DefaultConfig = new McpServerConfig
{
Id = "test_server",
@@ -43,6 +37,11 @@ public SseServerIntegrationTestFixture()
_serverTask = Program.MainAsync([], _redirectingLoggerFactory, _stopCts.Token);
}
+ public static McpClientOptions CreateDefaultClientOptions() => new()
+ {
+ ClientInfo = new() { Name = "IntegrationTestClient", Version = "1.0.0" },
+ };
+
public void Initialize(ITestOutputHelper output)
{
_delegatingTestOutputHelper.CurrentTestOutputHelper = output;
diff --git a/tests/ModelContextProtocol.Tests/SseServerIntegrationTests.cs b/tests/ModelContextProtocol.Tests/SseServerIntegrationTests.cs
index 767005ea..b834f843 100644
--- a/tests/ModelContextProtocol.Tests/SseServerIntegrationTests.cs
+++ b/tests/ModelContextProtocol.Tests/SseServerIntegrationTests.cs
@@ -19,7 +19,7 @@ private Task GetClientAsync(McpClientOptions? options = null)
{
return McpClientFactory.CreateAsync(
_fixture.DefaultConfig,
- options ?? _fixture.DefaultOptions,
+ options ?? SseServerIntegrationTestFixture.CreateDefaultClientOptions(),
loggerFactory: LoggerFactory);
}
@@ -201,28 +201,22 @@ public async Task Sampling_Sse_TestServer()
// Set up the sampling handler
int samplingHandlerCalls = 0;
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
- var options = _fixture.DefaultOptions with
+ var options = SseServerIntegrationTestFixture.CreateDefaultClientOptions();
+ options.Capabilities ??= new();
+ options.Capabilities.Sampling ??= new();
+ options.Capabilities.Sampling.SamplingHandler = async (_, _) =>
{
- Capabilities = new()
+ samplingHandlerCalls++;
+ return new CreateMessageResult
{
- Sampling = new()
+ Model = "test-model",
+ Role = "assistant",
+ Content = new Content
{
- SamplingHandler = async (_, _) =>
- {
- samplingHandlerCalls++;
- return new CreateMessageResult
- {
- Model = "test-model",
- Role = "assistant",
- Content = new Content
- {
- Type = "text",
- Text = "Test response"
- }
- };
- }
+ Type = "text",
+ Text = "Test response"
}
- }
+ };
};
var client = await GetClientAsync(options);
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously