Add public constructors to McpClient types for reusing cached definitions (#938)
* Initial plan * Add public constructor to McpClientTool for reusing tool definitions Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com> * Fix McpClientTool constructor per review feedback Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com> * Add public constructors for McpClientPrompt, McpClientResource, and McpClientResourceTemplate Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>
This commit is contained in:
parent
baa7d6e320
commit
b90f17bccb
1 changed files with 785 additions and 3 deletions
|
|
@ -0,0 +1,103 @@
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
using ModelContextProtocol.Client;
|
||||
using ModelContextProtocol.Protocol;
|
||||
using ModelContextProtocol.Server;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace ModelContextProtocol.Tests.Client;
|
||||
|
||||
public class McpClientResourceTemplateConstructorTests : ClientServerTestBase
|
||||
{
|
||||
public McpClientResourceTemplateConstructorTests(ITestOutputHelper outputHelper)
|
||||
: base(outputHelper)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void ConfigureServices(ServiceCollection services, IMcpServerBuilder mcpServerBuilder)
|
||||
{
|
||||
mcpServerBuilder.WithResources<FileTemplateResources>();
|
||||
}
|
||||
|
||||
[McpServerResourceType]
|
||||
private sealed class FileTemplateResources
|
||||
{
|
||||
[McpServerResource, Description("A file template")]
|
||||
public static string FileTemplate([Description("The file path")] string path) => $"Content for {path}";
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Constructor_WithValidParameters_CreatesInstance()
|
||||
{
|
||||
await using McpClient client = await CreateMcpClientForServer();
|
||||
|
||||
var templates = await client.ListResourceTemplatesAsync(cancellationToken: TestContext.Current.CancellationToken);
|
||||
var originalTemplate = templates.First();
|
||||
var templateDefinition = originalTemplate.ProtocolResourceTemplate;
|
||||
|
||||
var newTemplate = new McpClientResourceTemplate(client, templateDefinition);
|
||||
|
||||
Assert.NotNull(newTemplate);
|
||||
Assert.Equal("file_template", newTemplate.Name);
|
||||
Assert.Equal("A file template", newTemplate.Description);
|
||||
Assert.Same(templateDefinition, newTemplate.ProtocolResourceTemplate);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Constructor_WithNullClient_ThrowsArgumentNullException()
|
||||
{
|
||||
var templateDefinition = new ResourceTemplate
|
||||
{
|
||||
UriTemplate = "file:///{path}",
|
||||
Name = "test",
|
||||
Description = "Test template"
|
||||
};
|
||||
|
||||
Assert.Throws<ArgumentNullException>("client", () => new McpClientResourceTemplate(null!, templateDefinition));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Constructor_WithNullResourceTemplate_ThrowsArgumentNullException()
|
||||
{
|
||||
await using McpClient client = await CreateMcpClientForServer();
|
||||
|
||||
Assert.Throws<ArgumentNullException>("resourceTemplate", () => new McpClientResourceTemplate(client, null!));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ReuseResourceTemplateDefinition_PreservesTemplateMetadata()
|
||||
{
|
||||
await using McpClient client = await CreateMcpClientForServer();
|
||||
|
||||
var templates = await client.ListResourceTemplatesAsync(cancellationToken: TestContext.Current.CancellationToken);
|
||||
var originalTemplate = templates.First();
|
||||
var templateDefinition = originalTemplate.ProtocolResourceTemplate;
|
||||
|
||||
var reusedTemplate = new McpClientResourceTemplate(client, templateDefinition);
|
||||
|
||||
Assert.Equal(originalTemplate.Name, reusedTemplate.Name);
|
||||
Assert.Equal(originalTemplate.Description, reusedTemplate.Description);
|
||||
Assert.Equal(originalTemplate.UriTemplate, reusedTemplate.UriTemplate);
|
||||
Assert.Equal(originalTemplate.ProtocolResourceTemplate.Name, reusedTemplate.ProtocolResourceTemplate.Name);
|
||||
Assert.Equal(originalTemplate.ProtocolResourceTemplate.Description, reusedTemplate.ProtocolResourceTemplate.Description);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ManuallyConstructedResourceTemplate_CreatesValidInstance()
|
||||
{
|
||||
await using McpClient client = await CreateMcpClientForServer();
|
||||
|
||||
var manualTemplate = new ResourceTemplate
|
||||
{
|
||||
UriTemplate = "file:///{path}",
|
||||
Name = "file_template",
|
||||
Description = "A file template"
|
||||
};
|
||||
|
||||
var clientTemplate = new McpClientResourceTemplate(client, manualTemplate);
|
||||
|
||||
Assert.NotNull(clientTemplate);
|
||||
Assert.Equal("file_template", clientTemplate.Name);
|
||||
Assert.Equal("A file template", clientTemplate.Description);
|
||||
Assert.Equal("file:///{path}", clientTemplate.UriTemplate);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue