Skip to content

Commit 6114cb9

Browse files
removed AddNotificationHandler from server.
1 parent 1e0755c commit 6114cb9

File tree

4 files changed

+59
-32
lines changed

4 files changed

+59
-32
lines changed

src/ModelContextProtocol/Server/IMcpServer.cs

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -31,20 +31,4 @@ public interface IMcpServer : IMcpSession
3131
/// Runs the server, listening for and handling client requests.
3232
/// </summary>
3333
Task RunAsync(CancellationToken cancellationToken = default);
34-
35-
/// <summary>
36-
/// Adds a handler for server notifications of a specific method.
37-
/// </summary>
38-
/// <param name="method">The notification method to handle.</param>
39-
/// <param name="handler">The async handler function to process notifications.</param>
40-
/// <remarks>
41-
/// <para>
42-
/// Each method may have multiple handlers. Adding a handler for a method that already has one
43-
/// will not replace the existing handler.
44-
/// </para>
45-
/// <para>
46-
/// <see cref="NotificationMethods"> provides constants for common notification methods.</see>
47-
/// </para>
48-
/// </remarks>
49-
void AddNotificationHandler(string method, Func<JsonRpcNotification, Task> handler);
5034
}

src/ModelContextProtocol/Server/McpServer.cs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,11 @@ internal sealed class McpServer : McpJsonRpcEndpoint, IMcpServer
2626
/// <param name="loggerFactory">Logger factory to use for logging</param>
2727
/// <param name="serviceProvider">Optional service provider to use for dependency injection</param>
2828
/// <exception cref="McpServerException"></exception>
29-
public McpServer(ITransport transport, McpServerOptions options, ILoggerFactory? loggerFactory, IServiceProvider? serviceProvider)
29+
public McpServer(
30+
ITransport transport,
31+
McpServerOptions options,
32+
ILoggerFactory? loggerFactory,
33+
IServiceProvider? serviceProvider)
3034
: base(loggerFactory)
3135
{
3236
Throw.IfNull(transport);
@@ -74,6 +78,7 @@ public McpServer(ITransport transport, McpServerOptions options, ILoggerFactory?
7478
SetPromptsHandler(options);
7579
SetResourcesHandler(options);
7680
SetSetLoggingLevelHandler(options);
81+
SetNotificationHandlers(options);
7782
}
7883

7984
public ServerCapabilities? ServerCapabilities { get; set; }
@@ -382,4 +387,27 @@ private void SetSetLoggingLevelHandler(McpServerOptions options)
382387

383388
SetRequestHandler<SetLevelRequestParams, EmptyResult>(RequestMethods.LoggingSetLevel, (request, ct) => setLoggingLevelHandler(new(this, request), ct));
384389
}
390+
391+
private void SetNotificationHandlers(McpServerOptions options)
392+
{
393+
if (options.NotificationHandlers is not { } handlers)
394+
{
395+
throw new McpServerException("Experimental capability was enabled, but NotificationHandlers were not specified.");
396+
}
397+
398+
foreach (var handler in handlers)
399+
{
400+
var key = handler.Key;
401+
var list = handler.Value;
402+
foreach (var item in list)
403+
{
404+
SetNotificationHandler(key, item);
405+
}
406+
}
407+
}
408+
409+
private void SetNotificationHandler(string method, Func<JsonRpcNotification, Task> handler)
410+
{
411+
AddNotificationHandler(method, handler);
412+
}
385413
}

src/ModelContextProtocol/Server/McpServerOptions.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-

2-
using ModelContextProtocol.Protocol.Types;
1+
using ModelContextProtocol.Protocol.Types;
2+
using ModelContextProtocol.Protocol.Messages;
33
using System.Text.Json.Serialization;
4+
using ModelContextProtocol.Shared;
45

56
namespace ModelContextProtocol.Server;
67

@@ -41,4 +42,10 @@ public class McpServerOptions
4142
/// </summary>
4243
[JsonIgnore]
4344
public Func<RequestContext<CompleteRequestParams>, CancellationToken, Task<CompleteResult>>? GetCompletionHandler { get; set; }
45+
46+
/// <summary>
47+
/// Gets or sets the handler for get completion requests.
48+
/// </summary>
49+
[JsonIgnore]
50+
public IReadOnlyDictionary<string, List<Func<JsonRpcNotification, Task>>> NotificationHandlers { get; init; } = new NotificationHandlers();
4451
}

tests/ModelContextProtocol.Tests/Server/McpServerTests.cs

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,18 @@ public McpServerTests(ITestOutputHelper testOutputHelper)
2424
_serviceProvider = new ServiceCollection().BuildServiceProvider();
2525
}
2626

27-
private static McpServerOptions CreateOptions(ServerCapabilities? capabilities = null)
27+
private static McpServerOptions CreateOptions(
28+
ServerCapabilities? capabilities = null,
29+
IReadOnlyDictionary<string, List<Func<JsonRpcNotification, Task>>>? notificationHandlers = null)
2830
{
31+
notificationHandlers ??= new Dictionary<string, List<Func<JsonRpcNotification, Task>>>();
2932
return new McpServerOptions
3033
{
3134
ServerInfo = new Implementation { Name = "TestServer", Version = "1.0" },
3235
ProtocolVersion = "2024",
3336
InitializationTimeout = TimeSpan.FromSeconds(30),
3437
Capabilities = capabilities,
38+
NotificationHandlers = notificationHandlers,
3539
};
3640
}
3741

@@ -640,18 +644,20 @@ public Task RunAsync(CancellationToken cancellationToken = default) =>
640644
public async Task NotifyProgress_Should_Be_Handled()
641645
{
642646
await using TestServerTransport transport = new();
643-
var options = CreateOptions();
644-
645-
var notificationReceived = new TaskCompletionSource<JsonRpcNotification>();
646-
647-
var server = McpServerFactory.Create(transport, options, LoggerFactory, _serviceProvider);
648-
server.AddNotificationHandler(NotificationMethods.ProgressNotification, notification =>
647+
TaskCompletionSource<JsonRpcNotification> notificationReceived = new();
648+
var token = TestContext.Current.CancellationToken;
649+
650+
Task SetNotificationHandler(JsonRpcNotification notification)
649651
{
650652
notificationReceived.SetResult(notification);
651653
return Task.CompletedTask;
654+
}
655+
var options = CreateOptions(notificationHandlers: new Dictionary<string, List<Func<JsonRpcNotification, Task>>>()
656+
{
657+
{ NotificationMethods.ProgressNotification, [SetNotificationHandler] },
652658
});
653-
654-
Task serverTask = server.RunAsync(TestContext.Current.CancellationToken);
659+
var server = McpServerFactory.Create(transport, options, LoggerFactory, _serviceProvider);
660+
Task serverTask = server.RunAsync(token);
655661

656662
await transport.SendMessageAsync(new JsonRpcNotification
657663
{
@@ -666,14 +672,16 @@ await transport.SendMessageAsync(new JsonRpcNotification
666672
Message = "Progress message",
667673
},
668674
},
669-
}, TestContext.Current.CancellationToken);
675+
}, token);
670676

671677
var notification = await notificationReceived.Task;
672678
var progress = (ProgressNotification)notification.Params!;
673679
Assert.Equal("\"abc\"", progress.ProgressToken.ToString());
674-
Assert.Equal(50, progress.Progress.Progress);
675-
Assert.Equal(100, progress.Progress.Total);
676-
Assert.Equal("Progress message", progress.Progress.Message);
680+
681+
var progressValue = progress.Progress;
682+
Assert.Equal(50, progressValue.Progress);
683+
Assert.Equal(100, progressValue.Total);
684+
Assert.Equal("Progress message", progressValue.Message);
677685

678686
await server.DisposeAsync();
679687
await serverTask;

0 commit comments

Comments
 (0)