Improve progress reporting (#145)
* Improve progress reporting - Enable injecting an `IProgress<>` into a tool call to report progress when the client has supplied a progress token - Add a custom type for ProgressToken and ProgressNotification to map to the schema - Simplify RequestId to match ProgressToken's shape - Serialize StdioClientTransport's SendMessageAsync implementation - Add strongly-typed names for all request methods - Change all request IDs created by McpJsonRpcEndpoint to include a guid for that endpoint * Address PR feedback
This commit is contained in:
parent
0294c574a6
commit
2c75acded8
1 changed files with 627 additions and 228 deletions
|
|
@ -129,7 +129,7 @@ public class McpServerTests : LoggedTest
|
|||
Assert.NotNull(result);
|
||||
Assert.NotEmpty(transport.SentMessages);
|
||||
Assert.IsType<JsonRpcRequest>(transport.SentMessages[0]);
|
||||
Assert.Equal("sampling/createMessage", ((JsonRpcRequest)transport.SentMessages[0]).Method);
|
||||
Assert.Equal(RequestMethods.SamplingCreateMessage, ((JsonRpcRequest)transport.SentMessages[0]).Method);
|
||||
|
||||
await transport.DisposeAsync();
|
||||
await runTask;
|
||||
|
|
@ -162,7 +162,7 @@ public class McpServerTests : LoggedTest
|
|||
Assert.NotNull(result);
|
||||
Assert.NotEmpty(transport.SentMessages);
|
||||
Assert.IsType<JsonRpcRequest>(transport.SentMessages[0]);
|
||||
Assert.Equal("roots/list", ((JsonRpcRequest)transport.SentMessages[0]).Method);
|
||||
Assert.Equal(RequestMethods.RootsList, ((JsonRpcRequest)transport.SentMessages[0]).Method);
|
||||
|
||||
await transport.DisposeAsync();
|
||||
await runTask;
|
||||
|
|
@ -185,7 +185,7 @@ public class McpServerTests : LoggedTest
|
|||
{
|
||||
await Can_Handle_Requests(
|
||||
serverCapabilities: null,
|
||||
method: "ping",
|
||||
method: RequestMethods.Ping,
|
||||
configureOptions: null,
|
||||
assertResult: response =>
|
||||
{
|
||||
|
|
@ -198,7 +198,7 @@ public class McpServerTests : LoggedTest
|
|||
{
|
||||
await Can_Handle_Requests(
|
||||
serverCapabilities: null,
|
||||
method: "initialize",
|
||||
method: RequestMethods.Initialize,
|
||||
configureOptions: null,
|
||||
assertResult: response =>
|
||||
{
|
||||
|
|
@ -216,7 +216,7 @@ public class McpServerTests : LoggedTest
|
|||
{
|
||||
await Can_Handle_Requests(
|
||||
serverCapabilities: null,
|
||||
method: "completion/complete",
|
||||
method: RequestMethods.CompletionComplete,
|
||||
configureOptions: null,
|
||||
assertResult: response =>
|
||||
{
|
||||
|
|
@ -235,7 +235,7 @@ public class McpServerTests : LoggedTest
|
|||
{
|
||||
await Can_Handle_Requests(
|
||||
serverCapabilities: null,
|
||||
method: "completion/complete",
|
||||
method: RequestMethods.CompletionComplete,
|
||||
configureOptions: options =>
|
||||
{
|
||||
options.GetCompletionHandler = (request, ct) =>
|
||||
|
|
@ -287,7 +287,7 @@ public class McpServerTests : LoggedTest
|
|||
ReadResourceHandler = (request, ct) => throw new NotImplementedException(),
|
||||
}
|
||||
},
|
||||
"resources/templates/list",
|
||||
RequestMethods.ResourcesTemplatesList,
|
||||
configureOptions: null,
|
||||
assertResult: response =>
|
||||
{
|
||||
|
|
@ -318,7 +318,7 @@ public class McpServerTests : LoggedTest
|
|||
ReadResourceHandler = (request, ct) => throw new NotImplementedException(),
|
||||
}
|
||||
},
|
||||
"resources/list",
|
||||
RequestMethods.ResourcesList,
|
||||
configureOptions: null,
|
||||
assertResult: response =>
|
||||
{
|
||||
|
|
@ -334,7 +334,7 @@ public class McpServerTests : LoggedTest
|
|||
[Fact]
|
||||
public async Task Can_Handle_Resources_List_Requests_Throws_Exception_If_No_Handler_Assigned()
|
||||
{
|
||||
await Throws_Exception_If_No_Handler_Assigned(new ServerCapabilities { Resources = new() }, "resources/list", "ListResources handler not configured");
|
||||
await Throws_Exception_If_No_Handler_Assigned(new ServerCapabilities { Resources = new() }, RequestMethods.ResourcesList, "ListResources handler not configured");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -355,7 +355,7 @@ public class McpServerTests : LoggedTest
|
|||
ListResourcesHandler = (request, ct) => throw new NotImplementedException(),
|
||||
}
|
||||
},
|
||||
method: "resources/read",
|
||||
method: RequestMethods.ResourcesRead,
|
||||
configureOptions: null,
|
||||
assertResult: response =>
|
||||
{
|
||||
|
|
@ -373,7 +373,7 @@ public class McpServerTests : LoggedTest
|
|||
[Fact]
|
||||
public async Task Can_Handle_Resources_Read_Requests_Throws_Exception_If_No_Handler_Assigned()
|
||||
{
|
||||
await Throws_Exception_If_No_Handler_Assigned(new ServerCapabilities { Resources = new() }, "resources/read", "ReadResource handler not configured");
|
||||
await Throws_Exception_If_No_Handler_Assigned(new ServerCapabilities { Resources = new() }, RequestMethods.ResourcesRead, "ReadResource handler not configured");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -394,7 +394,7 @@ public class McpServerTests : LoggedTest
|
|||
GetPromptHandler = (request, ct) => throw new NotImplementedException(),
|
||||
},
|
||||
},
|
||||
method: "prompts/list",
|
||||
method: RequestMethods.PromptsList,
|
||||
configureOptions: null,
|
||||
assertResult: response =>
|
||||
{
|
||||
|
|
@ -410,7 +410,7 @@ public class McpServerTests : LoggedTest
|
|||
[Fact]
|
||||
public async Task Can_Handle_List_Prompts_Requests_Throws_Exception_If_No_Handler_Assigned()
|
||||
{
|
||||
await Throws_Exception_If_No_Handler_Assigned(new ServerCapabilities { Prompts = new() }, "prompts/list", "ListPrompts handler not configured");
|
||||
await Throws_Exception_If_No_Handler_Assigned(new ServerCapabilities { Prompts = new() }, RequestMethods.PromptsList, "ListPrompts handler not configured");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -425,7 +425,7 @@ public class McpServerTests : LoggedTest
|
|||
ListPromptsHandler = (request, ct) => throw new NotImplementedException(),
|
||||
}
|
||||
},
|
||||
method: "prompts/get",
|
||||
method: RequestMethods.PromptsGet,
|
||||
configureOptions: null,
|
||||
assertResult: response =>
|
||||
{
|
||||
|
|
@ -439,7 +439,7 @@ public class McpServerTests : LoggedTest
|
|||
[Fact]
|
||||
public async Task Can_Handle_Get_Prompts_Requests_Throws_Exception_If_No_Handler_Assigned()
|
||||
{
|
||||
await Throws_Exception_If_No_Handler_Assigned(new ServerCapabilities { Prompts = new() }, "prompts/get", "GetPrompt handler not configured");
|
||||
await Throws_Exception_If_No_Handler_Assigned(new ServerCapabilities { Prompts = new() }, RequestMethods.PromptsGet, "GetPrompt handler not configured");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -460,7 +460,7 @@ public class McpServerTests : LoggedTest
|
|||
CallToolHandler = (request, ct) => throw new NotImplementedException(),
|
||||
}
|
||||
},
|
||||
method: "tools/list",
|
||||
method: RequestMethods.ToolsList,
|
||||
configureOptions: null,
|
||||
assertResult: response =>
|
||||
{
|
||||
|
|
@ -475,7 +475,7 @@ public class McpServerTests : LoggedTest
|
|||
[Fact]
|
||||
public async Task Can_Handle_List_Tools_Requests_Throws_Exception_If_No_Handler_Assigned()
|
||||
{
|
||||
await Throws_Exception_If_No_Handler_Assigned(new ServerCapabilities { Tools = new() }, "tools/list", "ListTools handler not configured");
|
||||
await Throws_Exception_If_No_Handler_Assigned(new ServerCapabilities { Tools = new() }, RequestMethods.ToolsList, "ListTools handler not configured");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -496,7 +496,7 @@ public class McpServerTests : LoggedTest
|
|||
ListToolsHandler = (request, ct) => throw new NotImplementedException(),
|
||||
}
|
||||
},
|
||||
method: "tools/call",
|
||||
method: RequestMethods.ToolsCall,
|
||||
configureOptions: null,
|
||||
assertResult: response =>
|
||||
{
|
||||
|
|
@ -511,7 +511,7 @@ public class McpServerTests : LoggedTest
|
|||
[Fact]
|
||||
public async Task Can_Handle_Call_Tool_Requests_Throws_Exception_If_No_Handler_Assigned()
|
||||
{
|
||||
await Throws_Exception_If_No_Handler_Assigned(new ServerCapabilities { Tools = new() }, "tools/call", "CallTool handler not configured");
|
||||
await Throws_Exception_If_No_Handler_Assigned(new ServerCapabilities { Tools = new() }, RequestMethods.ToolsCall, "CallTool handler not configured");
|
||||
}
|
||||
|
||||
private async Task Can_Handle_Requests(ServerCapabilities? serverCapabilities, string method, Action<McpServerOptions>? configureOptions, Action<object> assertResult)
|
||||
|
|
@ -528,7 +528,7 @@ public class McpServerTests : LoggedTest
|
|||
|
||||
transport.OnMessageSent = (message) =>
|
||||
{
|
||||
if (message is JsonRpcResponse response && response.Id.AsNumber == 55)
|
||||
if (message is JsonRpcResponse response && response.Id.ToString() == "55")
|
||||
receivedMessage.SetResult(response);
|
||||
};
|
||||
|
||||
|
|
@ -536,7 +536,7 @@ public class McpServerTests : LoggedTest
|
|||
new JsonRpcRequest
|
||||
{
|
||||
Method = method,
|
||||
Id = RequestId.FromNumber(55)
|
||||
Id = new RequestId(55)
|
||||
}
|
||||
);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue