Audit protocol types (#892)

This commit is contained in:
Mackinnon Buck 2025-11-04 18:41:10 -05:00 • committed by GitHub
commit 121929da36
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 262 additions and 168 deletions

View file

@ -16,7 +16,11 @@ public class McpServerExtensionsTests
var server = new Mock<IMcpServer>(MockBehavior.Strict).Object;
var ex = await Assert.ThrowsAsync<InvalidOperationException>(async () => await server.SampleAsync(
new CreateMessageRequestParams { Messages = [new SamplingMessage { Role = Role.User, Content = new TextContentBlock { Text = "hi" } }] },
new CreateMessageRequestParams
{
Messages = [new SamplingMessage { Role = Role.User, Content = new TextContentBlock { Text = "hi" } }],
MaxTokens = 1000
},
TestContext.Current.CancellationToken));
Assert.Contains("Prefer using 'McpServer.SampleAsync' instead", ex.Message);
}
@ -90,6 +94,7 @@ public class McpServerExtensionsTests
.Setup(s => s.SendRequestAsync(It.IsAny<JsonRpcRequest>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(new JsonRpcResponse
{
Id = default,
Result = JsonSerializer.SerializeToNode(resultPayload, McpJsonUtilities.DefaultOptions),
});
@ -97,7 +102,8 @@ public class McpServerExtensionsTests
var result = await server.SampleAsync(new CreateMessageRequestParams
{
Messages = [new SamplingMessage { Role = Role.User, Content = new TextContentBlock { Text = "hi" } }]
Messages = [new SamplingMessage { Role = Role.User, Content = new TextContentBlock { Text = "hi" } }],
MaxTokens = 1000
}, TestContext.Current.CancellationToken);
Assert.Equal("test-model", result.Model);
@ -119,14 +125,28 @@ public class McpServerExtensionsTests
StopReason = "endTurn",
};
const int CustomMaxSamplingOutputTokens = 500;
mockServer
.Setup(s => s.ClientCapabilities)
.Returns(new ClientCapabilities() { Sampling = new() });
mockServer
.Setup(s => s.ServerOptions)
.Returns(new McpServerOptions { MaxSamplingOutputTokens = CustomMaxSamplingOutputTokens });
CreateMessageRequestParams? capturedRequest = null;
mockServer
.Setup(s => s.SendRequestAsync(It.IsAny<JsonRpcRequest>(), It.IsAny<CancellationToken>()))
.Callback<JsonRpcRequest, CancellationToken>((request, _) =>
{
capturedRequest = JsonSerializer.Deserialize<CreateMessageRequestParams>(
request.Params ?? throw new InvalidOperationException(),
McpJsonUtilities.DefaultOptions);
})
.ReturnsAsync(new JsonRpcResponse
{
Id = default,
Result = JsonSerializer.SerializeToNode(resultPayload, McpJsonUtilities.DefaultOptions),
});
@ -139,6 +159,10 @@ public class McpServerExtensionsTests
Assert.Equal(ChatRole.Assistant, last.Role);
Assert.Equal("resp", last.Text);
mockServer.Verify(s => s.SendRequestAsync(It.IsAny<JsonRpcRequest>(), It.IsAny<CancellationToken>()), Times.Once);
// Verify that the default value was used
Assert.NotNull(capturedRequest);
Assert.Equal(CustomMaxSamplingOutputTokens, capturedRequest.MaxTokens);
}
[Fact]
@ -156,6 +180,7 @@ public class McpServerExtensionsTests
.Setup(s => s.SendRequestAsync(It.IsAny<JsonRpcRequest>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(new JsonRpcResponse
{
Id = default,
Result = JsonSerializer.SerializeToNode(resultPayload, McpJsonUtilities.DefaultOptions),
});
@ -182,6 +207,7 @@ public class McpServerExtensionsTests
.Setup(s => s.SendRequestAsync(It.IsAny<JsonRpcRequest>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(new JsonRpcResponse
{
Id = default,
Result = JsonSerializer.SerializeToNode(resultPayload, McpJsonUtilities.DefaultOptions),
});

View file

@ -538,7 +538,7 @@ public partial class McpServerResourceTests
McpServerResource resource = McpServerResource.Create((McpServer server) =>
{
Assert.Same(mockServer.Object, server);
return new ReadResourceResult { Contents = [new TextResourceContents { Text = "hello" }] };
return new ReadResourceResult { Contents = [new TextResourceContents { Text = "hello", Uri = "" }] };
}, new() { Name = "Test" });
var result = await resource.ReadAsync(
new RequestContext<ReadResourceRequestParams>(mockServer.Object, CreateTestJsonRpcRequest()) { Params = new() { Uri = "resource://mcp/Test" } },
@ -555,7 +555,7 @@ public partial class McpServerResourceTests
McpServerResource resource = McpServerResource.Create((McpServer server) =>
{
Assert.Same(mockServer.Object, server);
return new TextResourceContents { Text = "hello" };
return new TextResourceContents { Text = "hello", Uri = "" };
}, new() { Name = "Test", SerializerOptions = JsonContext6.Default.Options });
var result = await resource.ReadAsync(
new RequestContext<ReadResourceRequestParams>(mockServer.Object, CreateTestJsonRpcRequest()) { Params = new() { Uri = "resource://mcp/Test" } },
@ -574,8 +574,8 @@ public partial class McpServerResourceTests
Assert.Same(mockServer.Object, server);
return (IList<ResourceContents>)
[
new TextResourceContents { Text = "hello" },
new BlobResourceContents { Blob = Convert.ToBase64String(new byte[] { 1, 2, 3 }) },
new TextResourceContents { Text = "hello", Uri = "" },
new BlobResourceContents { Blob = Convert.ToBase64String(new byte[] { 1, 2, 3 }), Uri = "" },
];
}, new() { Name = "Test" });
var result = await resource.ReadAsync(

View file

@ -130,7 +130,7 @@ public class McpServerTests : LoggedTest
await using var server = McpServer.Create(transport, _options, LoggerFactory);
SetClientCapabilities(server, new ClientCapabilities());
var action = async () => await server.SampleAsync(new CreateMessageRequestParams { Messages = [] }, CancellationToken.None);
var action = async () => await server.SampleAsync(new CreateMessageRequestParams { Messages = [], MaxTokens = 1000 }, CancellationToken.None);
// Act & Assert
await Assert.ThrowsAsync<InvalidOperationException>(action);
@ -147,7 +147,7 @@ public class McpServerTests : LoggedTest
var runTask = server.RunAsync(TestContext.Current.CancellationToken);
// Act
var result = await server.SampleAsync(new CreateMessageRequestParams { Messages = [] }, CancellationToken.None);
var result = await server.SampleAsync(new CreateMessageRequestParams { Messages = [], MaxTokens = 1000 }, CancellationToken.None);
Assert.NotNull(result);
Assert.NotEmpty(transport.SentMessages);
@ -201,7 +201,7 @@ public class McpServerTests : LoggedTest
SetClientCapabilities(server, new ClientCapabilities());
// Act & Assert
await Assert.ThrowsAsync<InvalidOperationException>(async () => await server.ElicitAsync(new ElicitRequestParams(), CancellationToken.None));
await Assert.ThrowsAsync<InvalidOperationException>(async () => await server.ElicitAsync(new ElicitRequestParams { Message = "" }, CancellationToken.None));
}
[Fact]
@ -214,7 +214,7 @@ public class McpServerTests : LoggedTest
var runTask = server.RunAsync(TestContext.Current.CancellationToken);
// Act
var result = await server.ElicitAsync(new ElicitRequestParams(), CancellationToken.None);
var result = await server.ElicitAsync(new ElicitRequestParams { Message = "" }, CancellationToken.None);
// Assert
Assert.NotNull(result);
@ -377,7 +377,7 @@ public class McpServerTests : LoggedTest
{
return new ReadResourceResult
{
Contents = [new TextResourceContents { Text = "test" }]
Contents = [new TextResourceContents { Text = "test", Uri = "" }]
};
};
options.Handlers.ListResourcesHandler = (request, ct) => throw new NotImplementedException();
@ -659,7 +659,7 @@ public class McpServerTests : LoggedTest
{
Method = method,
Id = new RequestId(55)
}
}
);
var response = await receivedMessage.Task.WaitAsync(TimeSpan.FromSeconds(10));