Skip to content

Commit 7352efb

Browse files
authored
Merge branch 'main' into dotnet-everything
2 parents 3be1849 + d21d933 commit 7352efb

Some content is hidden

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

47 files changed

+455
-485
lines changed

samples/QuickstartWeatherServer/Tools/WeatherTools.cs

-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using ModelContextProtocol;
22
using ModelContextProtocol.Server;
33
using System.ComponentModel;
4-
using System.Net.Http.Json;
54
using System.Text.Json;
65

76
namespace QuickstartWeatherServer.Tools;

src/ModelContextProtocol/Client/IMcpClient.cs

+9-7
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,21 @@ namespace ModelContextProtocol.Client;
88
public interface IMcpClient : IMcpEndpoint
99
{
1010
/// <summary>
11-
/// Gets the capabilities supported by the server.
11+
/// Gets the capabilities supported by the connected server.
1212
/// </summary>
13-
ServerCapabilities? ServerCapabilities { get; }
13+
ServerCapabilities ServerCapabilities { get; }
1414

1515
/// <summary>
16-
/// Gets the version and implementation information of the server.
16+
/// Gets the implementation information of the connected server.
1717
/// </summary>
18-
Implementation? ServerInfo { get; }
18+
Implementation ServerInfo { get; }
1919

2020
/// <summary>
21-
/// Instructions describing how to use the server and its features.
22-
/// This can be used by clients to improve the LLM's understanding of available tools, resources, etc.
23-
/// It can be thought of like a "hint" to the model. For example, this information MAY be added to the system prompt.
21+
/// Gets any instructions describing how to use the connected server and its features.
2422
/// </summary>
23+
/// <remarks>
24+
/// This can be used by clients to improve an LLM's understanding of available tools, prompts, and resources.
25+
/// It can be thought of like a "hint" to the model and may be added to a system prompt.
26+
/// </remarks>
2527
string? ServerInstructions { get; }
2628
}

src/ModelContextProtocol/Client/McpClient.cs

+66-46
Original file line numberDiff line numberDiff line change
@@ -12,67 +12,87 @@ namespace ModelContextProtocol.Client;
1212
/// <inheritdoc/>
1313
internal sealed class McpClient : McpEndpoint, IMcpClient
1414
{
15+
private static Implementation DefaultImplementation { get; } = new()
16+
{
17+
Name = DefaultAssemblyName.Name ?? nameof(McpClient),
18+
Version = DefaultAssemblyName.Version?.ToString() ?? "1.0.0",
19+
};
20+
1521
private readonly IClientTransport _clientTransport;
1622
private readonly McpClientOptions _options;
1723

1824
private ITransport? _sessionTransport;
1925
private CancellationTokenSource? _connectCts;
2026

27+
private ServerCapabilities? _serverCapabilities;
28+
private Implementation? _serverInfo;
29+
private string? _serverInstructions;
30+
2131
/// <summary>
2232
/// Initializes a new instance of the <see cref="McpClient"/> class.
2333
/// </summary>
2434
/// <param name="clientTransport">The transport to use for communication with the server.</param>
2535
/// <param name="options">Options for the client, defining protocol version and capabilities.</param>
2636
/// <param name="serverConfig">The server configuration.</param>
2737
/// <param name="loggerFactory">The logger factory.</param>
28-
public McpClient(IClientTransport clientTransport, McpClientOptions options, McpServerConfig serverConfig, ILoggerFactory? loggerFactory)
38+
public McpClient(IClientTransport clientTransport, McpClientOptions? options, McpServerConfig serverConfig, ILoggerFactory? loggerFactory)
2939
: base(loggerFactory)
3040
{
41+
options ??= new();
42+
3143
_clientTransport = clientTransport;
3244
_options = options;
3345

3446
EndpointName = $"Client ({serverConfig.Id}: {serverConfig.Name})";
3547

36-
if (options.Capabilities?.Sampling is { } samplingCapability)
48+
if (options.Capabilities is { } capabilities)
3749
{
38-
if (samplingCapability.SamplingHandler is not { } samplingHandler)
50+
if (capabilities.NotificationHandlers is { } notificationHandlers)
3951
{
40-
throw new InvalidOperationException($"Sampling capability was set but it did not provide a handler.");
52+
NotificationHandlers.AddRange(notificationHandlers);
4153
}
4254

43-
SetRequestHandler(
44-
RequestMethods.SamplingCreateMessage,
45-
(request, cancellationToken) => samplingHandler(
46-
request,
47-
request?.Meta?.ProgressToken is { } token ? new TokenProgress(this, token) : NullProgress.Instance,
48-
cancellationToken),
49-
McpJsonUtilities.JsonContext.Default.CreateMessageRequestParams,
50-
McpJsonUtilities.JsonContext.Default.CreateMessageResult);
51-
}
52-
53-
if (options.Capabilities?.Roots is { } rootsCapability)
54-
{
55-
if (rootsCapability.RootsHandler is not { } rootsHandler)
55+
if (capabilities.Sampling is { } samplingCapability)
5656
{
57-
throw new InvalidOperationException($"Roots capability was set but it did not provide a handler.");
57+
if (samplingCapability.SamplingHandler is not { } samplingHandler)
58+
{
59+
throw new InvalidOperationException($"Sampling capability was set but it did not provide a handler.");
60+
}
61+
62+
RequestHandlers.Set(
63+
RequestMethods.SamplingCreateMessage,
64+
(request, cancellationToken) => samplingHandler(
65+
request,
66+
request?.Meta?.ProgressToken is { } token ? new TokenProgress(this, token) : NullProgress.Instance,
67+
cancellationToken),
68+
McpJsonUtilities.JsonContext.Default.CreateMessageRequestParams,
69+
McpJsonUtilities.JsonContext.Default.CreateMessageResult);
5870
}
5971

60-
SetRequestHandler(
61-
RequestMethods.RootsList,
62-
rootsHandler,
63-
McpJsonUtilities.JsonContext.Default.ListRootsRequestParams,
64-
McpJsonUtilities.JsonContext.Default.ListRootsResult);
72+
if (capabilities.Roots is { } rootsCapability)
73+
{
74+
if (rootsCapability.RootsHandler is not { } rootsHandler)
75+
{
76+
throw new InvalidOperationException($"Roots capability was set but it did not provide a handler.");
77+
}
78+
79+
RequestHandlers.Set(
80+
RequestMethods.RootsList,
81+
rootsHandler,
82+
McpJsonUtilities.JsonContext.Default.ListRootsRequestParams,
83+
McpJsonUtilities.JsonContext.Default.ListRootsResult);
84+
}
6585
}
6686
}
6787

6888
/// <inheritdoc/>
69-
public ServerCapabilities? ServerCapabilities { get; private set; }
89+
public ServerCapabilities ServerCapabilities => _serverCapabilities ?? throw new InvalidOperationException("The client is not connected.");
7090

7191
/// <inheritdoc/>
72-
public Implementation? ServerInfo { get; private set; }
92+
public Implementation ServerInfo => _serverInfo ?? throw new InvalidOperationException("The client is not connected.");
7393

7494
/// <inheritdoc/>
75-
public string? ServerInstructions { get; private set; }
95+
public string? ServerInstructions => _serverInstructions;
7696

7797
/// <inheritdoc/>
7898
public override string EndpointName { get; }
@@ -92,46 +112,46 @@ public async Task ConnectAsync(CancellationToken cancellationToken = default)
92112
using var initializationCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
93113
initializationCts.CancelAfter(_options.InitializationTimeout);
94114

95-
try
96-
{
97-
// Send initialize request
98-
var initializeResponse = await this.SendRequestAsync(
99-
RequestMethods.Initialize,
100-
new InitializeRequestParams
101-
{
102-
ProtocolVersion = _options.ProtocolVersion,
103-
Capabilities = _options.Capabilities ?? new ClientCapabilities(),
104-
ClientInfo = _options.ClientInfo
105-
},
106-
McpJsonUtilities.JsonContext.Default.InitializeRequestParams,
107-
McpJsonUtilities.JsonContext.Default.InitializeResult,
108-
cancellationToken: initializationCts.Token).ConfigureAwait(false);
115+
try
116+
{
117+
// Send initialize request
118+
var initializeResponse = await this.SendRequestAsync(
119+
RequestMethods.Initialize,
120+
new InitializeRequestParams
121+
{
122+
ProtocolVersion = _options.ProtocolVersion,
123+
Capabilities = _options.Capabilities ?? new ClientCapabilities(),
124+
ClientInfo = _options.ClientInfo ?? DefaultImplementation,
125+
},
126+
McpJsonUtilities.JsonContext.Default.InitializeRequestParams,
127+
McpJsonUtilities.JsonContext.Default.InitializeResult,
128+
cancellationToken: initializationCts.Token).ConfigureAwait(false);
109129

110130
// Store server information
111131
_logger.ServerCapabilitiesReceived(EndpointName,
112132
capabilities: JsonSerializer.Serialize(initializeResponse.Capabilities, McpJsonUtilities.JsonContext.Default.ServerCapabilities),
113133
serverInfo: JsonSerializer.Serialize(initializeResponse.ServerInfo, McpJsonUtilities.JsonContext.Default.Implementation));
114134

115-
ServerCapabilities = initializeResponse.Capabilities;
116-
ServerInfo = initializeResponse.ServerInfo;
117-
ServerInstructions = initializeResponse.Instructions;
135+
_serverCapabilities = initializeResponse.Capabilities;
136+
_serverInfo = initializeResponse.ServerInfo;
137+
_serverInstructions = initializeResponse.Instructions;
118138

119139
// Validate protocol version
120140
if (initializeResponse.ProtocolVersion != _options.ProtocolVersion)
121141
{
122142
_logger.ServerProtocolVersionMismatch(EndpointName, _options.ProtocolVersion, initializeResponse.ProtocolVersion);
123-
throw new McpClientException($"Server protocol version mismatch. Expected {_options.ProtocolVersion}, got {initializeResponse.ProtocolVersion}");
143+
throw new McpException($"Server protocol version mismatch. Expected {_options.ProtocolVersion}, got {initializeResponse.ProtocolVersion}");
124144
}
125145

126146
// Send initialized notification
127147
await SendMessageAsync(
128148
new JsonRpcNotification { Method = NotificationMethods.InitializedNotification },
129149
initializationCts.Token).ConfigureAwait(false);
130150
}
131-
catch (OperationCanceledException) when (initializationCts.IsCancellationRequested)
151+
catch (OperationCanceledException oce) when (initializationCts.IsCancellationRequested)
132152
{
133153
_logger.ClientInitializationTimeout(EndpointName);
134-
throw new McpClientException("Initialization timed out");
154+
throw new McpException("Initialization timed out", oce);
135155
}
136156
}
137157
catch (Exception e)

src/ModelContextProtocol/Client/McpClientException.cs

-46
This file was deleted.

0 commit comments

Comments
 (0)