using ModelContextProtocol.Protocol; using System.Diagnostics.CodeAnalysis; namespace ModelContextProtocol.Server; /// /// Provides a container for handlers used in the creation of an MCP server. /// /// /// /// This class provides a centralized collection of delegates that implement various capabilities of the Model Context Protocol. /// Each handler in this class corresponds to a specific endpoint in the Model Context Protocol and /// is responsible for processing a particular type of message. The handlers are used to customize /// the behavior of the MCP server by providing implementations for the various protocol operations. /// /// /// When a client sends a message to the server, the appropriate handler is invoked to process it /// according to the protocol specification. Which handler is selected /// is done based on an ordinal, case-sensitive string comparison. /// /// public sealed class McpServerHandlers { /// /// Gets or sets the handler for requests. /// /// /// /// The handler should return a list of available tools when requested by a client. /// It supports pagination through the cursor mechanism, where the client can make /// repeated calls with the cursor returned by the previous call to retrieve more tools. /// /// /// This handler works alongside any tools defined in the collection. /// Tools from both sources will be combined when returning results to clients. /// /// public McpRequestHandler? ListToolsHandler { get; set; } #pragma warning disable MCPEXP002 // CallToolHandler and CallToolWithAlternateHandler reference the experimental ResultOrAlternate seam /// /// Gets or sets the handler for requests. /// /// /// This handler is invoked when a client makes a call to a tool that isn't found in the collection. /// The handler should implement logic to execute the requested tool and return appropriate results. /// Use instead if the tool may return an alternate result /// for the caller to handle. /// /// is already set. public McpRequestHandler? CallToolHandler { get; set { if (value is not null && CallToolWithAlternateHandler is not null) { throw new InvalidOperationException( $"Cannot set {nameof(CallToolHandler)} when {nameof(CallToolWithAlternateHandler)} is already set. Only one call tool handler may be configured."); } field = value; } } /// /// Gets or sets the handler for requests with alternate result support. /// /// /// /// This handler is invoked when a client makes a call to a tool, allowing the tool to return either /// a for immediate results or an alternate subtype. /// /// /// This is a low-level full replacement for the ordinary tool-call pipeline. It cannot be set if /// is already set, and it cannot be composed with ordinary /// . /// /// /// is already set. [Experimental(Experimentals.Extensibility_DiagnosticId, UrlFormat = Experimentals.Extensibility_Url)] public McpRequestHandler>? CallToolWithAlternateHandler { get; set { if (value is not null && CallToolHandler is not null) { throw new InvalidOperationException( $"Cannot set {nameof(CallToolWithAlternateHandler)} when {nameof(CallToolHandler)} is already set. Only one call tool handler may be configured."); } field = value; } } #pragma warning restore MCPEXP002 /// /// Gets or sets the handler for requests. /// /// /// /// The handler should return a list of available prompts when requested by a client. /// It supports pagination through the cursor mechanism, where the client can make /// repeated calls with the cursor returned by the previous call to retrieve more prompts. /// /// /// This handler works alongside any prompts defined in the collection. /// Prompts from both sources will be combined when returning results to clients. /// /// public McpRequestHandler? ListPromptsHandler { get; set; } /// /// Gets or sets the handler for requests. /// /// /// This handler is invoked when a client requests details for a specific prompt that isn't found in the collection. /// The handler should implement logic to fetch or generate the requested prompt and return appropriate results. /// public McpRequestHandler? GetPromptHandler { get; set; } /// /// Gets or sets the handler for requests. /// /// /// The handler should return a list of available resource templates when requested by a client. /// It supports pagination through the cursor mechanism, where the client can make /// repeated calls with the cursor returned by the previous call to retrieve more resource templates. /// public McpRequestHandler? ListResourceTemplatesHandler { get; set; } /// /// Gets or sets the handler for requests. /// /// /// The handler should return a list of available resources when requested by a client. /// It supports pagination through the cursor mechanism, where the client can make /// repeated calls with the cursor returned by the previous call to retrieve more resources. /// public McpRequestHandler? ListResourcesHandler { get; set; } /// /// Gets or sets the handler for requests. /// /// /// This handler is invoked when a client requests the content of a specific resource identified by its URI. /// The handler should implement logic to locate and retrieve the requested resource. /// public McpRequestHandler? ReadResourceHandler { get; set; } /// /// Gets or sets the handler for requests. /// /// /// This handler provides auto-completion suggestions for prompt arguments or resource references in the Model Context Protocol. /// The handler processes auto-completion requests, returning a list of suggestions based on the /// reference type and current argument value. /// public McpRequestHandler? CompleteHandler { get; set; } /// /// Gets or sets the handler for requests. /// /// /// /// This handler is invoked when a client wants to receive notifications about changes to specific resources or resource patterns. /// The handler should implement logic to register the client's interest in the specified resources /// and set up the necessary infrastructure to send notifications when those resources change. /// /// /// After a successful subscription, the server should send resource change notifications to the client /// whenever a relevant resource is created, updated, or deleted. /// /// public McpRequestHandler? SubscribeToResourcesHandler { get; set; } /// /// Gets or sets the handler for requests. /// /// /// /// This handler is invoked when a client wants to stop receiving notifications about previously subscribed resources. /// The handler should implement logic to remove the client's subscriptions to the specified resources /// and clean up any associated resources. /// /// /// After a successful unsubscription, the server should no longer send resource change notifications /// to the client for the specified resources. /// /// public McpRequestHandler? UnsubscribeFromResourcesHandler { get; set; } /// /// Gets or sets the handler for requests (SEP-2575). /// /// /// /// subscriptions/listen is a long-lived request introduced by the 2026-07-28 protocol revision. The /// held-open response is a solicited server-to-client stream: the server first acknowledges which /// subscriptions it will honor and then streams matching notifications until the request is cancelled. /// Setting this handler lets a server author own that stream directly to implement custom subscription /// kinds, application-driven resources/updated delivery, or subscriptions backed by their own event /// source. It is especially useful for stateless Streamable HTTP, where unsolicited notifications are /// dropped (there is no session-wide channel) but the listen request's response stream can still carry /// notifications for the duration of the request. /// /// /// This is a full replacement for the built-in subscriptions/listen handler. When set, the /// SDK does not track the subscription, does not send the acknowledgement, and does not perform any /// automatic */list_changed fan-out for the request; the handler is solely responsible for the /// entire lifetime of the stream. The SDK still enforces protocol-version gating: the handler is only /// reached when the negotiated protocol revision is 2026-07-28 or later, and is otherwise rejected with /// . /// /// /// An implementation of this handler is responsible for: /// /// /// /// Sending exactly one before any /// subscription events, reporting only the filters it actually honors. Advertised server capabilities must /// match what the handler will actually deliver. /// /// /// Tagging every streamed notification with the listen request id under /// _meta[] so clients sharing a channel can demultiplex it. /// /// /// Remaining active for the subscription lifetime and cleaning up when the supplied /// is cancelled (client disconnect on HTTP, or /// notifications/cancelled on stdio). /// /// /// Returning when it deliberately completes the stream. /// /// /// /// Notifications are sent through the request's server (for example request.Server.SendMessageAsync), /// which routes them over the request's own response stream. For extension filters not represented by /// , the handler can inspect /// request.JsonRpcRequest.Params. Application services and event buses can be resolved from /// request.Services or captured by the handler delegate. /// /// public McpRequestHandler? SubscriptionsListenHandler { get; set; } /// /// Gets or sets the handler for requests. /// /// /// /// This handler processes requests from clients. When set, it enables /// clients to control which log messages they receive by specifying a minimum severity threshold. /// /// /// After handling a level change request, the server typically begins sending log messages /// at or above the specified level to the client as notifications/message notifications. /// /// [Obsolete(Obsoletions.DeprecatedLogging_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)] public McpRequestHandler? SetLoggingLevelHandler { get; set; } /// Gets or sets notification handlers to register with the server. /// /// /// When constructed, the server will enumerate these handlers, which may contain multiple handlers per notification method key, once. /// The server will not re-enumerate the sequence after initialization. /// /// /// Notification handlers allow the server to respond to client-sent notifications for specific methods. /// Each key in the collection is a notification method name, and each value is a callback that will be invoked /// when a notification with that method is received. /// /// /// Handlers provided via will be registered with the server for the lifetime of the server. /// For transient handlers, may be used to register a handler that can /// then be unregistered by disposing of the returned from the method. /// /// public IEnumerable>>? NotificationHandlers { get; set; } }