1+ using Microsoft . Extensions . DependencyInjection ;
2+ using ModelContextProtocol . Protocol ;
3+
4+ namespace ModelContextProtocol . Server ;
5+
6+ /// <summary>
7+ /// Provides a container for handlers used in the creation of an MCP server.
8+ /// </summary>
9+ /// <remarks>
10+ /// <para>
11+ /// This class provides a centralized collection of delegates that implement various capabilities of the Model Context Protocol.
12+ /// Each handler in this class corresponds to a specific endpoint in the Model Context Protocol and
13+ /// is responsible for processing a particular type of request. The handlers are used to customize
14+ /// the behavior of the MCP server by providing implementations for the various protocol operations.
15+ /// </para>
16+ /// <para>
17+ /// Handlers can be configured individually using the extension methods in McpServerBuilderExtensions
18+ /// such as WithListToolsHandler and WithCallToolHandler.
19+ /// </para>
20+ /// <para>
21+ /// When a client sends a request to the server, the appropriate handler is invoked to process the
22+ /// request and produce a response according to the protocol specification. Which handler is selected
23+ /// is done based on an ordinal, case-sensitive string comparison.
24+ /// </para>
25+ /// </remarks>
26+ public sealed class McpServerHandlers
27+ {
28+ /// <summary>
29+ /// Gets or sets the handler for <see cref="RequestMethods.ToolsList"/> requests.
30+ /// </summary>
31+ /// <remarks>
32+ /// <para>
33+ /// The handler should return a list of available tools when requested by a client.
34+ /// It supports pagination through the cursor mechanism, where the client can make
35+ /// repeated calls with the cursor returned by the previous call to retrieve more tools.
36+ /// </para>
37+ /// <para>
38+ /// This handler works alongside any tools defined in the <see cref="McpServerTool"/> collection.
39+ /// Tools from both sources will be combined when returning results to clients.
40+ /// </para>
41+ /// </remarks>
42+ public Func < RequestContext < ListToolsRequestParams > , CancellationToken , ValueTask < ListToolsResult > > ? ListToolsHandler { get ; set ; }
43+
44+ /// <summary>
45+ /// Gets or sets the handler for <see cref="RequestMethods.ToolsCall"/> requests.
46+ /// </summary>
47+ /// <remarks>
48+ /// This handler is invoked when a client makes a call to a tool that isn't found in the <see cref="McpServerTool"/> collection.
49+ /// The handler should implement logic to execute the requested tool and return appropriate results.
50+ /// </remarks>
51+ public Func < RequestContext < CallToolRequestParams > , CancellationToken , ValueTask < CallToolResponse > > ? CallToolHandler { get ; set ; }
52+
53+ /// <summary>
54+ /// Gets or sets the handler for <see cref="RequestMethods.PromptsList"/> requests.
55+ /// </summary>
56+ /// <remarks>
57+ /// <para>
58+ /// The handler should return a list of available prompts when requested by a client.
59+ /// It supports pagination through the cursor mechanism, where the client can make
60+ /// repeated calls with the cursor returned by the previous call to retrieve more prompts.
61+ /// </para>
62+ /// <para>
63+ /// This handler works alongside any prompts defined in the <see cref="McpServerPrompt"/> collection.
64+ /// Prompts from both sources will be combined when returning results to clients.
65+ /// </para>
66+ /// </remarks>
67+ public Func < RequestContext < ListPromptsRequestParams > , CancellationToken , ValueTask < ListPromptsResult > > ? ListPromptsHandler { get ; set ; }
68+
69+ /// <summary>
70+ /// Gets or sets the handler for <see cref="RequestMethods.PromptsGet"/> requests.
71+ /// </summary>
72+ /// <remarks>
73+ /// This handler is invoked when a client requests details for a specific prompt that isn't found in the <see cref="McpServerPrompt"/> collection.
74+ /// The handler should implement logic to fetch or generate the requested prompt and return appropriate results.
75+ /// </remarks>
76+ public Func < RequestContext < GetPromptRequestParams > , CancellationToken , ValueTask < GetPromptResult > > ? GetPromptHandler { get ; set ; }
77+
78+ /// <summary>
79+ /// Gets or sets the handler for <see cref="RequestMethods.ResourcesTemplatesList"/> requests.
80+ /// </summary>
81+ /// <remarks>
82+ /// The handler should return a list of available resource templates when requested by a client.
83+ /// It supports pagination through the cursor mechanism, where the client can make
84+ /// repeated calls with the cursor returned by the previous call to retrieve more resource templates.
85+ /// </remarks>
86+ public Func < RequestContext < ListResourceTemplatesRequestParams > , CancellationToken , ValueTask < ListResourceTemplatesResult > > ? ListResourceTemplatesHandler { get ; set ; }
87+
88+ /// <summary>
89+ /// Gets or sets the handler for <see cref="RequestMethods.ResourcesList"/> requests.
90+ /// </summary>
91+ /// <remarks>
92+ /// The handler should return a list of available resources when requested by a client.
93+ /// It supports pagination through the cursor mechanism, where the client can make
94+ /// repeated calls with the cursor returned by the previous call to retrieve more resources.
95+ /// </remarks>
96+ public Func < RequestContext < ListResourcesRequestParams > , CancellationToken , ValueTask < ListResourcesResult > > ? ListResourcesHandler { get ; set ; }
97+
98+ /// <summary>
99+ /// Gets or sets the handler for <see cref="RequestMethods.ResourcesRead"/> requests.
100+ /// </summary>
101+ /// <remarks>
102+ /// This handler is invoked when a client requests the content of a specific resource identified by its URI.
103+ /// The handler should implement logic to locate and retrieve the requested resource.
104+ /// </remarks>
105+ public Func < RequestContext < ReadResourceRequestParams > , CancellationToken , ValueTask < ReadResourceResult > > ? ReadResourceHandler { get ; set ; }
106+
107+ /// <summary>
108+ /// Gets or sets the handler for <see cref="RequestMethods.CompletionComplete"/> requests.
109+ /// </summary>
110+ /// <remarks>
111+ /// This handler provides auto-completion suggestions for prompt arguments or resource references in the Model Context Protocol.
112+ /// The handler processes auto-completion requests, returning a list of suggestions based on the
113+ /// reference type and current argument value.
114+ /// </remarks>
115+ public Func < RequestContext < CompleteRequestParams > , CancellationToken , ValueTask < CompleteResult > > ? CompleteHandler { get ; set ; }
116+
117+ /// <summary>
118+ /// Gets or sets the handler for <see cref="RequestMethods.ResourcesSubscribe"/> requests.
119+ /// </summary>
120+ /// <remarks>
121+ /// <para>
122+ /// This handler is invoked when a client wants to receive notifications about changes to specific resources or resource patterns.
123+ /// The handler should implement logic to register the client's interest in the specified resources
124+ /// and set up the necessary infrastructure to send notifications when those resources change.
125+ /// </para>
126+ /// <para>
127+ /// After a successful subscription, the server should send resource change notifications to the client
128+ /// whenever a relevant resource is created, updated, or deleted.
129+ /// </para>
130+ /// </remarks>
131+ public Func < RequestContext < SubscribeRequestParams > , CancellationToken , ValueTask < EmptyResult > > ? SubscribeToResourcesHandler { get ; set ; }
132+
133+ /// <summary>
134+ /// Gets or sets the handler for <see cref="RequestMethods.ResourcesUnsubscribe"/> requests.
135+ /// </summary>
136+ /// <remarks>
137+ /// <para>
138+ /// This handler is invoked when a client wants to stop receiving notifications about previously subscribed resources.
139+ /// The handler should implement logic to remove the client's subscriptions to the specified resources
140+ /// and clean up any associated resources.
141+ /// </para>
142+ /// <para>
143+ /// After a successful unsubscription, the server should no longer send resource change notifications
144+ /// to the client for the specified resources.
145+ /// </para>
146+ /// </remarks>
147+ public Func < RequestContext < UnsubscribeRequestParams > , CancellationToken , ValueTask < EmptyResult > > ? UnsubscribeFromResourcesHandler { get ; set ; }
148+
149+ /// <summary>
150+ /// Gets or sets the handler for <see cref="RequestMethods.LoggingSetLevel"/> requests.
151+ /// </summary>
152+ /// <remarks>
153+ /// <para>
154+ /// This handler processes <see cref="RequestMethods.LoggingSetLevel"/> requests from clients. When set, it enables
155+ /// clients to control which log messages they receive by specifying a minimum severity threshold.
156+ /// </para>
157+ /// <para>
158+ /// After handling a level change request, the server typically begins sending log messages
159+ /// at or above the specified level to the client as notifications/message notifications.
160+ /// </para>
161+ /// </remarks>
162+ public Func < RequestContext < SetLevelRequestParams > , CancellationToken , ValueTask < EmptyResult > > ? SetLoggingLevelHandler { get ; set ; }
163+
164+ /// <summary>
165+ /// Overwrite any handlers in McpServerOptions with non-null handlers from this instance.
166+ /// </summary>
167+ /// <param name="options"></param>
168+ /// <returns></returns>
169+ internal void OverwriteWithSetHandlers ( McpServerOptions options )
170+ {
171+ PromptsCapability ? promptsCapability = options . Capabilities ? . Prompts ;
172+ if ( ListPromptsHandler is not null || GetPromptHandler is not null )
173+ {
174+ promptsCapability ??= new ( ) ;
175+ promptsCapability . ListPromptsHandler = ListPromptsHandler ?? promptsCapability . ListPromptsHandler ;
176+ promptsCapability . GetPromptHandler = GetPromptHandler ?? promptsCapability . GetPromptHandler ;
177+ }
178+
179+ ResourcesCapability ? resourcesCapability = options . Capabilities ? . Resources ;
180+ if ( ListResourcesHandler is not null ||
181+ ReadResourceHandler is not null )
182+ {
183+ resourcesCapability ??= new ( ) ;
184+ resourcesCapability . ListResourceTemplatesHandler = ListResourceTemplatesHandler ?? resourcesCapability . ListResourceTemplatesHandler ;
185+ resourcesCapability . ListResourcesHandler = ListResourcesHandler ?? resourcesCapability . ListResourcesHandler ;
186+ resourcesCapability . ReadResourceHandler = ReadResourceHandler ?? resourcesCapability . ReadResourceHandler ;
187+
188+ if ( SubscribeToResourcesHandler is not null || UnsubscribeFromResourcesHandler is not null )
189+ {
190+ resourcesCapability . SubscribeToResourcesHandler = SubscribeToResourcesHandler ?? resourcesCapability . SubscribeToResourcesHandler ;
191+ resourcesCapability . UnsubscribeFromResourcesHandler = UnsubscribeFromResourcesHandler ?? resourcesCapability . UnsubscribeFromResourcesHandler ;
192+ resourcesCapability . Subscribe = true ;
193+ }
194+ }
195+
196+ ToolsCapability ? toolsCapability = options . Capabilities ? . Tools ;
197+ if ( ListToolsHandler is not null || CallToolHandler is not null )
198+ {
199+ toolsCapability ??= new ( ) ;
200+ toolsCapability . ListToolsHandler = ListToolsHandler ?? toolsCapability . ListToolsHandler ;
201+ toolsCapability . CallToolHandler = CallToolHandler ?? toolsCapability . CallToolHandler ;
202+ }
203+
204+ LoggingCapability ? loggingCapability = options . Capabilities ? . Logging ;
205+ if ( SetLoggingLevelHandler is not null )
206+ {
207+ loggingCapability ??= new ( ) ;
208+ loggingCapability . SetLoggingLevelHandler = SetLoggingLevelHandler ;
209+ }
210+
211+ CompletionsCapability ? completionsCapability = options . Capabilities ? . Completions ;
212+ if ( CompleteHandler is not null )
213+ {
214+ completionsCapability ??= new ( ) ;
215+ completionsCapability . CompleteHandler = CompleteHandler ;
216+ }
217+
218+ options . Capabilities ??= new ( ) ;
219+ options . Capabilities . Prompts = promptsCapability ;
220+ options . Capabilities . Resources = resourcesCapability ;
221+ options . Capabilities . Tools = toolsCapability ;
222+ options . Capabilities . Logging = loggingCapability ;
223+ options . Capabilities . Completions = completionsCapability ;
224+ }
225+ }
0 commit comments