Add elicitation capability (#467)

* Add elicitation capability
This commit is contained in:
Stephen Toub 2025-05-29 22:03:03 -04:00 • committed by GitHub
commit 5cc7c00456
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -136,6 +136,26 @@ public class StatelessServerTests(ITestOutputHelper outputHelper) : KestrelInMem
Assert.Equal("Server to client requests are not supported in stateless mode.", toolContent.Text);
}
[Fact]
public async Task ElicitRequest_Fails_WithInvalidOperationException()
{
await StartAsync();
var mcpClientOptions = new McpClientOptions();
mcpClientOptions.Capabilities = new();
mcpClientOptions.Capabilities.Elicitation ??= new();
mcpClientOptions.Capabilities.Elicitation.ElicitationHandler = (_, _) =>
{
throw new UnreachableException();
};
await using var client = await ConnectMcpClientAsync(mcpClientOptions);
var toolResponse = await client.CallToolAsync("testElicitationErrors", cancellationToken: TestContext.Current.CancellationToken);
var toolContent = Assert.Single(toolResponse.Content);
Assert.Equal("Server to client requests are not supported in stateless mode.", toolContent.Text);
}
[Fact]
public async Task UnsolicitedNotification_Fails_WithInvalidOperationException()
{
@ -184,7 +204,7 @@ public class StatelessServerTests(ITestOutputHelper outputHelper) : KestrelInMem
var asSamplingChatClientEx = Assert.Throws<InvalidOperationException>(() => server.AsSamplingChatClient());
Assert.Equal(expectedSamplingErrorMessage, asSamplingChatClientEx.Message);
var requestSamplingEx = await Assert.ThrowsAsync<InvalidOperationException>(() => server.RequestSamplingAsync([]));
var requestSamplingEx = await Assert.ThrowsAsync<InvalidOperationException>(() => server.SampleAsync([]));
Assert.Equal(expectedSamplingErrorMessage, requestSamplingEx.Message);
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => server.SendRequestAsync(new JsonRpcRequest { Method = RequestMethods.SamplingCreateMessage }));
@ -206,6 +226,21 @@ public class StatelessServerTests(ITestOutputHelper outputHelper) : KestrelInMem
return ex.Message;
}
[McpServerTool(Name = "testElicitationErrors")]
public static async Task<string> TestElicitationErrors(IMcpServer server)
{
const string expectedElicitationErrorMessage = "Elicitation is not supported in stateless mode.";
// Even when the client has elicitation support, it should not be advertised in stateless mode.
Assert.Null(server.ClientCapabilities);
var requestElicitationEx = Assert.Throws<InvalidOperationException>(() => server.ElicitAsync(new()));
Assert.Equal(expectedElicitationErrorMessage, requestElicitationEx.Message);
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => server.SendRequestAsync(new JsonRpcRequest { Method = RequestMethods.ElicitationCreate }));
return ex.Message;
}
[McpServerTool(Name = "testScope")]
public static string? TestScope(ScopedService scopedService) => scopedService.State;