Add server "completions" capability (#232)

* Split apart Capabilities.cs

No code changes, just moving each type to its own file.

* Add server completions capability
This commit is contained in:
Stephen Toub 2025-04-07 16:59:37 -04:00 • committed by GitHub
commit 82510d5629
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 321 additions and 272 deletions

View file

@ -115,7 +115,7 @@ builder.Services
}
return Task.FromResult(new EmptyResult());
})
.WithGetCompletionHandler((ctx, ct) =>
.WithCompleteHandler((ctx, ct) =>
{
var exampleCompletions = new Dictionary<string, IEnumerable<string>>
{

View file

@ -386,7 +386,7 @@ public static class McpClientExtensions
/// <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="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> CompleteAsync(this IMcpClient client, Reference reference, string argumentName, string argumentValue, CancellationToken cancellationToken = default)
{
Throw.IfNull(client);
Throw.IfNull(reference);

View file

@ -288,15 +288,15 @@ public static partial class McpServerBuilderExtensions
}
/// <summary>
/// Sets the handler for get completion requests.
/// Sets the handler for completion complete requests.
/// </summary>
/// <param name="builder">The builder instance.</param>
/// <param name="handler">The handler.</param>
public static IMcpServerBuilder WithGetCompletionHandler(this IMcpServerBuilder builder, Func<RequestContext<CompleteRequestParams>, CancellationToken, Task<CompleteResult>> handler)
public static IMcpServerBuilder WithCompleteHandler(this IMcpServerBuilder builder, Func<RequestContext<CompleteRequestParams>, CancellationToken, Task<CompleteResult>> handler)
{
Throw.IfNull(builder);
builder.Services.Configure<McpServerHandlers>(s => s.GetCompletionHandler = handler);
builder.Services.Configure<McpServerHandlers>(s => s.CompleteHandler = handler);
return builder;
}

View file

@ -1,207 +0,0 @@
using ModelContextProtocol.Protocol.Messages;
using ModelContextProtocol.Server;
using System.Text.Json.Serialization;
namespace ModelContextProtocol.Protocol.Types;
/// <summary>
/// Represents the capabilities that a client may support.
/// <see href="https://github.com/modelcontextprotocol/specification/blob/main/schema/">See the schema for details</see>
/// </summary>
public class ClientCapabilities
{
/// <summary>
/// Experimental, non-standard capabilities that the client supports.
/// </summary>
[JsonPropertyName("experimental")]
public Dictionary<string, object>? Experimental { get; set; }
/// <summary>
/// Present if the client supports listing roots.
/// </summary>
[JsonPropertyName("roots")]
public RootsCapability? Roots { get; set; }
/// <summary>
/// Present if the client supports sampling from an LLM.
/// </summary>
[JsonPropertyName("sampling")]
public SamplingCapability? Sampling { get; set; }
/// <summary>Gets or sets notification handlers to register with the client.</summary>
/// <remarks>
/// When constructed, the client will enumerate these handlers, which may contain multiple handlers per key.
/// The client will not re-enumerate the sequence.
/// </remarks>
[JsonIgnore]
public IEnumerable<KeyValuePair<string, Func<JsonRpcNotification, CancellationToken, Task>>>? NotificationHandlers { get; set; }
}
/// <summary>
/// Represents the roots capability configuration.
/// <see href="https://github.com/modelcontextprotocol/specification/blob/main/schema/">See the schema for details</see>
/// </summary>
public class RootsCapability
{
/// <summary>
/// Whether the client supports notifications for changes to the roots list.
/// </summary>
[JsonPropertyName("listChanged")]
public bool? ListChanged { get; set; }
/// <summary>Gets or sets the handler for sampling requests.</summary>
[JsonIgnore]
public Func<ListRootsRequestParams?, CancellationToken, Task<ListRootsResult>>? RootsHandler { get; set; }
}
/// <summary>
/// Represents the sampling capability configuration.
/// <see href="https://github.com/modelcontextprotocol/specification/blob/main/schema/">See the schema for details</see>
/// </summary>
public class SamplingCapability
{
// Currently empty in the spec, but may be extended in the future
/// <summary>Gets or sets the handler for sampling requests.</summary>
[JsonIgnore]
public Func<CreateMessageRequestParams?, IProgress<ProgressNotificationValue>, CancellationToken, Task<CreateMessageResult>>? SamplingHandler { get; set; }
}
/// <summary>
/// Represents the logging capability configuration.
/// <see href="https://github.com/modelcontextprotocol/specification/blob/main/schema/">See the schema for details</see>
/// </summary>
public class LoggingCapability
{
// Currently empty in the spec, but may be extended in the future
/// <summary>
/// Gets or sets the handler for set logging level requests.
/// </summary>
[JsonIgnore]
public Func<RequestContext<SetLevelRequestParams>, CancellationToken, Task<EmptyResult>>? SetLoggingLevelHandler { get; set; }
}
/// <summary>
/// Represents the prompts capability configuration.
/// <see href="https://github.com/modelcontextprotocol/specification/blob/main/schema/">See the schema for details</see>
/// </summary>
public class PromptsCapability
{
/// <summary>
/// Whether this server supports notifications for changes to the prompt list.
/// </summary>
[JsonPropertyName("listChanged")]
public bool? ListChanged { get; set; }
/// <summary>
/// Gets or sets the handler for list prompts requests.
/// </summary>
[JsonIgnore]
public Func<RequestContext<ListPromptsRequestParams>, CancellationToken, Task<ListPromptsResult>>? ListPromptsHandler { get; set; }
/// <summary>
/// Gets or sets the handler for get prompt requests.
/// </summary>
[JsonIgnore]
public Func<RequestContext<GetPromptRequestParams>, CancellationToken, Task<GetPromptResult>>? GetPromptHandler { get; set; }
/// <summary>Gets or sets a collection of prompts served by the server.</summary>
/// <remarks>
/// Prompts will specified via <see cref="PromptCollection"/> augment the <see cref="ListPromptsHandler"/> and
/// <see cref="GetPromptHandler"/>, if provided. ListPrompts requests will output information about every prompt
/// in <see cref="PromptCollection"/> and then also any tools output by <see cref="ListPromptsHandler"/>, if it's
/// non-<see langword="null"/>. GetPrompt requests will first check <see cref="PromptCollection"/> for the prompt
/// being requested, and if the tool is not found in the <see cref="PromptCollection"/>, any specified <see cref="GetPromptHandler"/>
/// will be invoked as a fallback.
/// </remarks>
[JsonIgnore]
public McpServerPrimitiveCollection<McpServerPrompt>? PromptCollection { get; set; }
}
/// <summary>
/// Represents the resources capability configuration.
/// <see href="https://github.com/modelcontextprotocol/specification/blob/main/schema/">See the schema for details</see>
/// </summary>
public class ResourcesCapability
{
/// <summary>
/// Whether this server supports subscribing to resource updates.
/// </summary>
[JsonPropertyName("subscribe")]
public bool? Subscribe { get; set; }
/// <summary>
/// Whether this server supports notifications for changes to the resource list.
/// </summary>
[JsonPropertyName("listChanged")]
public bool? ListChanged { get; set; }
/// <summary>
/// Gets or sets the handler for list resource templates requests.
/// </summary>
[JsonIgnore]
public Func<RequestContext<ListResourceTemplatesRequestParams>, CancellationToken, Task<ListResourceTemplatesResult>>? ListResourceTemplatesHandler { get; set; }
/// <summary>
/// Gets or sets the handler for list resources requests.
/// </summary>
[JsonIgnore]
public Func<RequestContext<ListResourcesRequestParams>, CancellationToken, Task<ListResourcesResult>>? ListResourcesHandler { get; set; }
/// <summary>
/// Gets or sets the handler for read resources requests.
/// </summary>
[JsonIgnore]
public Func<RequestContext<ReadResourceRequestParams>, CancellationToken, Task<ReadResourceResult>>? ReadResourceHandler { get; set; }
/// <summary>
/// Gets or sets the handler for subscribe to resources messages.
/// </summary>
[JsonIgnore]
public Func<RequestContext<SubscribeRequestParams>, CancellationToken, Task<EmptyResult>>? SubscribeToResourcesHandler { get; set; }
/// <summary>
/// Gets or sets the handler for unsubscribe from resources messages.
/// </summary>
[JsonIgnore]
public Func<RequestContext<UnsubscribeRequestParams>, CancellationToken, Task<EmptyResult>>? UnsubscribeFromResourcesHandler { get; set; }
}
/// <summary>
/// Represents the tools capability configuration.
/// <see href="https://github.com/modelcontextprotocol/specification/blob/main/schema/">See the schema for details</see>
/// </summary>
public class ToolsCapability
{
/// <summary>
/// Gets or sets whether this server supports notifications for changes to the tool list.
/// </summary>
[JsonPropertyName("listChanged")]
public bool? ListChanged { get; set; }
/// <summary>
/// Gets or sets the handler for list tools requests.
/// </summary>
[JsonIgnore]
public Func<RequestContext<ListToolsRequestParams>, CancellationToken, Task<ListToolsResult>>? ListToolsHandler { get; set; }
/// <summary>
/// Gets or sets the handler for call tool requests.
/// </summary>
[JsonIgnore]
public Func<RequestContext<CallToolRequestParams>, CancellationToken, Task<CallToolResponse>>? CallToolHandler { get; set; }
/// <summary>Gets or sets a collection of tools served by the server.</summary>
/// <remarks>
/// Tools will specified via <see cref="ToolCollection"/> augment the <see cref="ListToolsHandler"/> and
/// <see cref="CallToolHandler"/>, if provided. ListTools requests will output information about every tool
/// in <see cref="ToolCollection"/> and then also any tools output by <see cref="ListToolsHandler"/>, if it's
/// non-<see langword="null"/>. CallTool requests will first check <see cref="ToolCollection"/> for the tool
/// being requested, and if the tool is not found in the <see cref="ToolCollection"/>, any specified <see cref="CallToolHandler"/>
/// will be invoked as a fallback.
/// </remarks>
[JsonIgnore]
public McpServerPrimitiveCollection<McpServerTool>? ToolCollection { get; set; }
}

View file

@ -0,0 +1,38 @@
using ModelContextProtocol.Protocol.Messages;
using ModelContextProtocol.Server;
using System.Text.Json.Serialization;
namespace ModelContextProtocol.Protocol.Types;
/// <summary>
/// Represents the capabilities that a client may support.
/// <see href="https://github.com/modelcontextprotocol/specification/blob/main/schema/">See the schema for details</see>
/// </summary>
public class ClientCapabilities
{
/// <summary>
/// Experimental, non-standard capabilities that the client supports.
/// </summary>
[JsonPropertyName("experimental")]
public Dictionary<string, object>? Experimental { get; set; }
/// <summary>
/// Present if the client supports listing roots.
/// </summary>
[JsonPropertyName("roots")]
public RootsCapability? Roots { get; set; }
/// <summary>
/// Present if the client supports sampling from an LLM.
/// </summary>
[JsonPropertyName("sampling")]
public SamplingCapability? Sampling { get; set; }
/// <summary>Gets or sets notification handlers to register with the client.</summary>
/// <remarks>
/// When constructed, the client will enumerate these handlers, which may contain multiple handlers per key.
/// The client will not re-enumerate the sequence.
/// </remarks>
[JsonIgnore]
public IEnumerable<KeyValuePair<string, Func<JsonRpcNotification, CancellationToken, Task>>>? NotificationHandlers { get; set; }
}

View file

@ -0,0 +1,19 @@
using ModelContextProtocol.Server;
using System.Text.Json.Serialization;
namespace ModelContextProtocol.Protocol.Types;
/// <summary>
/// Represents the completions capability configuration.
/// <see href="https://github.com/modelcontextprotocol/specification/blob/main/schema/">See the schema for details</see>
/// </summary>
public class CompletionsCapability
{
// Currently empty in the spec, but may be extended in the future.
/// <summary>
/// Gets or sets the handler for get completion requests.
/// </summary>
[JsonIgnore]
public Func<RequestContext<CompleteRequestParams>, CancellationToken, Task<CompleteResult>>? CompleteHandler { get; set; }
}

View file

@ -0,0 +1,21 @@
using ModelContextProtocol.Protocol.Messages;
using ModelContextProtocol.Server;
using System.Text.Json.Serialization;
namespace ModelContextProtocol.Protocol.Types;
/// <summary>
/// Represents the logging capability configuration.
/// <see href="https://github.com/modelcontextprotocol/specification/blob/main/schema/">See the schema for details</see>
/// </summary>
public class LoggingCapability
{
// Currently empty in the spec, but may be extended in the future
/// <summary>
/// Gets or sets the handler for set logging level requests.
/// </summary>
[JsonIgnore]
public Func<RequestContext<SetLevelRequestParams>, CancellationToken, Task<EmptyResult>>? SetLoggingLevelHandler { get; set; }
}

View file

@ -0,0 +1,42 @@
using ModelContextProtocol.Protocol.Messages;
using ModelContextProtocol.Server;
using System.Text.Json.Serialization;
namespace ModelContextProtocol.Protocol.Types;
/// <summary>
/// Represents the prompts capability configuration.
/// <see href="https://github.com/modelcontextprotocol/specification/blob/main/schema/">See the schema for details</see>
/// </summary>
public class PromptsCapability
{
/// <summary>
/// Whether this server supports notifications for changes to the prompt list.
/// </summary>
[JsonPropertyName("listChanged")]
public bool? ListChanged { get; set; }
/// <summary>
/// Gets or sets the handler for list prompts requests.
/// </summary>
[JsonIgnore]
public Func<RequestContext<ListPromptsRequestParams>, CancellationToken, Task<ListPromptsResult>>? ListPromptsHandler { get; set; }
/// <summary>
/// Gets or sets the handler for get prompt requests.
/// </summary>
[JsonIgnore]
public Func<RequestContext<GetPromptRequestParams>, CancellationToken, Task<GetPromptResult>>? GetPromptHandler { get; set; }
/// <summary>Gets or sets a collection of prompts served by the server.</summary>
/// <remarks>
/// Prompts will specified via <see cref="PromptCollection"/> augment the <see cref="ListPromptsHandler"/> and
/// <see cref="GetPromptHandler"/>, if provided. ListPrompts requests will output information about every prompt
/// in <see cref="PromptCollection"/> and then also any tools output by <see cref="ListPromptsHandler"/>, if it's
/// non-<see langword="null"/>. GetPrompt requests will first check <see cref="PromptCollection"/> for the prompt
/// being requested, and if the tool is not found in the <see cref="PromptCollection"/>, any specified <see cref="GetPromptHandler"/>
/// will be invoked as a fallback.
/// </remarks>
[JsonIgnore]
public McpServerPrimitiveCollection<McpServerPrompt>? PromptCollection { get; set; }
}

View file

@ -0,0 +1,54 @@
using ModelContextProtocol.Protocol.Messages;
using ModelContextProtocol.Server;
using System.Text.Json.Serialization;
namespace ModelContextProtocol.Protocol.Types;
/// <summary>
/// Represents the resources capability configuration.
/// <see href="https://github.com/modelcontextprotocol/specification/blob/main/schema/">See the schema for details</see>
/// </summary>
public class ResourcesCapability
{
/// <summary>
/// Whether this server supports subscribing to resource updates.
/// </summary>
[JsonPropertyName("subscribe")]
public bool? Subscribe { get; set; }
/// <summary>
/// Whether this server supports notifications for changes to the resource list.
/// </summary>
[JsonPropertyName("listChanged")]
public bool? ListChanged { get; set; }
/// <summary>
/// Gets or sets the handler for list resource templates requests.
/// </summary>
[JsonIgnore]
public Func<RequestContext<ListResourceTemplatesRequestParams>, CancellationToken, Task<ListResourceTemplatesResult>>? ListResourceTemplatesHandler { get; set; }
/// <summary>
/// Gets or sets the handler for list resources requests.
/// </summary>
[JsonIgnore]
public Func<RequestContext<ListResourcesRequestParams>, CancellationToken, Task<ListResourcesResult>>? ListResourcesHandler { get; set; }
/// <summary>
/// Gets or sets the handler for read resources requests.
/// </summary>
[JsonIgnore]
public Func<RequestContext<ReadResourceRequestParams>, CancellationToken, Task<ReadResourceResult>>? ReadResourceHandler { get; set; }
/// <summary>
/// Gets or sets the handler for subscribe to resources messages.
/// </summary>
[JsonIgnore]
public Func<RequestContext<SubscribeRequestParams>, CancellationToken, Task<EmptyResult>>? SubscribeToResourcesHandler { get; set; }
/// <summary>
/// Gets or sets the handler for unsubscribe from resources messages.
/// </summary>
[JsonIgnore]
public Func<RequestContext<UnsubscribeRequestParams>, CancellationToken, Task<EmptyResult>>? UnsubscribeFromResourcesHandler { get; set; }
}

View file

@ -0,0 +1,22 @@
using ModelContextProtocol.Protocol.Messages;
using ModelContextProtocol.Server;
using System.Text.Json.Serialization;
namespace ModelContextProtocol.Protocol.Types;
/// <summary>
/// Represents the roots capability configuration.
/// <see href="https://github.com/modelcontextprotocol/specification/blob/main/schema/">See the schema for details</see>
/// </summary>
public class RootsCapability
{
/// <summary>
/// Whether the client supports notifications for changes to the roots list.
/// </summary>
[JsonPropertyName("listChanged")]
public bool? ListChanged { get; set; }
/// <summary>Gets or sets the handler for sampling requests.</summary>
[JsonIgnore]
public Func<ListRootsRequestParams?, CancellationToken, Task<ListRootsResult>>? RootsHandler { get; set; }
}

View file

@ -0,0 +1,18 @@
using ModelContextProtocol.Protocol.Messages;
using ModelContextProtocol.Server;
using System.Text.Json.Serialization;
namespace ModelContextProtocol.Protocol.Types;
/// <summary>
/// Represents the sampling capability configuration.
/// <see href="https://github.com/modelcontextprotocol/specification/blob/main/schema/">See the schema for details</see>
/// </summary>
public class SamplingCapability
{
// Currently empty in the spec, but may be extended in the future
/// <summary>Gets or sets the handler for sampling requests.</summary>
[JsonIgnore]
public Func<CreateMessageRequestParams?, IProgress<ProgressNotificationValue>, CancellationToken, Task<CreateMessageResult>>? SamplingHandler { get; set; }
}

View file

@ -39,6 +39,12 @@ public class ServerCapabilities
[JsonPropertyName("tools")]
public ToolsCapability? Tools { get; set; }
/// <summary>
/// Present if the server supports argument autocompletion suggestions.
/// </summary>
[JsonPropertyName("completions")]
public CompletionsCapability? Completions { get; set; }
/// <summary>Gets or sets notification handlers to register with the server.</summary>
/// <remarks>
/// When constructed, the server will enumerate these handlers, which may contain multiple handlers per key.

View file

@ -0,0 +1,42 @@
using ModelContextProtocol.Protocol.Messages;
using ModelContextProtocol.Server;
using System.Text.Json.Serialization;
namespace ModelContextProtocol.Protocol.Types;
/// <summary>
/// Represents the tools capability configuration.
/// <see href="https://github.com/modelcontextprotocol/specification/blob/main/schema/">See the schema for details</see>
/// </summary>
public class ToolsCapability
{
/// <summary>
/// Gets or sets whether this server supports notifications for changes to the tool list.
/// </summary>
[JsonPropertyName("listChanged")]
public bool? ListChanged { get; set; }
/// <summary>
/// Gets or sets the handler for list tools requests.
/// </summary>
[JsonIgnore]
public Func<RequestContext<ListToolsRequestParams>, CancellationToken, Task<ListToolsResult>>? ListToolsHandler { get; set; }
/// <summary>
/// Gets or sets the handler for call tool requests.
/// </summary>
[JsonIgnore]
public Func<RequestContext<CallToolRequestParams>, CancellationToken, Task<CallToolResponse>>? CallToolHandler { get; set; }
/// <summary>Gets or sets a collection of tools served by the server.</summary>
/// <remarks>
/// Tools will specified via <see cref="ToolCollection"/> augment the <see cref="ListToolsHandler"/> and
/// <see cref="CallToolHandler"/>, if provided. ListTools requests will output information about every tool
/// in <see cref="ToolCollection"/> and then also any tools output by <see cref="ListToolsHandler"/>, if it's
/// non-<see langword="null"/>. CallTool requests will first check <see cref="ToolCollection"/> for the tool
/// being requested, and if the tool is not found in the <see cref="ToolCollection"/>, any specified <see cref="CallToolHandler"/>
/// will be invoked as a fallback.
/// </remarks>
[JsonIgnore]
public McpServerPrimitiveCollection<McpServerTool>? ToolCollection { get; set; }
}

View file

@ -175,11 +175,18 @@ internal sealed class McpServer : McpEndpoint, IMcpServer
private void SetCompletionHandler(McpServerOptions options)
{
if (options.Capabilities?.Completions is not { } completionsCapability)
{
return;
}
var completeHandler = completionsCapability.CompleteHandler ??
throw new McpException("Completions capability was enabled, but Complete handler was not specified.");
// This capability is not optional, so return an empty result if there is no handler.
RequestHandlers.Set(RequestMethods.CompletionComplete,
options.GetCompletionHandler is { } handler ?
(request, cancellationToken) => handler(new(this, request), cancellationToken) :
(request, cancellationToken) => Task.FromResult(new CompleteResult() { Completion = new() { Values = [], Total = 0, HasMore = false } }),
RequestHandlers.Set(
RequestMethods.CompletionComplete,
(request, cancellationToken) => completeHandler(new(this, request), cancellationToken),
McpJsonUtilities.JsonContext.Default.CompleteRequestParams,
McpJsonUtilities.JsonContext.Default.CompleteResult);
}

View file

@ -43,9 +43,9 @@ public sealed class McpServerHandlers
public Func<RequestContext<ReadResourceRequestParams>, CancellationToken, Task<ReadResourceResult>>? ReadResourceHandler { get; set; }
/// <summary>
/// Gets or sets the handler for get completion requests.
/// Gets or sets the handler for completion complete requests.
/// </summary>
public Func<RequestContext<CompleteRequestParams>, CancellationToken, Task<CompleteResult>>? GetCompletionHandler { get; set; }
public Func<RequestContext<CompleteRequestParams>, CancellationToken, Task<CompleteResult>>? CompleteHandler { get; set; }
/// <summary>
/// Gets or sets the handler for subscribe to resources messages.
@ -109,12 +109,18 @@ public sealed class McpServerHandlers
loggingCapability.SetLoggingLevelHandler = SetLoggingLevelHandler;
}
CompletionsCapability? completionsCapability = options.Capabilities?.Completions;
if (CompleteHandler is not null)
{
completionsCapability ??= new();
completionsCapability.CompleteHandler = CompleteHandler;
}
options.Capabilities ??= new();
options.Capabilities.Prompts = promptsCapability;
options.Capabilities.Resources = resourcesCapability;
options.Capabilities.Tools = toolsCapability;
options.Capabilities.Logging = loggingCapability;
options.GetCompletionHandler = GetCompletionHandler ?? options.GetCompletionHandler;
options.Capabilities.Completions = completionsCapability;
}
}

View file

@ -35,10 +35,4 @@ public class McpServerOptions
/// Optional server instructions to send to clients
/// </summary>
public string ServerInstructions { get; set; } = string.Empty;
/// <summary>
/// Gets or sets the handler for get completion requests.
/// </summary>
[JsonIgnore]
public Func<RequestContext<CompleteRequestParams>, CancellationToken, Task<CompleteResult>>? GetCompletionHandler { get; set; }
}

View file

@ -43,11 +43,11 @@ internal static class Program
Tools = ConfigureTools(),
Resources = ConfigureResources(),
Prompts = ConfigurePrompts(),
Logging = ConfigureLogging()
Logging = ConfigureLogging(),
Completions = ConfigureCompletions(),
},
ProtocolVersion = "2024-11-05",
ServerInstructions = "This is a test server with only stub functionality",
GetCompletionHandler = ConfigureCompletion(),
};
using var loggerFactory = CreateLoggerFactory();
@ -477,7 +477,7 @@ internal static class Program
};
}
private static Func<RequestContext<CompleteRequestParams>, CancellationToken, Task<CompleteResult>> ConfigureCompletion()
private static CompletionsCapability ConfigureCompletions()
{
List<string> sampleResourceIds = ["1", "2", "3", "4", "5"];
Dictionary<string, List<string>> exampleCompletions = new()
@ -486,7 +486,7 @@ internal static class Program
{"temperature", ["0", "0.5", "0.7", "1.0"]},
};
return (request, cancellationToken) =>
Func<RequestContext<CompleteRequestParams>, CancellationToken, Task<CompleteResult>> handler = (request, cancellationToken) =>
{
if (request.Params?.Ref?.Type == "ref/resource")
{
@ -512,6 +512,8 @@ internal static class Program
throw new McpException($"Unknown reference type: {request.Params?.Ref.Type}");
};
return new() { CompleteHandler = handler };
}
static CreateMessageRequestParams CreateRequestSamplingParams(string context, string uri, int maxTokens = 100)

View file

@ -314,13 +314,13 @@ public class ClientIntegrationTests : LoggedTest, IClassFixture<ClientIntegratio
[Theory]
[MemberData(nameof(GetClients))]
public async Task GetCompletion_Stdio_ResourceReference(string clientId)
public async Task Complete_Stdio_ResourceReference(string clientId)
{
// arrange
// act
await using var client = await _fixture.CreateClientAsync(clientId);
var result = await client.GetCompletionAsync(new Reference
var result = await client.CompleteAsync(new Reference
{
Type = "ref/resource",
Uri = "test://static/resource/1"
@ -336,13 +336,13 @@ public class ClientIntegrationTests : LoggedTest, IClassFixture<ClientIntegratio
[Theory]
[MemberData(nameof(GetClients))]
public async Task GetCompletion_Stdio_PromptReference(string clientId)
public async Task Complete_Stdio_PromptReference(string clientId)
{
// arrange
// act
await using var client = await _fixture.CreateClientAsync(clientId);
var result = await client.GetCompletionAsync(new Reference
var result = await client.CompleteAsync(new Reference
{
Type = "ref/prompt",
Name = "irrelevant"

View file

@ -110,16 +110,16 @@ public class McpServerBuilderExtensionsHandlerTests
}
[Fact]
public void WithGetCompletionHandler_Sets_Handler()
public void WithCompleteHandler_Sets_Handler()
{
Func<RequestContext<CompleteRequestParams>, CancellationToken, Task<CompleteResult>> handler = (context, token) => Task.FromResult(new CompleteResult());
_builder.Object.WithGetCompletionHandler(handler);
_builder.Object.WithCompleteHandler(handler);
var serviceProvider = _services.BuildServiceProvider();
var options = serviceProvider.GetRequiredService<IOptions<McpServerHandlers>>().Value;
Assert.Equal(handler, options.GetCompletionHandler);
Assert.Equal(handler, options.CompleteHandler);
}
[Fact]

View file

@ -17,7 +17,7 @@ public class McpServerHandlerTests
Assert.Null(handlers.ListResourceTemplatesHandler);
Assert.Null(handlers.ListResourcesHandler);
Assert.Null(handlers.ReadResourceHandler);
Assert.Null(handlers.GetCompletionHandler);
Assert.Null(handlers.CompleteHandler);
Assert.Null(handlers.SubscribeToResourcesHandler);
Assert.Null(handlers.UnsubscribeFromResourcesHandler);
@ -28,7 +28,7 @@ public class McpServerHandlerTests
handlers.ListResourceTemplatesHandler = (p, c) => Task.FromResult(new ListResourceTemplatesResult());
handlers.ListResourcesHandler = (p, c) => Task.FromResult(new ListResourcesResult());
handlers.ReadResourceHandler = (p, c) => Task.FromResult(new ReadResourceResult());
handlers.GetCompletionHandler = (p, c) => Task.FromResult(new CompleteResult());
handlers.CompleteHandler = (p, c) => Task.FromResult(new CompleteResult());
handlers.SubscribeToResourcesHandler = (s, c) => Task.FromResult(new EmptyResult());
handlers.UnsubscribeFromResourcesHandler = (s, c) => Task.FromResult(new EmptyResult());
@ -39,7 +39,7 @@ public class McpServerHandlerTests
Assert.NotNull(handlers.ListResourceTemplatesHandler);
Assert.NotNull(handlers.ListResourcesHandler);
Assert.NotNull(handlers.ReadResourceHandler);
Assert.NotNull(handlers.GetCompletionHandler);
Assert.NotNull(handlers.CompleteHandler);
Assert.NotNull(handlers.SubscribeToResourcesHandler);
Assert.NotNull(handlers.UnsubscribeFromResourcesHandler);
}

Some files were not shown because too many files have changed in this diff Show more