Skip to content

Tool/prompt/resource handlers only getting added if collections aren't empty #864

@stephentoub

Description

@stephentoub

We currently synthesize handlers for tools, prompts, resources if the relevant collection has been initialized, but only if it's not empty. If instead it's empty, with the idea that entries will be added later, no handlers are synthesized.

Repro:

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using ModelContextProtocol.Client;
using ModelContextProtocol.Protocol;
using ModelContextProtocol.Server;
using System.IO.Pipelines;

Pipe clientToServerPipe = new(), serverToClientPipe = new();

McpServerResourceCollection resourceCollection = [];

// Uncomment this line and then both resources will work
// resourceCollection.Add(McpServerResource.Create(() => "something", new() { UriTemplate = "something://something/1" }));

var builder = Host.CreateApplicationBuilder(args);
builder.Logging.AddConsole(o => o.LogToStandardErrorThreshold = LogLevel.Trace);
builder.Services
    .AddMcpServer(options =>
    {
        options.ServerInfo = new Implementation
        {
            Name = "observable-game-state",
            Version = "1.0.0",
            Title = "Observable Game State Server"
        };

        options.ResourceCollection = resourceCollection;
    })
    .WithStreamServerTransport(clientToServerPipe.Reader.AsStream(), serverToClientPipe.Writer.AsStream());
_ = builder.Build().RunAsync();

await using McpClient client = await McpClient.CreateAsync(
    new StreamClientTransport(clientToServerPipe.Writer.AsStream(), serverToClientPipe.Reader.AsStream()));

Console.WriteLine("First:");
foreach (var resource in await client.ListResourcesAsync())
{
    Console.WriteLine($"Resource: {resource.Uri}");
}

resourceCollection.Add(McpServerResource.Create(() => "something", new() { UriTemplate = "something://something/2" }));

Console.WriteLine("Second:");
foreach (var resource in await client.ListResourcesAsync())
{
    Console.WriteLine($"Resource: {resource.Uri}");
}

That check is happening here:

if (resources is { IsEmpty: false })

We should instead always synthesize these handlers if this collection has been initialized, even if it's empty.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions