Skip to content

Commit 9bbae84

Browse files
PederHPhalter73mikekistler
authored
Resource subscribe should be true if handler provided (#676)
Co-authored-by: Stephen Halter <[email protected]> Co-authored-by: Mike Kistler <[email protected]>
1 parent 31f8d20 commit 9bbae84

File tree

4 files changed

+18
-42
lines changed

4 files changed

+18
-42
lines changed

src/ModelContextProtocol/McpServerOptionsSetup.cs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,13 +97,14 @@ private static void OverwriteWithSetHandlers(McpServerHandlers handlers, McpServ
9797
optionsHandlers.ListResourceTemplatesHandler = handlers.ListResourceTemplatesHandler ?? optionsHandlers.ListResourceTemplatesHandler;
9898
optionsHandlers.ListResourcesHandler = handlers.ListResourcesHandler ?? optionsHandlers.ListResourcesHandler;
9999
optionsHandlers.ReadResourceHandler = handlers.ReadResourceHandler ?? optionsHandlers.ReadResourceHandler;
100+
}
100101

101-
if (handlers.SubscribeToResourcesHandler is not null || handlers.UnsubscribeFromResourcesHandler is not null)
102-
{
103-
optionsHandlers.SubscribeToResourcesHandler = handlers.SubscribeToResourcesHandler ?? optionsHandlers.SubscribeToResourcesHandler;
104-
optionsHandlers.UnsubscribeFromResourcesHandler = handlers.UnsubscribeFromResourcesHandler ?? optionsHandlers.UnsubscribeFromResourcesHandler;
105-
resourcesCapability.Subscribe = true;
106-
}
102+
if (handlers.SubscribeToResourcesHandler is not null || handlers.UnsubscribeFromResourcesHandler is not null)
103+
{
104+
resourcesCapability ??= new();
105+
optionsHandlers.SubscribeToResourcesHandler = handlers.SubscribeToResourcesHandler ?? optionsHandlers.SubscribeToResourcesHandler;
106+
optionsHandlers.UnsubscribeFromResourcesHandler = handlers.UnsubscribeFromResourcesHandler ?? optionsHandlers.UnsubscribeFromResourcesHandler;
107+
resourcesCapability.Subscribe = true;
107108
}
108109

109110
ToolsCapability? toolsCapability = options.Capabilities?.Tools;

tests/ModelContextProtocol.AspNetCore.Tests/ServerConformanceTests.cs

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -110,21 +110,6 @@ public async Task RunConformanceTests()
110110

111111
private void StartConformanceServer()
112112
{
113-
// The ConformanceServer binary is in a parallel directory to the test binary
114-
// Test binary is in: artifacts/bin/ModelContextProtocol.ConformanceTests/Debug/{tfm}/
115-
// ConformanceServer binary is in: artifacts/bin/ModelContextProtocol.ConformanceServer/Debug/{tfm}/
116-
var testBinaryDir = AppContext.BaseDirectory; // e.g., .../net10.0/
117-
var configuration = Path.GetFileName(Path.GetDirectoryName(testBinaryDir.TrimEnd(Path.DirectorySeparatorChar))!);
118-
var targetFramework = Path.GetFileName(testBinaryDir.TrimEnd(Path.DirectorySeparatorChar));
119-
var conformanceServerDir = Path.GetFullPath(
120-
Path.Combine(testBinaryDir, "..", "..", "..", "ModelContextProtocol.ConformanceServer", configuration, targetFramework));
121-
122-
if (!Directory.Exists(conformanceServerDir))
123-
{
124-
throw new DirectoryNotFoundException(
125-
$"ConformanceServer directory not found at: {conformanceServerDir}");
126-
}
127-
128113
// Start the server in a background task
129114
_serverCts = new CancellationTokenSource();
130115
_serverTask = Task.Run(() => ConformanceServer.Program.MainAsync(["--urls", _serverUrl], new XunitLoggerProvider(_output), cancellationToken: _serverCts.Token));

tests/ModelContextProtocol.ConformanceServer/Program.cs

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
using ConformanceServer.Prompts;
22
using ConformanceServer.Resources;
33
using ConformanceServer.Tools;
4-
using Microsoft.Extensions.AI;
54
using ModelContextProtocol.Protocol;
65
using System.Collections.Concurrent;
76
using System.Text.Json;
8-
using System.Text.Json.Nodes;
9-
using System.Text.Json.Serialization;
107

118
namespace ModelContextProtocol.ConformanceServer;
129

@@ -41,18 +38,8 @@ public static async Task MainAsync(string[] args, ILoggerProvider? loggerProvide
4138
}
4239
if (ctx.Params?.Uri is { } uri)
4340
{
44-
subscriptions[ctx.Server.SessionId].TryAdd(uri, 0);
45-
46-
await ctx.Server.SampleAsync([
47-
new ChatMessage(ChatRole.System, "You are a helpful test server"),
48-
new ChatMessage(ChatRole.User, $"Resource {uri}, context: A new subscription was started"),
49-
],
50-
chatOptions: new ChatOptions
51-
{
52-
MaxOutputTokens = 100,
53-
Temperature = 0.7f,
54-
},
55-
cancellationToken: ct);
41+
var sessionSubscriptions = subscriptions.GetOrAdd(ctx.Server.SessionId, _ => new());
42+
sessionSubscriptions.TryAdd(uri, 0);
5643
}
5744

5845
return new EmptyResult();
@@ -67,6 +54,7 @@ await ctx.Server.SampleAsync([
6754
{
6855
subscriptions[ctx.Server.SessionId].TryRemove(uri, out _);
6956
}
57+
7058
return new EmptyResult();
7159
})
7260
.WithCompleteHandler(async (ctx, ct) =>

tests/ModelContextProtocol.Tests/Configuration/McpServerOptionsSetupTests.cs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -108,29 +108,31 @@ public void Configure_WithUnsubscribeFromResourcesHandler_And_WithOtherResources
108108
}
109109

110110
[Fact]
111-
public void Configure_WithSubscribeToResourcesHandler_WithoutOtherResourcesHandler_DoesNotCreateResourcesCapability()
111+
public void Configure_WithSubscribeToResourcesHandler_WithoutOtherResourcesHandler_DoesCreateResourcesCapability()
112112
{
113113
var services = new ServiceCollection();
114114
services.AddMcpServer()
115115
.WithSubscribeToResourcesHandler(async (request, ct) => new EmptyResult());
116116

117117
var options = services.BuildServiceProvider().GetRequiredService<IOptions<McpServerOptions>>().Value;
118118

119-
Assert.Null(options.Handlers.SubscribeToResourcesHandler);
120-
Assert.Null(options.Capabilities?.Resources);
119+
Assert.NotNull(options.Handlers.SubscribeToResourcesHandler);
120+
Assert.NotNull(options.Capabilities?.Resources);
121+
Assert.True(options.Capabilities.Resources.Subscribe);
121122
}
122123

123124
[Fact]
124-
public void Configure_WithUnsubscribeFromResourcesHandler_WithoutOtherResourcesHandler_DoesNotCreateResourcesCapability()
125+
public void Configure_WithUnsubscribeFromResourcesHandler_WithoutOtherResourcesHandler_DoesCreateResourcesCapability()
125126
{
126127
var services = new ServiceCollection();
127128
services.AddMcpServer()
128129
.WithUnsubscribeFromResourcesHandler(async (request, ct) => new EmptyResult());
129130

130131
var options = services.BuildServiceProvider().GetRequiredService<IOptions<McpServerOptions>>().Value;
131132

132-
Assert.Null(options.Handlers.UnsubscribeFromResourcesHandler);
133-
Assert.Null(options.Capabilities?.Resources);
133+
Assert.NotNull(options.Handlers.UnsubscribeFromResourcesHandler);
134+
Assert.NotNull(options.Capabilities?.Resources);
135+
Assert.True(options.Capabilities.Resources.Subscribe);
134136
}
135137

136138
[Fact]

0 commit comments

Comments
 (0)