Skip to content

Commit 14463a6

Browse files
committed
Fix McpServerResource registration
- Add missing filling of ResourceCollection in McpServerOptionsSetup - Remove AIFunctionMcpServerXx.ToString overrides; for resources, it was changing behavior undesirably, and for the others it was duplicate code. - Fix notification method used for resource list changes. - Fix type in WithResources parameter name.
1 parent 4043538 commit 14463a6

7 files changed

Lines changed: 330 additions & 34 deletions

File tree

src/ModelContextProtocol/Configuration/McpServerBuilderExtensions.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -334,16 +334,16 @@ where t.GetCustomAttribute<McpServerPromptTypeAttribute>() is not null
334334

335335
/// <summary>Adds <see cref="McpServerResource"/> instances to the service collection backing <paramref name="builder"/>.</summary>
336336
/// <param name="builder">The builder instance.</param>
337-
/// <param name="resourcetemplates">The <see cref="McpServerResource"/> instances to add to the server.</param>
337+
/// <param name="resourceTemplates">The <see cref="McpServerResource"/> instances to add to the server.</param>
338338
/// <returns>The builder provided in <paramref name="builder"/>.</returns>
339339
/// <exception cref="ArgumentNullException"><paramref name="builder"/> is <see langword="null"/>.</exception>
340-
/// <exception cref="ArgumentNullException"><paramref name="resourcetemplates"/> is <see langword="null"/>.</exception>
341-
public static IMcpServerBuilder WithResources(this IMcpServerBuilder builder, IEnumerable<McpServerResource> resourcetemplates)
340+
/// <exception cref="ArgumentNullException"><paramref name="resourceTemplates"/> is <see langword="null"/>.</exception>
341+
public static IMcpServerBuilder WithResources(this IMcpServerBuilder builder, IEnumerable<McpServerResource> resourceTemplates)
342342
{
343343
Throw.IfNull(builder);
344-
Throw.IfNull(resourcetemplates);
344+
Throw.IfNull(resourceTemplates);
345345

346-
foreach (var resourceTemplate in resourcetemplates)
346+
foreach (var resourceTemplate in resourceTemplates)
347347
{
348348
if (resourceTemplate is not null)
349349
{
@@ -409,7 +409,7 @@ public static IMcpServerBuilder WithResources(this IMcpServerBuilder builder, IE
409409
/// of the containing class will be constructed for each invocation of the resource.
410410
/// </para>
411411
/// <para>
412-
/// Resource templates registered through this method can be discovered by clients using the <c>list_resourcetemplates</c> request
412+
/// Resource templates registered through this method can be discovered by clients using the <c>list_resourceTemplates</c> request
413413
/// and invoked using the <c>read_resource</c> request.
414414
/// </para>
415415
/// <para>

src/ModelContextProtocol/Configuration/McpServerOptionsSetup.cs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@ namespace Microsoft.Extensions.DependencyInjection;
1010
/// <param name="serverHandlers">The server handlers configuration options.</param>
1111
/// <param name="serverTools">Tools individually registered.</param>
1212
/// <param name="serverPrompts">Prompts individually registered.</param>
13+
/// <param name="serverResources">Resources individually registered.</param>
1314
internal sealed class McpServerOptionsSetup(
1415
IOptions<McpServerHandlers> serverHandlers,
1516
IEnumerable<McpServerTool> serverTools,
16-
IEnumerable<McpServerPrompt> serverPrompts) : IConfigureOptions<McpServerOptions>
17+
IEnumerable<McpServerPrompt> serverPrompts,
18+
IEnumerable<McpServerResource> serverResources) : IConfigureOptions<McpServerOptions>
1719
{
1820
/// <summary>
1921
/// Configures the given McpServerOptions instance by setting server information
@@ -58,6 +60,23 @@ public void Configure(McpServerOptions options)
5860
options.Capabilities.Prompts.PromptCollection = promptCollection;
5961
}
6062

63+
// Collect all of the provided resources into a resources collection. If the options already has
64+
// a collection, add to it, otherwise create a new one. We want to maintain the identity
65+
// of an existing collection in case someone has provided their own derived type, wants
66+
// change notifications, etc.
67+
McpServerPrimitiveCollection<McpServerResource> resourceCollection = options.Capabilities?.Resources?.ResourceCollection ?? [];
68+
foreach (var resource in serverResources)
69+
{
70+
resourceCollection.TryAdd(resource);
71+
}
72+
73+
if (!resourceCollection.IsEmpty)
74+
{
75+
options.Capabilities ??= new();
76+
options.Capabilities.Resources ??= new();
77+
options.Capabilities.Resources.ResourceCollection = resourceCollection;
78+
}
79+
6180
// Apply custom server handlers.
6281
serverHandlers.Value.OverwriteWithSetHandlers(options);
6382
}

src/ModelContextProtocol/Server/AIFunctionMcpServerPrompt.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -213,9 +213,6 @@ private AIFunctionMcpServerPrompt(AIFunction function, Prompt prompt)
213213
ProtocolPrompt = prompt;
214214
}
215215

216-
/// <inheritdoc />
217-
public override string ToString() => AIFunction.ToString();
218-
219216
/// <inheritdoc />
220217
public override Prompt ProtocolPrompt { get; }
221218

src/ModelContextProtocol/Server/AIFunctionMcpServerResource.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -328,9 +328,6 @@ private AIFunctionMcpServerResource(AIFunction function, ResourceTemplate resour
328328
}
329329
}
330330

331-
/// <inheritdoc />
332-
public override string ToString() => AIFunction.ToString();
333-
334331
/// <inheritdoc />
335332
public override ResourceTemplate ProtocolResourceTemplate { get; }
336333

src/ModelContextProtocol/Server/AIFunctionMcpServerTool.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -243,9 +243,6 @@ private AIFunctionMcpServerTool(AIFunction function, Tool tool)
243243
ProtocolTool = tool;
244244
}
245245

246-
/// <inheritdoc />
247-
public override string ToString() => AIFunction.ToString();
248-
249246
/// <inheritdoc />
250247
public override Tool ProtocolTool { get; }
251248

src/ModelContextProtocol/Server/McpServer.cs

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -75,26 +75,19 @@ public McpServer(ITransport transport, McpServerOptions options, ILoggerFactory?
7575
}
7676

7777
// Now that everything has been configured, subscribe to any necessary notifications.
78-
if (ServerOptions.Capabilities?.Tools?.ToolCollection is { } tools)
79-
{
80-
EventHandler changed = (sender, e) => _ = this.SendNotificationAsync(NotificationMethods.ToolListChangedNotification);
81-
tools.Changed += changed;
82-
_disposables.Add(() => tools.Changed -= changed);
83-
}
78+
Register(ServerOptions.Capabilities?.Tools?.ToolCollection, NotificationMethods.ToolListChangedNotification);
79+
Register(ServerOptions.Capabilities?.Prompts?.PromptCollection, NotificationMethods.PromptListChangedNotification);
80+
Register(ServerOptions.Capabilities?.Resources?.ResourceCollection, NotificationMethods.ResourceListChangedNotification);
8481

85-
if (ServerOptions.Capabilities?.Prompts?.PromptCollection is { } prompts)
82+
void Register<TPrimitive>(McpServerPrimitiveCollection<TPrimitive>? collection, string notificationMethod)
83+
where TPrimitive : IMcpServerPrimitive
8684
{
87-
EventHandler changed = (sender, e) => _ = this.SendNotificationAsync(NotificationMethods.PromptListChangedNotification);
88-
prompts.Changed += changed;
89-
_disposables.Add(() => prompts.Changed -= changed);
90-
}
91-
92-
var resources = ServerOptions.Capabilities?.Resources?.ResourceCollection;
93-
if (resources is not null)
94-
{
95-
EventHandler changed = (sender, e) => _ = this.SendNotificationAsync(NotificationMethods.PromptListChangedNotification);
96-
resources.Changed += changed;
97-
_disposables.Add(() => resources.Changed -= changed);
85+
if (collection is not null)
86+
{
87+
EventHandler changed = (sender, e) => _ = this.SendNotificationAsync(notificationMethod);
88+
collection.Changed += changed;
89+
_disposables.Add(() => collection.Changed -= changed);
90+
}
9891
}
9992

10093
// And initialize the session.

0 commit comments

Comments
 (0)