Consolidate McpClientException/McpServerException into McpException (#209)
This commit is contained in:
parent
d1a3c201a4
commit
8fcdf95785
25 changed files with 163 additions and 197 deletions
|
|
@ -8,19 +8,21 @@ namespace ModelContextProtocol.Client;
|
||||||
public interface IMcpClient : IMcpEndpoint
|
public interface IMcpClient : IMcpEndpoint
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the capabilities supported by the server.
|
/// Gets the capabilities supported by the connected server.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ServerCapabilities? ServerCapabilities { get; }
|
ServerCapabilities ServerCapabilities { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the version and implementation information of the server.
|
/// Gets the implementation information of the connected server.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Implementation? ServerInfo { get; }
|
Implementation ServerInfo { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Instructions describing how to use the server and its features.
|
/// Gets any instructions describing how to use the connected server and its features.
|
||||||
/// This can be used by clients to improve the LLM's understanding of available tools, resources, etc.
|
|
||||||
/// It can be thought of like a "hint" to the model. For example, this information MAY be added to the system prompt.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This can be used by clients to improve an LLM's understanding of available tools, prompts, and resources.
|
||||||
|
/// It can be thought of like a "hint" to the model and may be added to a system prompt.
|
||||||
|
/// </remarks>
|
||||||
string? ServerInstructions { get; }
|
string? ServerInstructions { get; }
|
||||||
}
|
}
|
||||||
|
|
@ -18,6 +18,10 @@ internal sealed class McpClient : McpEndpoint, IMcpClient
|
||||||
private ITransport? _sessionTransport;
|
private ITransport? _sessionTransport;
|
||||||
private CancellationTokenSource? _connectCts;
|
private CancellationTokenSource? _connectCts;
|
||||||
|
|
||||||
|
private ServerCapabilities? _serverCapabilities;
|
||||||
|
private Implementation? _serverInfo;
|
||||||
|
private string? _serverInstructions;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="McpClient"/> class.
|
/// Initializes a new instance of the <see cref="McpClient"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -66,13 +70,13 @@ internal sealed class McpClient : McpEndpoint, IMcpClient
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public ServerCapabilities? ServerCapabilities { get; private set; }
|
public ServerCapabilities ServerCapabilities => _serverCapabilities ?? throw new InvalidOperationException("The client is not connected.");
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public Implementation? ServerInfo { get; private set; }
|
public Implementation ServerInfo => _serverInfo ?? throw new InvalidOperationException("The client is not connected.");
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public string? ServerInstructions { get; private set; }
|
public string? ServerInstructions => _serverInstructions;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public override string EndpointName { get; }
|
public override string EndpointName { get; }
|
||||||
|
|
@ -112,15 +116,15 @@ internal sealed class McpClient : McpEndpoint, IMcpClient
|
||||||
capabilities: JsonSerializer.Serialize(initializeResponse.Capabilities, McpJsonUtilities.JsonContext.Default.ServerCapabilities),
|
capabilities: JsonSerializer.Serialize(initializeResponse.Capabilities, McpJsonUtilities.JsonContext.Default.ServerCapabilities),
|
||||||
serverInfo: JsonSerializer.Serialize(initializeResponse.ServerInfo, McpJsonUtilities.JsonContext.Default.Implementation));
|
serverInfo: JsonSerializer.Serialize(initializeResponse.ServerInfo, McpJsonUtilities.JsonContext.Default.Implementation));
|
||||||
|
|
||||||
ServerCapabilities = initializeResponse.Capabilities;
|
_serverCapabilities = initializeResponse.Capabilities;
|
||||||
ServerInfo = initializeResponse.ServerInfo;
|
_serverInfo = initializeResponse.ServerInfo;
|
||||||
ServerInstructions = initializeResponse.Instructions;
|
_serverInstructions = initializeResponse.Instructions;
|
||||||
|
|
||||||
// Validate protocol version
|
// Validate protocol version
|
||||||
if (initializeResponse.ProtocolVersion != _options.ProtocolVersion)
|
if (initializeResponse.ProtocolVersion != _options.ProtocolVersion)
|
||||||
{
|
{
|
||||||
_logger.ServerProtocolVersionMismatch(EndpointName, _options.ProtocolVersion, initializeResponse.ProtocolVersion);
|
_logger.ServerProtocolVersionMismatch(EndpointName, _options.ProtocolVersion, initializeResponse.ProtocolVersion);
|
||||||
throw new McpClientException($"Server protocol version mismatch. Expected {_options.ProtocolVersion}, got {initializeResponse.ProtocolVersion}");
|
throw new McpException($"Server protocol version mismatch. Expected {_options.ProtocolVersion}, got {initializeResponse.ProtocolVersion}");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send initialized notification
|
// Send initialized notification
|
||||||
|
|
@ -128,10 +132,10 @@ internal sealed class McpClient : McpEndpoint, IMcpClient
|
||||||
new JsonRpcNotification { Method = NotificationMethods.InitializedNotification },
|
new JsonRpcNotification { Method = NotificationMethods.InitializedNotification },
|
||||||
initializationCts.Token).ConfigureAwait(false);
|
initializationCts.Token).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (OperationCanceledException) when (initializationCts.IsCancellationRequested)
|
catch (OperationCanceledException oce) when (initializationCts.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
_logger.ClientInitializationTimeout(EndpointName);
|
_logger.ClientInitializationTimeout(EndpointName);
|
||||||
throw new McpClientException("Initialization timed out");
|
throw new McpException("Initialization timed out", oce);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
||||||
namespace ModelContextProtocol.Client;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents errors that occur in the MCP client.
|
|
||||||
/// </summary>
|
|
||||||
public class McpClientException : Exception
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the error code if this exception was caused by a JSON-RPC error response.
|
|
||||||
/// </summary>
|
|
||||||
public int? ErrorCode { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="McpClientException"/> class.
|
|
||||||
/// </summary>
|
|
||||||
public McpClientException()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="McpClientException"/> class with a specified error message.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="message">The message that describes the error.</param>
|
|
||||||
public McpClientException(string message) : base(message)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="McpClientException"/> class with a specified error message and error code.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="message">The message that describes the error.</param>
|
|
||||||
/// <param name="errorCode">The error code associated with the JSON-RPC error response.</param>
|
|
||||||
public McpClientException(string message, int errorCode) : base(message)
|
|
||||||
{
|
|
||||||
ErrorCode = errorCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="McpClientException"/> class with a specified error message and a reference to the inner exception that is the cause of this exception.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="message">The message that describes the error.</param>
|
|
||||||
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference if no inner exception is specified.</param>
|
|
||||||
public McpClientException(string message, Exception innerException) : base(message, innerException)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -15,7 +15,7 @@ public static class McpClientExtensions
|
||||||
/// Sends a ping request to verify server connectivity.
|
/// Sends a ping request to verify server connectivity.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="client">The client.</param>
|
/// <param name="client">The client.</param>
|
||||||
/// <param name="cancellationToken">A token to cancel the operation.</param>
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||||
/// <returns>A task that completes when the ping is successful.</returns>
|
/// <returns>A task that completes when the ping is successful.</returns>
|
||||||
public static Task PingAsync(this IMcpClient client, CancellationToken cancellationToken = default)
|
public static Task PingAsync(this IMcpClient client, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
|
|
@ -34,7 +34,7 @@ public static class McpClientExtensions
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="client">The client.</param>
|
/// <param name="client">The client.</param>
|
||||||
/// <param name="serializerOptions">The serializer options governing tool parameter serialization.</param>
|
/// <param name="serializerOptions">The serializer options governing tool parameter serialization.</param>
|
||||||
/// <param name="cancellationToken">A token to cancel the operation.</param>
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||||
/// <returns>A list of all available tools.</returns>
|
/// <returns>A list of all available tools.</returns>
|
||||||
public static async Task<IList<McpClientTool>> ListToolsAsync(
|
public static async Task<IList<McpClientTool>> ListToolsAsync(
|
||||||
this IMcpClient client,
|
this IMcpClient client,
|
||||||
|
|
@ -75,7 +75,7 @@ public static class McpClientExtensions
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="client">The client.</param>
|
/// <param name="client">The client.</param>
|
||||||
/// <param name="serializerOptions">The serializer options governing tool parameter serialization.</param>
|
/// <param name="serializerOptions">The serializer options governing tool parameter serialization.</param>
|
||||||
/// <param name="cancellationToken">A token to cancel the operation.</param>
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||||
/// <returns>An asynchronous sequence of all available tools.</returns>
|
/// <returns>An asynchronous sequence of all available tools.</returns>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Every iteration through the returned <see cref="IAsyncEnumerable{McpClientTool}"/>
|
/// Every iteration through the returned <see cref="IAsyncEnumerable{McpClientTool}"/>
|
||||||
|
|
@ -115,7 +115,7 @@ public static class McpClientExtensions
|
||||||
/// Retrieves a list of available prompts from the server.
|
/// Retrieves a list of available prompts from the server.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="client">The client.</param>
|
/// <param name="client">The client.</param>
|
||||||
/// <param name="cancellationToken">A token to cancel the operation.</param>
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||||
/// <returns>A list of all available prompts.</returns>
|
/// <returns>A list of all available prompts.</returns>
|
||||||
public static async Task<IList<McpClientPrompt>> ListPromptsAsync(
|
public static async Task<IList<McpClientPrompt>> ListPromptsAsync(
|
||||||
this IMcpClient client, CancellationToken cancellationToken = default)
|
this IMcpClient client, CancellationToken cancellationToken = default)
|
||||||
|
|
@ -150,7 +150,7 @@ public static class McpClientExtensions
|
||||||
/// Creates an enumerable for asynchronously enumerating all available prompts from the server.
|
/// Creates an enumerable for asynchronously enumerating all available prompts from the server.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="client">The client.</param>
|
/// <param name="client">The client.</param>
|
||||||
/// <param name="cancellationToken">A token to cancel the operation.</param>
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||||
/// <returns>An asynchronous sequence of all available prompts.</returns>
|
/// <returns>An asynchronous sequence of all available prompts.</returns>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Every iteration through the returned <see cref="IAsyncEnumerable{Prompt}"/>
|
/// Every iteration through the returned <see cref="IAsyncEnumerable{Prompt}"/>
|
||||||
|
|
@ -188,7 +188,7 @@ public static class McpClientExtensions
|
||||||
/// <param name="name">The name of the prompt to retrieve</param>
|
/// <param name="name">The name of the prompt to retrieve</param>
|
||||||
/// <param name="arguments">Optional arguments for the prompt</param>
|
/// <param name="arguments">Optional arguments for the prompt</param>
|
||||||
/// <param name="serializerOptions">The serialization options governing argument serialization.</param>
|
/// <param name="serializerOptions">The serialization options governing argument serialization.</param>
|
||||||
/// <param name="cancellationToken">A token to cancel the operation.</param>
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||||
/// <returns>A task containing the prompt's content and messages.</returns>
|
/// <returns>A task containing the prompt's content and messages.</returns>
|
||||||
public static Task<GetPromptResult> GetPromptAsync(
|
public static Task<GetPromptResult> GetPromptAsync(
|
||||||
this IMcpClient client,
|
this IMcpClient client,
|
||||||
|
|
@ -216,7 +216,7 @@ public static class McpClientExtensions
|
||||||
/// Retrieves a list of available resource templates from the server.
|
/// Retrieves a list of available resource templates from the server.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="client">The client.</param>
|
/// <param name="client">The client.</param>
|
||||||
/// <param name="cancellationToken">A token to cancel the operation.</param>
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||||
/// <returns>A list of all available resource templates.</returns>
|
/// <returns>A list of all available resource templates.</returns>
|
||||||
public static async Task<IList<ResourceTemplate>> ListResourceTemplatesAsync(
|
public static async Task<IList<ResourceTemplate>> ListResourceTemplatesAsync(
|
||||||
this IMcpClient client, CancellationToken cancellationToken = default)
|
this IMcpClient client, CancellationToken cancellationToken = default)
|
||||||
|
|
@ -255,7 +255,7 @@ public static class McpClientExtensions
|
||||||
/// Creates an enumerable for asynchronously enumerating all available resource templates from the server.
|
/// Creates an enumerable for asynchronously enumerating all available resource templates from the server.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="client">The client.</param>
|
/// <param name="client">The client.</param>
|
||||||
/// <param name="cancellationToken">A token to cancel the operation.</param>
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||||
/// <returns>An asynchronous sequence of all available resource templates.</returns>
|
/// <returns>An asynchronous sequence of all available resource templates.</returns>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Every iteration through the returned <see cref="IAsyncEnumerable{ResourceTemplate}"/>
|
/// Every iteration through the returned <see cref="IAsyncEnumerable{ResourceTemplate}"/>
|
||||||
|
|
@ -290,7 +290,7 @@ public static class McpClientExtensions
|
||||||
/// Retrieves a list of available resources from the server.
|
/// Retrieves a list of available resources from the server.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="client">The client.</param>
|
/// <param name="client">The client.</param>
|
||||||
/// <param name="cancellationToken">A token to cancel the operation.</param>
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||||
/// <returns>A list of all available resources.</returns>
|
/// <returns>A list of all available resources.</returns>
|
||||||
public static async Task<IList<Resource>> ListResourcesAsync(
|
public static async Task<IList<Resource>> ListResourcesAsync(
|
||||||
this IMcpClient client, CancellationToken cancellationToken = default)
|
this IMcpClient client, CancellationToken cancellationToken = default)
|
||||||
|
|
@ -329,7 +329,7 @@ public static class McpClientExtensions
|
||||||
/// Creates an enumerable for asynchronously enumerating all available resources from the server.
|
/// Creates an enumerable for asynchronously enumerating all available resources from the server.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="client">The client.</param>
|
/// <param name="client">The client.</param>
|
||||||
/// <param name="cancellationToken">A token to cancel the operation.</param>
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||||
/// <returns>An asynchronous sequence of all available resources.</returns>
|
/// <returns>An asynchronous sequence of all available resources.</returns>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Every iteration through the returned <see cref="IAsyncEnumerable{Resource}"/>
|
/// Every iteration through the returned <see cref="IAsyncEnumerable{Resource}"/>
|
||||||
|
|
@ -365,7 +365,7 @@ public static class McpClientExtensions
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="client">The client.</param>
|
/// <param name="client">The client.</param>
|
||||||
/// <param name="uri">The uri of the resource.</param>
|
/// <param name="uri">The uri of the resource.</param>
|
||||||
/// <param name="cancellationToken">A token to cancel the operation.</param>
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||||
public static Task<ReadResourceResult> ReadResourceAsync(
|
public static Task<ReadResourceResult> ReadResourceAsync(
|
||||||
this IMcpClient client, string uri, CancellationToken cancellationToken = default)
|
this IMcpClient client, string uri, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
|
|
@ -387,7 +387,7 @@ public static class McpClientExtensions
|
||||||
/// <param name="reference">A resource (uri) or prompt (name) reference</param>
|
/// <param name="reference">A resource (uri) or prompt (name) reference</param>
|
||||||
/// <param name="argumentName">Name of argument. Must be non-null and non-empty.</param>
|
/// <param name="argumentName">Name of argument. Must be non-null and non-empty.</param>
|
||||||
/// <param name="argumentValue">Value of argument. Must be non-null.</param>
|
/// <param name="argumentValue">Value of argument. Must be non-null.</param>
|
||||||
/// <param name="cancellationToken">A token to cancel the operation.</param>
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||||
public static Task<CompleteResult> GetCompletionAsync(this IMcpClient client, Reference reference, string argumentName, string argumentValue, CancellationToken cancellationToken = default)
|
public static Task<CompleteResult> GetCompletionAsync(this IMcpClient client, Reference reference, string argumentName, string argumentValue, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
Throw.IfNull(client);
|
Throw.IfNull(client);
|
||||||
|
|
@ -416,7 +416,7 @@ public static class McpClientExtensions
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="client">The client.</param>
|
/// <param name="client">The client.</param>
|
||||||
/// <param name="uri">The uri of the resource.</param>
|
/// <param name="uri">The uri of the resource.</param>
|
||||||
/// <param name="cancellationToken">A token to cancel the operation.</param>
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||||
public static Task SubscribeToResourceAsync(this IMcpClient client, string uri, CancellationToken cancellationToken = default)
|
public static Task SubscribeToResourceAsync(this IMcpClient client, string uri, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
Throw.IfNull(client);
|
Throw.IfNull(client);
|
||||||
|
|
@ -435,7 +435,7 @@ public static class McpClientExtensions
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="client">The client.</param>
|
/// <param name="client">The client.</param>
|
||||||
/// <param name="uri">The uri of the resource.</param>
|
/// <param name="uri">The uri of the resource.</param>
|
||||||
/// <param name="cancellationToken">A token to cancel the operation.</param>
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||||
public static Task UnsubscribeFromResourceAsync(this IMcpClient client, string uri, CancellationToken cancellationToken = default)
|
public static Task UnsubscribeFromResourceAsync(this IMcpClient client, string uri, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
Throw.IfNull(client);
|
Throw.IfNull(client);
|
||||||
|
|
@ -456,7 +456,7 @@ public static class McpClientExtensions
|
||||||
/// <param name="toolName">The name of the tool to call.</param>
|
/// <param name="toolName">The name of the tool to call.</param>
|
||||||
/// <param name="arguments">Optional arguments for the tool.</param>
|
/// <param name="arguments">Optional arguments for the tool.</param>
|
||||||
/// <param name="serializerOptions">The serialization options governing argument serialization.</param>
|
/// <param name="serializerOptions">The serialization options governing argument serialization.</param>
|
||||||
/// <param name="cancellationToken">A token to cancel the operation.</param>
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||||
/// <returns>A task containing the tool's response.</returns>
|
/// <returns>A task containing the tool's response.</returns>
|
||||||
public static Task<CallToolResponse> CallToolAsync(
|
public static Task<CallToolResponse> CallToolAsync(
|
||||||
this IMcpClient client,
|
this IMcpClient client,
|
||||||
|
|
@ -622,7 +622,7 @@ public static class McpClientExtensions
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="client">The client.</param>
|
/// <param name="client">The client.</param>
|
||||||
/// <param name="level">The minimum log level of messages to be generated.</param>
|
/// <param name="level">The minimum log level of messages to be generated.</param>
|
||||||
/// <param name="cancellationToken">A token to cancel the operation.</param>
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||||
public static Task SetLoggingLevel(this IMcpClient client, LoggingLevel level, CancellationToken cancellationToken = default)
|
public static Task SetLoggingLevel(this IMcpClient client, LoggingLevel level, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
Throw.IfNull(client);
|
Throw.IfNull(client);
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ public static class McpClientFactory
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <param name="createTransportFunc">An optional factory method which returns transport implementations based on a server configuration.</param>
|
/// <param name="createTransportFunc">An optional factory method which returns transport implementations based on a server configuration.</param>
|
||||||
/// <param name="loggerFactory">A logger factory for creating loggers for clients.</param>
|
/// <param name="loggerFactory">A logger factory for creating loggers for clients.</param>
|
||||||
/// <param name="cancellationToken">A token to cancel the operation.</param>
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||||
/// <returns>An <see cref="IMcpClient"/> that's connected to the specified server.</returns>
|
/// <returns>An <see cref="IMcpClient"/> that's connected to the specified server.</returns>
|
||||||
/// <exception cref="ArgumentNullException"><paramref name="serverConfig"/> is <see langword="null"/>.</exception>
|
/// <exception cref="ArgumentNullException"><paramref name="serverConfig"/> is <see langword="null"/>.</exception>
|
||||||
/// <exception cref="ArgumentNullException"><paramref name="clientOptions"/> is <see langword="null"/>.</exception>
|
/// <exception cref="ArgumentNullException"><paramref name="clientOptions"/> is <see langword="null"/>.</exception>
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ public sealed class McpClientPrompt
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="arguments">Optional arguments for the prompt</param>
|
/// <param name="arguments">Optional arguments for the prompt</param>
|
||||||
/// <param name="serializerOptions">The serialization options governing argument serialization.</param>
|
/// <param name="serializerOptions">The serialization options governing argument serialization.</param>
|
||||||
/// <param name="cancellationToken">A token to cancel the operation.</param>
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||||
/// <returns>A task containing the prompt's content and messages.</returns>
|
/// <returns>A task containing the prompt's content and messages.</returns>
|
||||||
public async ValueTask<GetPromptResult> GetAsync(
|
public async ValueTask<GetPromptResult> GetAsync(
|
||||||
IEnumerable<KeyValuePair<string, object?>>? arguments = null,
|
IEnumerable<KeyValuePair<string, object?>>? arguments = null,
|
||||||
|
|
|
||||||
|
|
@ -7,13 +7,13 @@ public interface IMcpEndpoint : IAsyncDisposable
|
||||||
{
|
{
|
||||||
/// <summary>Sends a JSON-RPC request to the connected endpoint.</summary>
|
/// <summary>Sends a JSON-RPC request to the connected endpoint.</summary>
|
||||||
/// <param name="request">The JSON-RPC request to send.</param>
|
/// <param name="request">The JSON-RPC request to send.</param>
|
||||||
/// <param name="cancellationToken">A token to cancel the operation.</param>
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||||
/// <returns>A task containing the client's response.</returns>
|
/// <returns>A task containing the client's response.</returns>
|
||||||
Task<JsonRpcResponse> SendRequestAsync(JsonRpcRequest request, CancellationToken cancellationToken = default);
|
Task<JsonRpcResponse> SendRequestAsync(JsonRpcRequest request, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
/// <summary>Sends a message to the connected endpoint.</summary>
|
/// <summary>Sends a message to the connected endpoint.</summary>
|
||||||
/// <param name="message">The message.</param>
|
/// <param name="message">The message.</param>
|
||||||
/// <param name="cancellationToken">A token to cancel the operation.</param>
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||||
Task SendMessageAsync(IJsonRpcMessage message, CancellationToken cancellationToken = default);
|
Task SendMessageAsync(IJsonRpcMessage message, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ public static class McpEndpointExtensions
|
||||||
/// <param name="parameters">Object representing the request parameters.</param>
|
/// <param name="parameters">Object representing the request parameters.</param>
|
||||||
/// <param name="requestId">The request id for the request.</param>
|
/// <param name="requestId">The request id for the request.</param>
|
||||||
/// <param name="serializerOptions">The options governing request serialization.</param>
|
/// <param name="serializerOptions">The options governing request serialization.</param>
|
||||||
/// <param name="cancellationToken">A token to cancel the operation.</param>
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||||
/// <returns>A task that represents the asynchronous operation. The task result contains the deserialized result.</returns>
|
/// <returns>A task that represents the asynchronous operation. The task result contains the deserialized result.</returns>
|
||||||
public static Task<TResult> SendRequestAsync<TParameters, TResult>(
|
public static Task<TResult> SendRequestAsync<TParameters, TResult>(
|
||||||
this IMcpEndpoint endpoint,
|
this IMcpEndpoint endpoint,
|
||||||
|
|
@ -50,7 +50,7 @@ public static class McpEndpointExtensions
|
||||||
/// <param name="parametersTypeInfo">The type information for request parameter serialization.</param>
|
/// <param name="parametersTypeInfo">The type information for request parameter serialization.</param>
|
||||||
/// <param name="resultTypeInfo">The type information for request parameter deserialization.</param>
|
/// <param name="resultTypeInfo">The type information for request parameter deserialization.</param>
|
||||||
/// <param name="requestId">The request id for the request.</param>
|
/// <param name="requestId">The request id for the request.</param>
|
||||||
/// <param name="cancellationToken">A token to cancel the operation.</param>
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||||
/// <returns>A task that represents the asynchronous operation. The task result contains the deserialized result.</returns>
|
/// <returns>A task that represents the asynchronous operation. The task result contains the deserialized result.</returns>
|
||||||
internal static async Task<TResult> SendRequestAsync<TParameters, TResult>(
|
internal static async Task<TResult> SendRequestAsync<TParameters, TResult>(
|
||||||
this IMcpEndpoint endpoint,
|
this IMcpEndpoint endpoint,
|
||||||
|
|
@ -87,7 +87,7 @@ public static class McpEndpointExtensions
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="client">The client.</param>
|
/// <param name="client">The client.</param>
|
||||||
/// <param name="method">The notification method name.</param>
|
/// <param name="method">The notification method name.</param>
|
||||||
/// <param name="cancellationToken">A token to cancel the operation.</param>
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||||
public static Task SendNotificationAsync(this IMcpEndpoint client, string method, CancellationToken cancellationToken = default)
|
public static Task SendNotificationAsync(this IMcpEndpoint client, string method, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
Throw.IfNull(client);
|
Throw.IfNull(client);
|
||||||
|
|
@ -102,7 +102,7 @@ public static class McpEndpointExtensions
|
||||||
/// <param name="method">The JSON-RPC method name to invoke.</param>
|
/// <param name="method">The JSON-RPC method name to invoke.</param>
|
||||||
/// <param name="parameters">Object representing the request parameters.</param>
|
/// <param name="parameters">Object representing the request parameters.</param>
|
||||||
/// <param name="serializerOptions">The options governing request serialization.</param>
|
/// <param name="serializerOptions">The options governing request serialization.</param>
|
||||||
/// <param name="cancellationToken">A token to cancel the operation.</param>
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||||
public static Task SendNotificationAsync<TParameters>(
|
public static Task SendNotificationAsync<TParameters>(
|
||||||
this IMcpEndpoint endpoint,
|
this IMcpEndpoint endpoint,
|
||||||
string method,
|
string method,
|
||||||
|
|
@ -124,7 +124,7 @@ public static class McpEndpointExtensions
|
||||||
/// <param name="method">The JSON-RPC method name to invoke.</param>
|
/// <param name="method">The JSON-RPC method name to invoke.</param>
|
||||||
/// <param name="parameters">Object representing the request parameters.</param>
|
/// <param name="parameters">Object representing the request parameters.</param>
|
||||||
/// <param name="parametersTypeInfo">The type information for request parameter serialization.</param>
|
/// <param name="parametersTypeInfo">The type information for request parameter serialization.</param>
|
||||||
/// <param name="cancellationToken">A token to cancel the operation.</param>
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||||
internal static Task SendNotificationAsync<TParameters>(
|
internal static Task SendNotificationAsync<TParameters>(
|
||||||
this IMcpEndpoint endpoint,
|
this IMcpEndpoint endpoint,
|
||||||
string method,
|
string method,
|
||||||
|
|
@ -144,7 +144,7 @@ public static class McpEndpointExtensions
|
||||||
/// <param name="endpoint">The endpoint issuing the notification.</param>
|
/// <param name="endpoint">The endpoint issuing the notification.</param>
|
||||||
/// <param name="progressToken">The <see cref="ProgressToken"/> identifying the operation.</param>
|
/// <param name="progressToken">The <see cref="ProgressToken"/> identifying the operation.</param>
|
||||||
/// <param name="progress">The progress update to send.</param>
|
/// <param name="progress">The progress update to send.</param>
|
||||||
/// <param name="cancellationToken">A token to cancel the operation.</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 operation.</returns>
|
/// <returns>A task representing the completion of the operation.</returns>
|
||||||
/// <exception cref="ArgumentNullException"><paramref name="endpoint"/> is <see langword="null"/>.</exception>
|
/// <exception cref="ArgumentNullException"><paramref name="endpoint"/> is <see langword="null"/>.</exception>
|
||||||
public static Task NotifyProgressAsync(
|
public static Task NotifyProgressAsync(
|
||||||
|
|
|
||||||
56
src/ModelContextProtocol/McpException.cs
Normal file
56
src/ModelContextProtocol/McpException.cs
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
namespace ModelContextProtocol;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An exception that is thrown when an MCP configuration or protocol error occurs.
|
||||||
|
/// </summary>
|
||||||
|
public class McpException : Exception
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="McpException"/> class.
|
||||||
|
/// </summary>
|
||||||
|
public McpException()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="McpException"/> class with a specified error message.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="message">The message that describes the error.</param>
|
||||||
|
public McpException(string message) : base(message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="McpException"/> class with a specified error message and a reference to the inner exception that is the cause of this exception.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="message">The message that describes the error.</param>
|
||||||
|
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference if no inner exception is specified.</param>
|
||||||
|
public McpException(string message, Exception? innerException) : base(message, innerException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="McpException"/> class with a specified error message and a reference to the inner exception that is the cause of this exception.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="message">The message that describes the error.</param>
|
||||||
|
/// <param name="errorCode">A JSON-RPC error code, if this exception represents a JSON-RPC error.</param>
|
||||||
|
public McpException(string message, int? errorCode) : this(message, null, errorCode)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="McpException"/> class with a specified error message and a reference to the inner exception that is the cause of this exception.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="message">The message that describes the error.</param>
|
||||||
|
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference if no inner exception is specified.</param>
|
||||||
|
/// <param name="errorCode">A JSON-RPC error code, if this exception represents a JSON-RPC error.</param>
|
||||||
|
public McpException(string message, Exception? innerException, int? errorCode) : base(message, innerException)
|
||||||
|
{
|
||||||
|
ErrorCode = errorCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the error code if this exception was caused by a JSON-RPC error response.
|
||||||
|
/// </summary>
|
||||||
|
public int? ErrorCode { get; }
|
||||||
|
}
|
||||||
|
|
@ -8,7 +8,7 @@ public interface IClientTransport
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Asynchronously establishes a transport session with an MCP server and returns an interface for the duplex JSON-RPC message stream.
|
/// Asynchronously establishes a transport session with an MCP server and returns an interface for the duplex JSON-RPC message stream.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="cancellationToken">Token to cancel the operation.</param>
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||||
/// <returns>Returns an interface for the duplex JSON-RPC message stream.</returns>
|
/// <returns>Returns an interface for the duplex JSON-RPC message stream.</returns>
|
||||||
Task<ITransport> ConnectAsync(CancellationToken cancellationToken = default);
|
Task<ITransport> ConnectAsync(CancellationToken cancellationToken = default);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,6 @@ public interface ITransport : IAsyncDisposable
|
||||||
/// Sends a message through the transport.
|
/// Sends a message through the transport.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="message">The message to send.</param>
|
/// <param name="message">The message to send.</param>
|
||||||
/// <param name="cancellationToken">Token to cancel the operation.</param>
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||||
Task SendMessageAsync(IJsonRpcMessage message, CancellationToken cancellationToken = default);
|
Task SendMessageAsync(IJsonRpcMessage message, CancellationToken cancellationToken = default);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ public sealed class SseResponseStreamTransport(Stream sseResponseStream, string
|
||||||
/// Starts the transport and writes the JSON-RPC messages sent via <see cref="SendMessageAsync(IJsonRpcMessage, CancellationToken)"/>
|
/// Starts the transport and writes the JSON-RPC messages sent via <see cref="SendMessageAsync(IJsonRpcMessage, CancellationToken)"/>
|
||||||
/// to the SSE response stream until cancelled or disposed.
|
/// to the SSE response stream until cancelled or disposed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="cancellationToken">A token to cancel writing to the SSE response stream.</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 send loop that writes JSON-RPC messages to the SSE response stream.</returns>
|
/// <returns>A task representing the send loop that writes JSON-RPC messages to the SSE response stream.</returns>
|
||||||
public Task RunAsync(CancellationToken cancellationToken)
|
public Task RunAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
|
@ -84,7 +84,7 @@ public sealed class SseResponseStreamTransport(Stream sseResponseStream, string
|
||||||
/// Handles incoming JSON-RPC messages received on the /message endpoint.
|
/// Handles incoming JSON-RPC messages received on the /message endpoint.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="message">The JSON-RPC message received.</param>
|
/// <param name="message">The JSON-RPC message received.</param>
|
||||||
/// <param name="cancellationToken">A token to cancel the operation.</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 potentially asynchronous operation to buffer or process the JSON-RPC message.</returns>
|
/// <returns>A task representing the potentially asynchronous operation to buffer or process the JSON-RPC message.</returns>
|
||||||
/// <exception cref="InvalidOperationException">Thrown when there is an attempt to process a message before calling <see cref="RunAsync(CancellationToken)"/>.</exception>
|
/// <exception cref="InvalidOperationException">Thrown when there is an attempt to process a message before calling <see cref="RunAsync(CancellationToken)"/>.</exception>
|
||||||
public async Task OnMessageReceivedAsync(IJsonRpcMessage message, CancellationToken cancellationToken)
|
public async Task OnMessageReceivedAsync(IJsonRpcMessage message, CancellationToken cancellationToken)
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ public abstract class TransportBase : ITransport
|
||||||
/// Writes a message to the message channel.
|
/// Writes a message to the message channel.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="message">The message to write.</param>
|
/// <param name="message">The message to write.</param>
|
||||||
/// <param name="cancellationToken">Token to cancel the operation.</param>
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||||
protected async Task WriteMessageAsync(IJsonRpcMessage message, CancellationToken cancellationToken = default)
|
protected async Task WriteMessageAsync(IJsonRpcMessage message, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
if (!_isConnected)
|
if (!_isConnected)
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ internal sealed class McpServer : McpEndpoint, IMcpServer
|
||||||
/// Make sure to accurately reflect exactly what capabilities the server supports and does not support.</param>
|
/// Make sure to accurately reflect exactly what capabilities the server supports and does not support.</param>
|
||||||
/// <param name="loggerFactory">Logger factory to use for logging</param>
|
/// <param name="loggerFactory">Logger factory to use for logging</param>
|
||||||
/// <param name="serviceProvider">Optional service provider to use for dependency injection</param>
|
/// <param name="serviceProvider">Optional service provider to use for dependency injection</param>
|
||||||
/// <exception cref="McpServerException"></exception>
|
/// <exception cref="McpException">The server was incorrectly configured.</exception>
|
||||||
public McpServer(ITransport transport, McpServerOptions options, ILoggerFactory? loggerFactory, IServiceProvider? serviceProvider)
|
public McpServer(ITransport transport, McpServerOptions options, ILoggerFactory? loggerFactory, IServiceProvider? serviceProvider)
|
||||||
: base(loggerFactory)
|
: base(loggerFactory)
|
||||||
{
|
{
|
||||||
|
|
@ -185,7 +185,7 @@ internal sealed class McpServer : McpEndpoint, IMcpServer
|
||||||
if ((listResourcesHandler is not { } && listResourceTemplatesHandler is not { }) ||
|
if ((listResourcesHandler is not { } && listResourceTemplatesHandler is not { }) ||
|
||||||
resourcesCapability.ReadResourceHandler is not { } readResourceHandler)
|
resourcesCapability.ReadResourceHandler is not { } readResourceHandler)
|
||||||
{
|
{
|
||||||
throw new McpServerException("Resources capability was enabled, but ListResources and/or ReadResource handlers were not specified.");
|
throw new McpException("Resources capability was enabled, but ListResources and/or ReadResource handlers were not specified.");
|
||||||
}
|
}
|
||||||
|
|
||||||
listResourcesHandler ??= (static (_, _) => Task.FromResult(new ListResourcesResult()));
|
listResourcesHandler ??= (static (_, _) => Task.FromResult(new ListResourcesResult()));
|
||||||
|
|
@ -218,7 +218,7 @@ internal sealed class McpServer : McpEndpoint, IMcpServer
|
||||||
var unsubscribeHandler = resourcesCapability.UnsubscribeFromResourcesHandler;
|
var unsubscribeHandler = resourcesCapability.UnsubscribeFromResourcesHandler;
|
||||||
if (subscribeHandler is null || unsubscribeHandler is null)
|
if (subscribeHandler is null || unsubscribeHandler is null)
|
||||||
{
|
{
|
||||||
throw new McpServerException("Resources capability was enabled with subscribe support, but SubscribeToResources and/or UnsubscribeFromResources handlers were not specified.");
|
throw new McpException("Resources capability was enabled with subscribe support, but SubscribeToResources and/or UnsubscribeFromResources handlers were not specified.");
|
||||||
}
|
}
|
||||||
|
|
||||||
SetRequestHandler(
|
SetRequestHandler(
|
||||||
|
|
@ -243,7 +243,7 @@ internal sealed class McpServer : McpEndpoint, IMcpServer
|
||||||
|
|
||||||
if (listPromptsHandler is null != getPromptHandler is null)
|
if (listPromptsHandler is null != getPromptHandler is null)
|
||||||
{
|
{
|
||||||
throw new McpServerException("ListPrompts and GetPrompt handlers should be specified together.");
|
throw new McpException("ListPrompts and GetPrompt handlers should be specified together.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle prompts provided via DI.
|
// Handle prompts provided via DI.
|
||||||
|
|
@ -276,7 +276,7 @@ internal sealed class McpServer : McpEndpoint, IMcpServer
|
||||||
return originalGetPromptHandler(request, cancellationToken);
|
return originalGetPromptHandler(request, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new McpServerException($"Unknown prompt '{request.Params?.Name}'");
|
throw new McpException($"Unknown prompt '{request.Params?.Name}'");
|
||||||
}
|
}
|
||||||
|
|
||||||
return prompt.GetAsync(request, cancellationToken);
|
return prompt.GetAsync(request, cancellationToken);
|
||||||
|
|
@ -310,7 +310,7 @@ internal sealed class McpServer : McpEndpoint, IMcpServer
|
||||||
// Make sure the handlers are provided if the capability is enabled.
|
// Make sure the handlers are provided if the capability is enabled.
|
||||||
if (listPromptsHandler is null || getPromptHandler is null)
|
if (listPromptsHandler is null || getPromptHandler is null)
|
||||||
{
|
{
|
||||||
throw new McpServerException("ListPrompts and/or GetPrompt handlers were not specified but the Prompts capability was enabled.");
|
throw new McpException("ListPrompts and/or GetPrompt handlers were not specified but the Prompts capability was enabled.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -336,7 +336,7 @@ internal sealed class McpServer : McpEndpoint, IMcpServer
|
||||||
|
|
||||||
if (listToolsHandler is null != callToolHandler is null)
|
if (listToolsHandler is null != callToolHandler is null)
|
||||||
{
|
{
|
||||||
throw new McpServerException("ListTools and CallTool handlers should be specified together.");
|
throw new McpException("ListTools and CallTool handlers should be specified together.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle tools provided via DI.
|
// Handle tools provided via DI.
|
||||||
|
|
@ -369,7 +369,7 @@ internal sealed class McpServer : McpEndpoint, IMcpServer
|
||||||
return originalCallToolHandler(request, cancellationToken);
|
return originalCallToolHandler(request, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new McpServerException($"Unknown tool '{request.Params?.Name}'");
|
throw new McpException($"Unknown tool '{request.Params?.Name}'");
|
||||||
}
|
}
|
||||||
|
|
||||||
return tool.InvokeAsync(request, cancellationToken);
|
return tool.InvokeAsync(request, cancellationToken);
|
||||||
|
|
@ -403,7 +403,7 @@ internal sealed class McpServer : McpEndpoint, IMcpServer
|
||||||
// Make sure the handlers are provided if the capability is enabled.
|
// Make sure the handlers are provided if the capability is enabled.
|
||||||
if (listToolsHandler is null || callToolHandler is null)
|
if (listToolsHandler is null || callToolHandler is null)
|
||||||
{
|
{
|
||||||
throw new McpServerException("ListTools and/or CallTool handlers were not specified but the Tools capability was enabled.");
|
throw new McpException("ListTools and/or CallTool handlers were not specified but the Tools capability was enabled.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -429,7 +429,7 @@ internal sealed class McpServer : McpEndpoint, IMcpServer
|
||||||
|
|
||||||
if (loggingCapability.SetLoggingLevelHandler is not { } setLoggingLevelHandler)
|
if (loggingCapability.SetLoggingLevelHandler is not { } setLoggingLevelHandler)
|
||||||
{
|
{
|
||||||
throw new McpServerException("Logging capability was enabled, but SetLoggingLevelHandler was not specified.");
|
throw new McpException("Logging capability was enabled, but SetLoggingLevelHandler was not specified.");
|
||||||
}
|
}
|
||||||
|
|
||||||
SetRequestHandler(
|
SetRequestHandler(
|
||||||
|
|
|
||||||
|
|
@ -1,48 +0,0 @@
|
||||||
using ModelContextProtocol.Client;
|
|
||||||
|
|
||||||
namespace ModelContextProtocol.Server;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents errors that occur in the MCP server.
|
|
||||||
/// </summary>
|
|
||||||
public class McpServerException : Exception
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the error code if this exception was caused by a JSON-RPC error response.
|
|
||||||
/// </summary>
|
|
||||||
public int? ErrorCode { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="McpServerException"/> class with a specified error message.
|
|
||||||
/// </summary>
|
|
||||||
public McpServerException()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="McpServerException"/> class with a specified error message.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="message">The message that describes the error.</param>
|
|
||||||
public McpServerException(string message) : base(message)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="McpServerException"/> class with a specified error message and error code.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="message">The message that describes the error.</param>
|
|
||||||
/// <param name="errorCode">The error code associated with the JSON-RPC error response.</param>
|
|
||||||
public McpServerException(string message, int errorCode) : base(message)
|
|
||||||
{
|
|
||||||
ErrorCode = errorCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="McpClientException"/> class with a specified error message and a reference to the inner exception that is the cause of this exception.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="message">The message that describes the error.</param>
|
|
||||||
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference if no inner exception is specified.</param>
|
|
||||||
public McpServerException(string message, Exception innerException) : base(message, innerException)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -41,7 +41,7 @@ public static class McpServerExtensions
|
||||||
/// <param name="server">The server issueing the request.</param>
|
/// <param name="server">The server issueing the request.</param>
|
||||||
/// <param name="messages">The messages to send as part of the request.</param>
|
/// <param name="messages">The messages to send as part of the request.</param>
|
||||||
/// <param name="options">The options to use for the request.</param>
|
/// <param name="options">The options to use for the request.</param>
|
||||||
/// <param name="cancellationToken">A token to cancel the operation.</param>
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||||
/// <returns>A task containing the response from the client.</returns>
|
/// <returns>A task containing the response from the client.</returns>
|
||||||
/// <exception cref="ArgumentNullException"><paramref name="server"/> is <see langword="null"/>.</exception>
|
/// <exception cref="ArgumentNullException"><paramref name="server"/> is <see langword="null"/>.</exception>
|
||||||
/// <exception cref="ArgumentNullException"><paramref name="messages"/> is <see langword="null"/>.</exception>
|
/// <exception cref="ArgumentNullException"><paramref name="messages"/> is <see langword="null"/>.</exception>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Logging.Abstractions;
|
using Microsoft.Extensions.Logging.Abstractions;
|
||||||
using ModelContextProtocol.Client;
|
|
||||||
using ModelContextProtocol.Logging;
|
using ModelContextProtocol.Logging;
|
||||||
using ModelContextProtocol.Protocol.Messages;
|
using ModelContextProtocol.Protocol.Messages;
|
||||||
using ModelContextProtocol.Protocol.Transport;
|
using ModelContextProtocol.Protocol.Transport;
|
||||||
|
|
@ -147,7 +146,7 @@ internal sealed class McpSession : IDisposable
|
||||||
JsonRpc = "2.0",
|
JsonRpc = "2.0",
|
||||||
Error = new JsonRpcErrorDetail
|
Error = new JsonRpcErrorDetail
|
||||||
{
|
{
|
||||||
Code = (ex as McpServerException)?.ErrorCode ?? ErrorCodes.InternalError,
|
Code = (ex as McpException)?.ErrorCode ?? ErrorCodes.InternalError,
|
||||||
Message = ex.Message
|
Message = ex.Message
|
||||||
}
|
}
|
||||||
}, cancellationToken).ConfigureAwait(false);
|
}, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
@ -298,7 +297,7 @@ internal sealed class McpSession : IDisposable
|
||||||
if (!_requestHandlers.TryGetValue(request.Method, out var handler))
|
if (!_requestHandlers.TryGetValue(request.Method, out var handler))
|
||||||
{
|
{
|
||||||
_logger.NoHandlerFoundForRequest(EndpointName, request.Method);
|
_logger.NoHandlerFoundForRequest(EndpointName, request.Method);
|
||||||
throw new McpServerException("The method does not exist or is not available.", ErrorCodes.MethodNotFound);
|
throw new McpException("The method does not exist or is not available.", ErrorCodes.MethodNotFound);
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.RequestHandlerCalled(EndpointName, request.Method);
|
_logger.RequestHandlerCalled(EndpointName, request.Method);
|
||||||
|
|
@ -318,14 +317,14 @@ internal sealed class McpSession : IDisposable
|
||||||
/// Use this method for custom requests or those not yet covered explicitly by the endpoint implementation.
|
/// Use this method for custom requests or those not yet covered explicitly by the endpoint implementation.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">The JSON-RPC request to send.</param>
|
/// <param name="request">The JSON-RPC request to send.</param>
|
||||||
/// <param name="cancellationToken">A token to cancel the operation.</param>
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||||
/// <returns>A task containing the server's response.</returns>
|
/// <returns>A task containing the server's response.</returns>
|
||||||
public async Task<JsonRpcResponse> SendRequestAsync(JsonRpcRequest request, CancellationToken cancellationToken)
|
public async Task<JsonRpcResponse> SendRequestAsync(JsonRpcRequest request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (!_transport.IsConnected)
|
if (!_transport.IsConnected)
|
||||||
{
|
{
|
||||||
_logger.EndpointNotConnected(EndpointName);
|
_logger.EndpointNotConnected(EndpointName);
|
||||||
throw new McpClientException("Transport is not connected");
|
throw new McpException("Transport is not connected");
|
||||||
}
|
}
|
||||||
|
|
||||||
Histogram<double> durationMetric = _isServer ? s_serverRequestDuration : s_clientRequestDuration;
|
Histogram<double> durationMetric = _isServer ? s_serverRequestDuration : s_clientRequestDuration;
|
||||||
|
|
@ -372,7 +371,7 @@ internal sealed class McpSession : IDisposable
|
||||||
if (response is JsonRpcError error)
|
if (response is JsonRpcError error)
|
||||||
{
|
{
|
||||||
_logger.RequestFailed(EndpointName, request.Method, error.Error.Message, error.Error.Code);
|
_logger.RequestFailed(EndpointName, request.Method, error.Error.Message, error.Error.Code);
|
||||||
throw new McpClientException($"Request failed (server side): {error.Error.Message}", error.Error.Code);
|
throw new McpException($"Request failed (server side): {error.Error.Message}", error.Error.Code);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response is JsonRpcResponse success)
|
if (response is JsonRpcResponse success)
|
||||||
|
|
@ -384,7 +383,7 @@ internal sealed class McpSession : IDisposable
|
||||||
|
|
||||||
// Unexpected response type
|
// Unexpected response type
|
||||||
_logger.RequestInvalidResponseType(EndpointName, request.Method);
|
_logger.RequestInvalidResponseType(EndpointName, request.Method);
|
||||||
throw new McpClientException("Invalid response type");
|
throw new McpException("Invalid response type");
|
||||||
}
|
}
|
||||||
catch (Exception ex) when (addTags)
|
catch (Exception ex) when (addTags)
|
||||||
{
|
{
|
||||||
|
|
@ -405,7 +404,7 @@ internal sealed class McpSession : IDisposable
|
||||||
if (!_transport.IsConnected)
|
if (!_transport.IsConnected)
|
||||||
{
|
{
|
||||||
_logger.ClientNotConnected(EndpointName);
|
_logger.ClientNotConnected(EndpointName);
|
||||||
throw new McpClientException("Transport is not connected");
|
throw new McpException("Transport is not connected");
|
||||||
}
|
}
|
||||||
|
|
||||||
Histogram<double> durationMetric = _isServer ? s_serverRequestDuration : s_clientRequestDuration;
|
Histogram<double> durationMetric = _isServer ? s_serverRequestDuration : s_clientRequestDuration;
|
||||||
|
|
@ -529,8 +528,7 @@ internal sealed class McpSession : IDisposable
|
||||||
{
|
{
|
||||||
tags.Add("error.type", e.GetType().FullName);
|
tags.Add("error.type", e.GetType().FullName);
|
||||||
tags.Add("rpc.jsonrpc.error_code",
|
tags.Add("rpc.jsonrpc.error_code",
|
||||||
(e as McpClientException)?.ErrorCode is int clientError ? clientError :
|
(e as McpException)?.ErrorCode is int errorCode ? errorCode :
|
||||||
(e as McpServerException)?.ErrorCode is int serverError ? serverError :
|
|
||||||
e is JsonException ? ErrorCodes.ParseError :
|
e is JsonException ? ErrorCodes.ParseError :
|
||||||
ErrorCodes.InternalError);
|
ErrorCodes.InternalError);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -164,7 +164,7 @@ internal static class Program
|
||||||
{
|
{
|
||||||
if (request.Params?.Arguments is null || !request.Params.Arguments.TryGetValue("message", out var message))
|
if (request.Params?.Arguments is null || !request.Params.Arguments.TryGetValue("message", out var message))
|
||||||
{
|
{
|
||||||
throw new McpServerException("Missing required argument 'message'");
|
throw new McpException("Missing required argument 'message'");
|
||||||
}
|
}
|
||||||
return new CallToolResponse()
|
return new CallToolResponse()
|
||||||
{
|
{
|
||||||
|
|
@ -177,7 +177,7 @@ internal static class Program
|
||||||
!request.Params.Arguments.TryGetValue("prompt", out var prompt) ||
|
!request.Params.Arguments.TryGetValue("prompt", out var prompt) ||
|
||||||
!request.Params.Arguments.TryGetValue("maxTokens", out var maxTokens))
|
!request.Params.Arguments.TryGetValue("maxTokens", out var maxTokens))
|
||||||
{
|
{
|
||||||
throw new McpServerException("Missing required arguments 'prompt' and 'maxTokens'");
|
throw new McpException("Missing required arguments 'prompt' and 'maxTokens'");
|
||||||
}
|
}
|
||||||
var sampleResult = await request.Server.RequestSamplingAsync(CreateRequestSamplingParams(prompt.ToString(), "sampleLLM", Convert.ToInt32(maxTokens.GetRawText())),
|
var sampleResult = await request.Server.RequestSamplingAsync(CreateRequestSamplingParams(prompt.ToString(), "sampleLLM", Convert.ToInt32(maxTokens.GetRawText())),
|
||||||
cancellationToken);
|
cancellationToken);
|
||||||
|
|
@ -189,7 +189,7 @@ internal static class Program
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new McpServerException($"Unknown tool: {request.Params?.Name}");
|
throw new McpException($"Unknown tool: {request.Params?.Name}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -283,7 +283,7 @@ internal static class Program
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new McpServerException($"Unknown prompt: {request.Params?.Name}");
|
throw new McpException($"Unknown prompt: {request.Params?.Name}");
|
||||||
}
|
}
|
||||||
|
|
||||||
return Task.FromResult(new GetPromptResult()
|
return Task.FromResult(new GetPromptResult()
|
||||||
|
|
@ -304,7 +304,7 @@ internal static class Program
|
||||||
{
|
{
|
||||||
if (request.Params?.Level is null)
|
if (request.Params?.Level is null)
|
||||||
{
|
{
|
||||||
throw new McpServerException("Missing required argument 'level'");
|
throw new McpException("Missing required argument 'level'");
|
||||||
}
|
}
|
||||||
|
|
||||||
_minimumLoggingLevel = request.Params.Level;
|
_minimumLoggingLevel = request.Params.Level;
|
||||||
|
|
@ -384,9 +384,9 @@ internal static class Program
|
||||||
var startIndexAsString = Encoding.UTF8.GetString(Convert.FromBase64String(request.Params.Cursor));
|
var startIndexAsString = Encoding.UTF8.GetString(Convert.FromBase64String(request.Params.Cursor));
|
||||||
startIndex = Convert.ToInt32(startIndexAsString);
|
startIndex = Convert.ToInt32(startIndexAsString);
|
||||||
}
|
}
|
||||||
catch
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
throw new McpServerException("Invalid cursor");
|
throw new McpException("Invalid cursor.", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -408,7 +408,7 @@ internal static class Program
|
||||||
{
|
{
|
||||||
if (request.Params?.Uri is null)
|
if (request.Params?.Uri is null)
|
||||||
{
|
{
|
||||||
throw new McpServerException("Missing required argument 'uri'");
|
throw new McpException("Missing required argument 'uri'");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.Params.Uri.StartsWith("test://dynamic/resource/"))
|
if (request.Params.Uri.StartsWith("test://dynamic/resource/"))
|
||||||
|
|
@ -416,7 +416,7 @@ internal static class Program
|
||||||
var id = request.Params.Uri.Split('/').LastOrDefault();
|
var id = request.Params.Uri.Split('/').LastOrDefault();
|
||||||
if (string.IsNullOrEmpty(id))
|
if (string.IsNullOrEmpty(id))
|
||||||
{
|
{
|
||||||
throw new McpServerException("Invalid resource URI");
|
throw new McpException("Invalid resource URI");
|
||||||
}
|
}
|
||||||
return Task.FromResult(new ReadResourceResult()
|
return Task.FromResult(new ReadResourceResult()
|
||||||
{
|
{
|
||||||
|
|
@ -432,7 +432,7 @@ internal static class Program
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceContents contents = resourceContents.FirstOrDefault(r => r.Uri == request.Params.Uri)
|
ResourceContents contents = resourceContents.FirstOrDefault(r => r.Uri == request.Params.Uri)
|
||||||
?? throw new McpServerException("Resource not found");
|
?? throw new McpException("Resource not found");
|
||||||
|
|
||||||
return Task.FromResult(new ReadResourceResult()
|
return Task.FromResult(new ReadResourceResult()
|
||||||
{
|
{
|
||||||
|
|
@ -444,12 +444,12 @@ internal static class Program
|
||||||
{
|
{
|
||||||
if (request?.Params?.Uri is null)
|
if (request?.Params?.Uri is null)
|
||||||
{
|
{
|
||||||
throw new McpServerException("Missing required argument 'uri'");
|
throw new McpException("Missing required argument 'uri'");
|
||||||
}
|
}
|
||||||
if (!request.Params.Uri.StartsWith("test://static/resource/")
|
if (!request.Params.Uri.StartsWith("test://static/resource/")
|
||||||
&& !request.Params.Uri.StartsWith("test://dynamic/resource/"))
|
&& !request.Params.Uri.StartsWith("test://dynamic/resource/"))
|
||||||
{
|
{
|
||||||
throw new McpServerException("Invalid resource URI");
|
throw new McpException("Invalid resource URI");
|
||||||
}
|
}
|
||||||
|
|
||||||
_subscribedResources.TryAdd(request.Params.Uri, true);
|
_subscribedResources.TryAdd(request.Params.Uri, true);
|
||||||
|
|
@ -461,12 +461,12 @@ internal static class Program
|
||||||
{
|
{
|
||||||
if (request?.Params?.Uri is null)
|
if (request?.Params?.Uri is null)
|
||||||
{
|
{
|
||||||
throw new McpServerException("Missing required argument 'uri'");
|
throw new McpException("Missing required argument 'uri'");
|
||||||
}
|
}
|
||||||
if (!request.Params.Uri.StartsWith("test://static/resource/")
|
if (!request.Params.Uri.StartsWith("test://static/resource/")
|
||||||
&& !request.Params.Uri.StartsWith("test://dynamic/resource/"))
|
&& !request.Params.Uri.StartsWith("test://dynamic/resource/"))
|
||||||
{
|
{
|
||||||
throw new McpServerException("Invalid resource URI");
|
throw new McpException("Invalid resource URI");
|
||||||
}
|
}
|
||||||
|
|
||||||
_subscribedResources.Remove(request.Params.Uri, out _);
|
_subscribedResources.Remove(request.Params.Uri, out _);
|
||||||
|
|
@ -511,7 +511,7 @@ internal static class Program
|
||||||
return Task.FromResult(new CompleteResult() { Completion = new() { Values = values, HasMore = false, Total = values.Length } });
|
return Task.FromResult(new CompleteResult() { Completion = new() { Values = values, HasMore = false, Total = values.Length } });
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new McpServerException($"Unknown reference type: {request.Params?.Ref.Type}");
|
throw new McpException($"Unknown reference type: {request.Params?.Ref.Type}");
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -154,13 +154,13 @@ public class Program
|
||||||
{
|
{
|
||||||
if (request.Params is null)
|
if (request.Params is null)
|
||||||
{
|
{
|
||||||
throw new McpServerException("Missing required parameter 'name'");
|
throw new McpException("Missing required parameter 'name'");
|
||||||
}
|
}
|
||||||
if (request.Params.Name == "echo")
|
if (request.Params.Name == "echo")
|
||||||
{
|
{
|
||||||
if (request.Params.Arguments is null || !request.Params.Arguments.TryGetValue("message", out var message))
|
if (request.Params.Arguments is null || !request.Params.Arguments.TryGetValue("message", out var message))
|
||||||
{
|
{
|
||||||
throw new McpServerException("Missing required argument 'message'");
|
throw new McpException("Missing required argument 'message'");
|
||||||
}
|
}
|
||||||
return new CallToolResponse()
|
return new CallToolResponse()
|
||||||
{
|
{
|
||||||
|
|
@ -173,7 +173,7 @@ public class Program
|
||||||
!request.Params.Arguments.TryGetValue("prompt", out var prompt) ||
|
!request.Params.Arguments.TryGetValue("prompt", out var prompt) ||
|
||||||
!request.Params.Arguments.TryGetValue("maxTokens", out var maxTokens))
|
!request.Params.Arguments.TryGetValue("maxTokens", out var maxTokens))
|
||||||
{
|
{
|
||||||
throw new McpServerException("Missing required arguments 'prompt' and 'maxTokens'");
|
throw new McpException("Missing required arguments 'prompt' and 'maxTokens'");
|
||||||
}
|
}
|
||||||
var sampleResult = await request.Server.RequestSamplingAsync(CreateRequestSamplingParams(prompt.ToString(), "sampleLLM", Convert.ToInt32(maxTokens.ToString())),
|
var sampleResult = await request.Server.RequestSamplingAsync(CreateRequestSamplingParams(prompt.ToString(), "sampleLLM", Convert.ToInt32(maxTokens.ToString())),
|
||||||
cancellationToken);
|
cancellationToken);
|
||||||
|
|
@ -185,7 +185,7 @@ public class Program
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new McpServerException($"Unknown tool: {request.Params.Name}");
|
throw new McpException($"Unknown tool: {request.Params.Name}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -219,7 +219,7 @@ public class Program
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
throw new McpServerException("Invalid cursor");
|
throw new McpException("Invalid cursor");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -240,7 +240,7 @@ public class Program
|
||||||
{
|
{
|
||||||
if (request.Params?.Uri is null)
|
if (request.Params?.Uri is null)
|
||||||
{
|
{
|
||||||
throw new McpServerException("Missing required argument 'uri'");
|
throw new McpException("Missing required argument 'uri'");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.Params.Uri.StartsWith("test://dynamic/resource/"))
|
if (request.Params.Uri.StartsWith("test://dynamic/resource/"))
|
||||||
|
|
@ -248,7 +248,7 @@ public class Program
|
||||||
var id = request.Params.Uri.Split('/').LastOrDefault();
|
var id = request.Params.Uri.Split('/').LastOrDefault();
|
||||||
if (string.IsNullOrEmpty(id))
|
if (string.IsNullOrEmpty(id))
|
||||||
{
|
{
|
||||||
throw new McpServerException("Invalid resource URI");
|
throw new McpException("Invalid resource URI");
|
||||||
}
|
}
|
||||||
return Task.FromResult(new ReadResourceResult()
|
return Task.FromResult(new ReadResourceResult()
|
||||||
{
|
{
|
||||||
|
|
@ -264,7 +264,7 @@ public class Program
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceContents? contents = resourceContents.FirstOrDefault(r => r.Uri == request.Params.Uri) ??
|
ResourceContents? contents = resourceContents.FirstOrDefault(r => r.Uri == request.Params.Uri) ??
|
||||||
throw new McpServerException("Resource not found");
|
throw new McpException("Resource not found");
|
||||||
|
|
||||||
return Task.FromResult(new ReadResourceResult()
|
return Task.FromResult(new ReadResourceResult()
|
||||||
{
|
{
|
||||||
|
|
@ -311,7 +311,7 @@ public class Program
|
||||||
{
|
{
|
||||||
if (request.Params is null)
|
if (request.Params is null)
|
||||||
{
|
{
|
||||||
throw new McpServerException("Missing required parameter 'name'");
|
throw new McpException("Missing required parameter 'name'");
|
||||||
}
|
}
|
||||||
List<PromptMessage> messages = new();
|
List<PromptMessage> messages = new();
|
||||||
if (request.Params.Name == "simple_prompt")
|
if (request.Params.Name == "simple_prompt")
|
||||||
|
|
@ -361,7 +361,7 @@ public class Program
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new McpServerException($"Unknown prompt: {request.Params.Name}");
|
throw new McpException($"Unknown prompt: {request.Params.Name}");
|
||||||
}
|
}
|
||||||
|
|
||||||
return Task.FromResult(new GetPromptResult()
|
return Task.FromResult(new GetPromptResult()
|
||||||
|
|
|
||||||
|
|
@ -175,7 +175,7 @@ public class ClientIntegrationTests : LoggedTest, IClassFixture<ClientIntegratio
|
||||||
|
|
||||||
// act
|
// act
|
||||||
await using var client = await _fixture.CreateClientAsync(clientId);
|
await using var client = await _fixture.CreateClientAsync(clientId);
|
||||||
await Assert.ThrowsAsync<McpClientException>(() =>
|
await Assert.ThrowsAsync<McpException>(() =>
|
||||||
client.GetPromptAsync("non_existent_prompt", null, cancellationToken: TestContext.Current.CancellationToken));
|
client.GetPromptAsync("non_existent_prompt", null, cancellationToken: TestContext.Current.CancellationToken));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue