Skip to content

Commit ca59b30

Browse files
committed
Supporting resource templates with read resource callback
Fixes #123
1 parent 9330774 commit ca59b30

File tree

2 files changed

+106
-5
lines changed

2 files changed

+106
-5
lines changed

src/ModelContextProtocol/Server/McpServer.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -170,19 +170,21 @@ private void SetResourcesHandler(McpServerOptions options)
170170
return;
171171
}
172172

173-
if (resourcesCapability.ListResourcesHandler is not { } listResourcesHandler ||
173+
var listResourcesHandler = resourcesCapability.ListResourcesHandler;
174+
var listResourceTemplatesHandler = resourcesCapability.ListResourceTemplatesHandler;
175+
176+
if ((listResourcesHandler is not { } && listResourceTemplatesHandler is not { }) ||
174177
resourcesCapability.ReadResourceHandler is not { } readResourceHandler)
175178
{
176179
throw new McpServerException("Resources capability was enabled, but ListResources and/or ReadResource handlers were not specified.");
177180
}
178181

182+
listResourcesHandler ??= (static (_, _) => Task.FromResult(new ListResourcesResult()));
183+
179184
SetRequestHandler<ListResourcesRequestParams, ListResourcesResult>("resources/list", (request, ct) => listResourcesHandler(new(this, request), ct));
180185
SetRequestHandler<ReadResourceRequestParams, ReadResourceResult>("resources/read", (request, ct) => readResourceHandler(new(this, request), ct));
181186

182-
// Set the list resource templates handler, or use the default if not specified
183-
var listResourceTemplatesHandler = resourcesCapability.ListResourceTemplatesHandler
184-
?? (static (_, _) => Task.FromResult(new ListResourceTemplatesResult()));
185-
187+
listResourceTemplatesHandler ??= (static (_, _) => Task.FromResult(new ListResourceTemplatesResult()));
186188
SetRequestHandler<ListResourceTemplatesRequestParams, ListResourceTemplatesResult>("resources/templates/list", (request, ct) => listResourceTemplatesHandler(new(this, request), ct));
187189

188190
if (resourcesCapability.Subscribe is not true)
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
using Microsoft.Extensions.DependencyInjection;
2+
using ModelContextProtocol.Protocol.Types;
3+
using ModelContextProtocol.Server;
4+
5+
namespace ModelContextProtocol.Tests.Server;
6+
public class McpServerResourceTests
7+
{
8+
[Fact]
9+
public void CanCreateServerWithResourceTemplates()
10+
{
11+
var services = new ServiceCollection();
12+
13+
services.AddMcpServer()
14+
.WithStdioServerTransport()
15+
.WithListResourceTemplatesHandler((ctx, ct) =>
16+
{
17+
return Task.FromResult(new ListResourceTemplatesResult
18+
{
19+
ResourceTemplates =
20+
[
21+
new ResourceTemplate { Name = "Static Resource", Description = "A static resource with a numeric ID", UriTemplate = "test://static/resource/{id}" }
22+
]
23+
});
24+
})
25+
.WithReadResourceHandler((ctx, ct) =>
26+
{
27+
return Task.FromResult(new ReadResourceResult
28+
{
29+
Contents = [new ResourceContents
30+
{
31+
Uri = ctx.Params!.Uri!,
32+
Text = "Static Resource",
33+
MimeType = "text/plain",
34+
}]
35+
});
36+
});
37+
38+
var provider = services.BuildServiceProvider();
39+
40+
provider.GetRequiredService<IMcpServer>();
41+
}
42+
43+
[Fact]
44+
public void CanCreateServerWithResources()
45+
{
46+
var services = new ServiceCollection();
47+
48+
services.AddMcpServer()
49+
.WithStdioServerTransport()
50+
.WithListResourcesHandler((ctx, ct) =>
51+
{
52+
return Task.FromResult(new ListResourcesResult
53+
{
54+
Resources =
55+
[
56+
new Resource { Name = "Static Resource", Description = "A static resource with a numeric ID", Uri = "test://static/resource/foo.txt" }
57+
]
58+
});
59+
})
60+
.WithReadResourceHandler((ctx, ct) =>
61+
{
62+
return Task.FromResult(new ReadResourceResult
63+
{
64+
Contents = [new ResourceContents
65+
{
66+
Uri = ctx.Params!.Uri!,
67+
Text = "Static Resource",
68+
MimeType = "text/plain",
69+
}]
70+
});
71+
});
72+
73+
var provider = services.BuildServiceProvider();
74+
75+
provider.GetRequiredService<IMcpServer>();
76+
}
77+
78+
[Fact]
79+
public void CreatingReadHandlerWithNoListHandlerFails()
80+
{
81+
var services = new ServiceCollection();
82+
services.AddMcpServer()
83+
.WithStdioServerTransport()
84+
.WithReadResourceHandler((ctx, ct) =>
85+
{
86+
return Task.FromResult(new ReadResourceResult
87+
{
88+
Contents = [new ResourceContents
89+
{
90+
Uri = ctx.Params!.Uri!,
91+
Text = "Static Resource",
92+
MimeType = "text/plain",
93+
}]
94+
});
95+
});
96+
var sp = services.BuildServiceProvider();
97+
Assert.Throws<McpServerException>(() => sp.GetRequiredService<IMcpServer>());
98+
}
99+
}

0 commit comments

Comments
 (0)