88
99namespace ModelContextProtocol . Server ;
1010
11+ internal class SetMcpHandlerHelper ( McpServerOptions options )
12+ {
13+ public void SetRequestHandler < TParams , TResult > (
14+ string method ,
15+ Func < TParams , CancellationToken , Task < TResult > > handler )
16+ where TParams : class
17+ where TResult : class
18+ {
19+ options . RequestHandlers . Add ( method , async ( request , cancellationToken ) =>
20+ request . Params is not TParams { } parameters
21+ ? throw new InvalidOperationException ( $ "Request { method } was sent with invalid parameters.")
22+ : await handler ( parameters , cancellationToken ) . ConfigureAwait ( false ) ) ;
23+ }
24+
25+ public void AddNotificationHandler ( string method , Func < JsonRpcNotification , Task > handler )
26+ {
27+ var list = options . NotificationHandlers . GetOrAdd ( method , _ => [ ] ) ;
28+ list . Add ( handler ) ;
29+ }
30+ }
31+
1132/// <inheritdoc />
1233internal sealed class McpServer : McpJsonRpcEndpoint , IMcpServer
1334{
@@ -56,7 +77,9 @@ public McpServer(
5677 } ) ;
5778 } ;
5879
59- AddNotificationHandler ( NotificationMethods . InitializedNotification , _ =>
80+ SetMcpHandlerHelper setHandlerHelper = new ( options ) ;
81+
82+ setHandlerHelper . AddNotificationHandler ( NotificationMethods . InitializedNotification , _ =>
6083 {
6184 if ( ServerOptions . Capabilities ? . Tools ? . ToolCollection is { } tools )
6285 {
@@ -71,14 +94,13 @@ public McpServer(
7194 return Task . CompletedTask ;
7295 } ) ;
7396
74- SetToolsHandler ( options ) ;
75- SetInitializeHandler ( options ) ;
76- SetCompletionHandler ( options ) ;
77- SetPingHandler ( ) ;
78- SetPromptsHandler ( options ) ;
79- SetResourcesHandler ( options ) ;
80- SetSetLoggingLevelHandler ( options ) ;
81- SetNotificationHandlers ( options ) ;
97+ SetToolsHandler ( options , setHandlerHelper ) ;
98+ SetInitializeHandler ( options , setHandlerHelper ) ;
99+ SetCompletionHandler ( options , setHandlerHelper ) ;
100+ SetPingHandler ( setHandlerHelper ) ;
101+ SetPromptsHandler ( options , setHandlerHelper ) ;
102+ SetResourcesHandler ( options , setHandlerHelper ) ;
103+ SetSetLoggingLevelHandler ( options , setHandlerHelper ) ;
82104 }
83105
84106 public ServerCapabilities ? ServerCapabilities { get ; set ; }
@@ -128,15 +150,15 @@ public override async ValueTask DisposeUnsynchronizedAsync()
128150 await base . DisposeUnsynchronizedAsync ( ) . ConfigureAwait ( false ) ;
129151 }
130152
131- private void SetPingHandler ( )
153+ private void SetPingHandler ( SetMcpHandlerHelper helper )
132154 {
133- SetRequestHandler < JsonNode , PingResult > ( RequestMethods . Ping ,
155+ helper . SetRequestHandler < JsonNode , PingResult > ( RequestMethods . Ping ,
134156 ( request , _ ) => Task . FromResult ( new PingResult ( ) ) ) ;
135157 }
136158
137- private void SetInitializeHandler ( McpServerOptions options )
159+ private void SetInitializeHandler ( McpServerOptions options , SetMcpHandlerHelper helper )
138160 {
139- SetRequestHandler < InitializeRequestParams , InitializeResult > ( RequestMethods . Initialize ,
161+ helper . SetRequestHandler < InitializeRequestParams , InitializeResult > ( RequestMethods . Initialize ,
140162 ( request , _ ) =>
141163 {
142164 ClientCapabilities = request ? . Capabilities ?? new ( ) ;
@@ -156,16 +178,14 @@ private void SetInitializeHandler(McpServerOptions options)
156178 } ) ;
157179 }
158180
159- private void SetCompletionHandler ( McpServerOptions options )
181+ private void SetCompletionHandler ( McpServerOptions options , SetMcpHandlerHelper helper )
160182 {
161183 // This capability is not optional, so return an empty result if there is no handler.
162- SetRequestHandler < CompleteRequestParams , CompleteResult > ( RequestMethods . CompletionComplete ,
163- options . GetCompletionHandler is { } handler ?
164- ( request , ct ) => handler ( new ( this , request ) , ct ) :
165- ( request , ct ) => Task . FromResult ( new CompleteResult ( ) { Completion = new ( ) { Values = [ ] , Total = 0 , HasMore = false } } ) ) ;
184+ helper . SetRequestHandler < CompleteRequestParams , CompleteResult > ( RequestMethods . CompletionComplete ,
185+ ( request , ct ) => Task . FromResult ( new CompleteResult ( ) { Completion = new ( ) { Values = [ ] , Total = 0 , HasMore = false } } ) ) ;
166186 }
167187
168- private void SetResourcesHandler ( McpServerOptions options )
188+ private void SetResourcesHandler ( McpServerOptions options , SetMcpHandlerHelper helper )
169189 {
170190 if ( options . Capabilities ? . Resources is not { } resourcesCapability )
171191 {
@@ -183,11 +203,11 @@ private void SetResourcesHandler(McpServerOptions options)
183203
184204 listResourcesHandler ??= ( static ( _ , _ ) => Task . FromResult ( new ListResourcesResult ( ) ) ) ;
185205
186- SetRequestHandler < ListResourcesRequestParams , ListResourcesResult > ( RequestMethods . ResourcesList , ( request , ct ) => listResourcesHandler ( new ( this , request ) , ct ) ) ;
187- SetRequestHandler < ReadResourceRequestParams , ReadResourceResult > ( RequestMethods . ResourcesRead , ( request , ct ) => readResourceHandler ( new ( this , request ) , ct ) ) ;
206+ helper . SetRequestHandler < ListResourcesRequestParams , ListResourcesResult > ( RequestMethods . ResourcesList , ( request , ct ) => listResourcesHandler ( new ( this , request ) , ct ) ) ;
207+ helper . SetRequestHandler < ReadResourceRequestParams , ReadResourceResult > ( RequestMethods . ResourcesRead , ( request , ct ) => readResourceHandler ( new ( this , request ) , ct ) ) ;
188208
189209 listResourceTemplatesHandler ??= ( static ( _ , _ ) => Task . FromResult ( new ListResourceTemplatesResult ( ) ) ) ;
190- SetRequestHandler < ListResourceTemplatesRequestParams , ListResourceTemplatesResult > ( RequestMethods . ResourcesTemplatesList , ( request , ct ) => listResourceTemplatesHandler ( new ( this , request ) , ct ) ) ;
210+ helper . SetRequestHandler < ListResourceTemplatesRequestParams , ListResourceTemplatesResult > ( RequestMethods . ResourcesTemplatesList , ( request , ct ) => listResourceTemplatesHandler ( new ( this , request ) , ct ) ) ;
191211
192212 if ( resourcesCapability . Subscribe is not true )
193213 {
@@ -201,11 +221,11 @@ private void SetResourcesHandler(McpServerOptions options)
201221 throw new McpServerException ( "Resources capability was enabled with subscribe support, but SubscribeToResources and/or UnsubscribeFromResources handlers were not specified." ) ;
202222 }
203223
204- SetRequestHandler < SubscribeRequestParams , EmptyResult > ( RequestMethods . ResourcesSubscribe , ( request , ct ) => subscribeHandler ( new ( this , request ) , ct ) ) ;
205- SetRequestHandler < UnsubscribeRequestParams , EmptyResult > ( RequestMethods . ResourcesUnsubscribe , ( request , ct ) => unsubscribeHandler ( new ( this , request ) , ct ) ) ;
224+ helper . SetRequestHandler < SubscribeRequestParams , EmptyResult > ( RequestMethods . ResourcesSubscribe , ( request , ct ) => subscribeHandler ( new ( this , request ) , ct ) ) ;
225+ helper . SetRequestHandler < UnsubscribeRequestParams , EmptyResult > ( RequestMethods . ResourcesUnsubscribe , ( request , ct ) => unsubscribeHandler ( new ( this , request ) , ct ) ) ;
206226 }
207227
208- private void SetPromptsHandler ( McpServerOptions options )
228+ private void SetPromptsHandler ( McpServerOptions options , SetMcpHandlerHelper helper )
209229 {
210230 PromptsCapability ? promptsCapability = options . Capabilities ? . Prompts ;
211231 var listPromptsHandler = promptsCapability ? . ListPromptsHandler ;
@@ -285,11 +305,11 @@ await originalListPromptsHandler(request, cancellationToken).ConfigureAwait(fals
285305 }
286306 }
287307
288- SetRequestHandler < ListPromptsRequestParams , ListPromptsResult > ( RequestMethods . PromptsList , ( request , ct ) => listPromptsHandler ( new ( this , request ) , ct ) ) ;
289- SetRequestHandler < GetPromptRequestParams , GetPromptResult > ( RequestMethods . PromptsGet , ( request , ct ) => getPromptHandler ( new ( this , request ) , ct ) ) ;
308+ helper . SetRequestHandler < ListPromptsRequestParams , ListPromptsResult > ( RequestMethods . PromptsList , ( request , ct ) => listPromptsHandler ( new ( this , request ) , ct ) ) ;
309+ helper . SetRequestHandler < GetPromptRequestParams , GetPromptResult > ( RequestMethods . PromptsGet , ( request , ct ) => getPromptHandler ( new ( this , request ) , ct ) ) ;
290310 }
291311
292- private void SetToolsHandler ( McpServerOptions options )
312+ private void SetToolsHandler ( McpServerOptions options , SetMcpHandlerHelper helper )
293313 {
294314 ToolsCapability ? toolsCapability = options . Capabilities ? . Tools ;
295315 var listToolsHandler = toolsCapability ? . ListToolsHandler ;
@@ -369,11 +389,13 @@ await originalListToolsHandler(request, cancellationToken).ConfigureAwait(false)
369389 }
370390 }
371391
372- SetRequestHandler < ListToolsRequestParams , ListToolsResult > ( RequestMethods . ToolsList , ( request , ct ) => listToolsHandler ( new ( this , request ) , ct ) ) ;
373- SetRequestHandler < CallToolRequestParams , CallToolResponse > ( RequestMethods . ToolsCall , ( request , ct ) => callToolHandler ( new ( this , request ) , ct ) ) ;
392+ helper . SetRequestHandler < ListToolsRequestParams , ListToolsResult > ( RequestMethods . ToolsList ,
393+ ( request , ct ) => listToolsHandler ( new ( this , request ) , ct ) ) ;
394+ helper . SetRequestHandler < CallToolRequestParams , CallToolResponse > ( RequestMethods . ToolsCall ,
395+ ( request , ct ) => callToolHandler ( new ( this , request ) , ct ) ) ;
374396 }
375397
376- private void SetSetLoggingLevelHandler ( McpServerOptions options )
398+ private void SetSetLoggingLevelHandler ( McpServerOptions options , SetMcpHandlerHelper helper )
377399 {
378400 if ( options . Capabilities ? . Logging is not { } loggingCapability )
379401 {
@@ -385,29 +407,7 @@ private void SetSetLoggingLevelHandler(McpServerOptions options)
385407 throw new McpServerException ( "Logging capability was enabled, but SetLoggingLevelHandler was not specified." ) ;
386408 }
387409
388- SetRequestHandler < SetLevelRequestParams , EmptyResult > ( RequestMethods . LoggingSetLevel , ( request , ct ) => setLoggingLevelHandler ( new ( this , request ) , ct ) ) ;
389- }
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 ) ;
410+ helper . SetRequestHandler < SetLevelRequestParams , EmptyResult > ( RequestMethods . LoggingSetLevel ,
411+ ( request , ct ) => setLoggingLevelHandler ( new ( this , request ) , ct ) ) ;
412412 }
413413}
0 commit comments