diff --git a/src/ModelContextProtocol.Core/Client/McpClientHandlers.cs b/src/ModelContextProtocol.Core/Client/McpClientHandlers.cs index 452070c13..9fb26d5c3 100644 --- a/src/ModelContextProtocol.Core/Client/McpClientHandlers.cs +++ b/src/ModelContextProtocol.Core/Client/McpClientHandlers.cs @@ -22,7 +22,7 @@ namespace ModelContextProtocol.Client; /// is done based on an ordinal, case-sensitive string comparison. /// /// -public class McpClientHandlers +public sealed class McpClientHandlers { /// Gets or sets notification handlers to register with the client. /// diff --git a/src/ModelContextProtocol.Core/Server/McpMessageFilters.cs b/src/ModelContextProtocol.Core/Server/McpMessageFilters.cs index 11923d411..82b972b6e 100644 --- a/src/ModelContextProtocol.Core/Server/McpMessageFilters.cs +++ b/src/ModelContextProtocol.Core/Server/McpMessageFilters.cs @@ -8,7 +8,7 @@ namespace ModelContextProtocol.Server; public sealed class McpMessageFilters { /// - /// Gets the filters for all incoming JSON-RPC messages. + /// Gets or sets the filters for all incoming JSON-RPC messages. /// /// /// @@ -21,10 +21,18 @@ public sealed class McpMessageFilters /// the next handler in the pipeline, the default handlers will not be executed. /// /// - public IList IncomingFilters { get; } = []; + public IList IncomingFilters + { + get => field ??= []; + set + { + Throw.IfNull(value); + field = value; + } + } /// - /// Gets the filters for all outgoing JSON-RPC messages. + /// Gets or sets the filters for all outgoing JSON-RPC messages. /// /// /// @@ -38,5 +46,13 @@ public sealed class McpMessageFilters /// server-to-client messages. /// /// - public IList OutgoingFilters { get; } = []; + public IList OutgoingFilters + { + get => field ??= []; + set + { + Throw.IfNull(value); + field = value; + } + } } diff --git a/src/ModelContextProtocol.Core/Server/McpRequestFilters.cs b/src/ModelContextProtocol.Core/Server/McpRequestFilters.cs index 530a30aa4..5044f8928 100644 --- a/src/ModelContextProtocol.Core/Server/McpRequestFilters.cs +++ b/src/ModelContextProtocol.Core/Server/McpRequestFilters.cs @@ -8,7 +8,7 @@ namespace ModelContextProtocol.Server; public sealed class McpRequestFilters { /// - /// Gets the filters for the list-tools handler pipeline. + /// Gets or sets the filters for the list-tools handler pipeline. /// /// /// @@ -22,20 +22,36 @@ public sealed class McpRequestFilters /// Tools from both sources will be combined when returning results to clients. /// /// - public IList> ListToolsFilters { get; } = []; + public IList> ListToolsFilters + { + get => field ??= []; + set + { + Throw.IfNull(value); + field = value; + } + } /// - /// Gets the filters for the call-tool handler pipeline. + /// Gets or sets the filters for the call-tool handler pipeline. /// /// /// These filters wrap handlers that are invoked when a client makes a call to a tool that isn't found in the collection. /// The filters can modify, log, or perform additional operations on requests and responses for /// requests. The handler should implement logic to execute the requested tool and return appropriate results. /// - public IList> CallToolFilters { get; } = []; + public IList> CallToolFilters + { + get => field ??= []; + set + { + Throw.IfNull(value); + field = value; + } + } /// - /// Gets the filters for the list-prompts handler pipeline. + /// Gets or sets the filters for the list-prompts handler pipeline. /// /// /// @@ -49,20 +65,36 @@ public sealed class McpRequestFilters /// Prompts from both sources will be combined when returning results to clients. /// /// - public IList> ListPromptsFilters { get; } = []; + public IList> ListPromptsFilters + { + get => field ??= []; + set + { + Throw.IfNull(value); + field = value; + } + } /// - /// Gets the filters for the get-prompt handler pipeline. + /// Gets or sets the filters for the get-prompt handler pipeline. /// /// /// These filters wrap handlers that are invoked when a client requests details for a specific prompt that isn't found in the collection. /// The filters can modify, log, or perform additional operations on requests and responses for /// requests. The handler should implement logic to fetch or generate the requested prompt and return appropriate results. /// - public IList> GetPromptFilters { get; } = []; + public IList> GetPromptFilters + { + get => field ??= []; + set + { + Throw.IfNull(value); + field = value; + } + } /// - /// Gets the filters for the list-resource-templates handler pipeline. + /// Gets or sets the filters for the list-resource-templates handler pipeline. /// /// /// These filters wrap handlers that return a list of available resource templates when requested by a client. @@ -70,10 +102,18 @@ public sealed class McpRequestFilters /// requests. 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 IList> ListResourceTemplatesFilters { get; } = []; + public IList> ListResourceTemplatesFilters + { + get => field ??= []; + set + { + Throw.IfNull(value); + field = value; + } + } /// - /// Gets the filters for the list-resources handler pipeline. + /// Gets or sets the filters for the list-resources handler pipeline. /// /// /// These filters wrap handlers that return a list of available resources when requested by a client. @@ -81,20 +121,36 @@ public sealed class McpRequestFilters /// requests. 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 IList> ListResourcesFilters { get; } = []; + public IList> ListResourcesFilters + { + get => field ??= []; + set + { + Throw.IfNull(value); + field = value; + } + } /// - /// Gets the filters for the read-resource handler pipeline. + /// Gets or sets the filters for the read-resource handler pipeline. /// /// /// These filters wrap handlers that are invoked when a client requests the content of a specific resource identified by its URI. /// The filters can modify, log, or perform additional operations on requests and responses for /// requests. The handler should implement logic to locate and retrieve the requested resource. /// - public IList> ReadResourceFilters { get; } = []; + public IList> ReadResourceFilters + { + get => field ??= []; + set + { + Throw.IfNull(value); + field = value; + } + } /// - /// Gets the filters for the complete-handler pipeline. + /// Gets or sets the filters for the complete-handler pipeline. /// /// /// These filters wrap handlers that provide auto-completion suggestions for prompt arguments or resource references in the Model Context Protocol. @@ -102,10 +158,18 @@ public sealed class McpRequestFilters /// requests. The handler processes auto-completion requests, returning a list of suggestions based on the /// reference type and current argument value. /// - public IList> CompleteFilters { get; } = []; + public IList> CompleteFilters + { + get => field ??= []; + set + { + Throw.IfNull(value); + field = value; + } + } /// - /// Gets the filters for the subscribe-to-resources handler pipeline. + /// Gets or sets the filters for the subscribe-to-resources handler pipeline. /// /// /// @@ -119,10 +183,18 @@ public sealed class McpRequestFilters /// whenever a relevant resource is created, updated, or deleted. /// /// - public IList> SubscribeToResourcesFilters { get; } = []; + public IList> SubscribeToResourcesFilters + { + get => field ??= []; + set + { + Throw.IfNull(value); + field = value; + } + } /// - /// Gets the filters for the unsubscribe-from-resources handler pipeline. + /// Gets or sets the filters for the unsubscribe-from-resources handler pipeline. /// /// /// @@ -136,10 +208,18 @@ public sealed class McpRequestFilters /// to the client for the specified resources. /// /// - public IList> UnsubscribeFromResourcesFilters { get; } = []; + public IList> UnsubscribeFromResourcesFilters + { + get => field ??= []; + set + { + Throw.IfNull(value); + field = value; + } + } /// - /// Gets the filters for the set-logging-level handler pipeline. + /// Gets or sets the filters for the set-logging-level handler pipeline. /// /// /// @@ -153,5 +233,13 @@ public sealed class McpRequestFilters /// at or above the specified level to the client as notifications/message notifications. /// /// - public IList> SetLoggingLevelFilters { get; } = []; + public IList> SetLoggingLevelFilters + { + get => field ??= []; + set + { + Throw.IfNull(value); + field = value; + } + } } diff --git a/src/ModelContextProtocol.Core/Server/McpServerFilters.cs b/src/ModelContextProtocol.Core/Server/McpServerFilters.cs index 39fa1d6a7..d165d55e4 100644 --- a/src/ModelContextProtocol.Core/Server/McpServerFilters.cs +++ b/src/ModelContextProtocol.Core/Server/McpServerFilters.cs @@ -12,12 +12,28 @@ namespace ModelContextProtocol.Server; public sealed class McpServerFilters { /// - /// Gets the filters for incoming and outgoing JSON-RPC messages. + /// Gets or sets the filters for incoming and outgoing JSON-RPC messages. /// - public McpMessageFilters Message { get; } = new(); + public McpMessageFilters Message + { + get => field ??= new(); + set + { + Throw.IfNull(value); + field = value; + } + } /// - /// Gets the filters for request-specific MCP handler pipelines. + /// Gets or sets the filters for request-specific MCP handler pipelines. /// - public McpRequestFilters Request { get; } = new(); + public McpRequestFilters Request + { + get => field ??= new(); + set + { + Throw.IfNull(value); + field = value; + } + } } diff --git a/src/ModelContextProtocol.Core/Server/McpServerOptions.cs b/src/ModelContextProtocol.Core/Server/McpServerOptions.cs index b1a63ab0b..a8d232980 100644 --- a/src/ModelContextProtocol.Core/Server/McpServerOptions.cs +++ b/src/ModelContextProtocol.Core/Server/McpServerOptions.cs @@ -97,17 +97,33 @@ public sealed class McpServerOptions /// /// Gets or sets the container of handlers used by the server for processing protocol messages. /// - public McpServerHandlers Handlers { get; } = new(); + public McpServerHandlers Handlers + { + get => field ??= new(); + set + { + Throw.IfNull(value); + field = value; + } + } /// - /// Gets the filter collections for MCP server handlers. + /// Gets or sets the filter collections for MCP server handlers. /// /// /// This property provides access to filter collections that can be used to modify the behavior /// of various MCP server handlers. The first filter added is the outermost (first to execute), /// and each subsequent filter wraps closer to the handler. /// - public McpServerFilters Filters { get; } = new(); + public McpServerFilters Filters + { + get => field ??= new(); + set + { + Throw.IfNull(value); + field = value; + } + } /// /// Gets or sets a collection of tools served by the server. diff --git a/tests/ModelContextProtocol.TestSseServer/Program.cs b/tests/ModelContextProtocol.TestSseServer/Program.cs index 2222f5b5d..1a27c0c15 100644 --- a/tests/ModelContextProtocol.TestSseServer/Program.cs +++ b/tests/ModelContextProtocol.TestSseServer/Program.cs @@ -90,313 +90,316 @@ static CreateMessageRequestParams CreateRequestSamplingParams(string context, st } const int pageSize = 10; - options.Handlers.ListToolsHandler = async (request, cancellationToken) => + options.Handlers = new() { - return new ListToolsResult + ListToolsHandler = async (request, cancellationToken) => { - Tools = - [ - new Tool - { - Name = "echo", - Description = "Echoes the input back to the client.", - InputSchema = JsonElement.Parse(""" - { - "type": "object", - "properties": { - "message": { - "type": "string", - "description": "The input to echo back." - } - }, - "required": ["message"] - } - """), - }, - new Tool - { - Name = "echoSessionId", - Description = "Echoes the session id back to the client.", - InputSchema = JsonElement.Parse(""" - { - "type": "object" - } - """), - }, - new Tool - { - Name = "sampleLLM", - Description = "Samples from an LLM using MCP's sampling feature.", - InputSchema = JsonElement.Parse(""" - { - "type": "object", - "properties": { - "prompt": { - "type": "string", - "description": "The prompt to send to the LLM" + return new ListToolsResult + { + Tools = + [ + new Tool + { + Name = "echo", + Description = "Echoes the input back to the client.", + InputSchema = JsonElement.Parse(""" + { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "The input to echo back." + } }, - "maxTokens": { - "type": "number", - "description": "Maximum number of tokens to generate" - } - }, - "required": ["prompt", "maxTokens"] - } - """), - }, - new Tool - { - Name = "longRunning", - Description = "Simulates a long-running operation that supports task-based execution.", - InputSchema = JsonElement.Parse(""" + "required": ["message"] + } + """), + }, + new Tool + { + Name = "echoSessionId", + Description = "Echoes the session id back to the client.", + InputSchema = JsonElement.Parse(""" + { + "type": "object" + } + """), + }, + new Tool + { + Name = "sampleLLM", + Description = "Samples from an LLM using MCP's sampling feature.", + InputSchema = JsonElement.Parse(""" + { + "type": "object", + "properties": { + "prompt": { + "type": "string", + "description": "The prompt to send to the LLM" + }, + "maxTokens": { + "type": "number", + "description": "Maximum number of tokens to generate" + } + }, + "required": ["prompt", "maxTokens"] + } + """), + }, + new Tool + { + Name = "longRunning", + Description = "Simulates a long-running operation that supports task-based execution.", + InputSchema = JsonElement.Parse(""" + { + "type": "object", + "properties": { + "durationMs": { + "type": "number", + "description": "Duration of the operation in milliseconds" + } + }, + "required": ["durationMs"] + } + """), + Execution = new ToolExecution { - "type": "object", - "properties": { - "durationMs": { - "type": "number", - "description": "Duration of the operation in milliseconds" - } - }, - "required": ["durationMs"] + TaskSupport = ToolTaskSupport.Optional } - """), - Execution = new ToolExecution - { - TaskSupport = ToolTaskSupport.Optional } - } - ] - }; - }; - - options.Handlers.CallToolHandler = async (request, cancellationToken) => - { - if (request.Params is null) - { - throw new McpProtocolException("Missing required parameter 'name'", McpErrorCode.InvalidParams); - } - - if (request.Params.Name == "echo") - { - if (request.Params.Arguments is null || !request.Params.Arguments.TryGetValue("message", out var message)) - { - throw new McpProtocolException("Missing required argument 'message'", McpErrorCode.InvalidParams); - } - return new CallToolResult - { - Content = [new TextContentBlock { Text = $"Echo: {message}" }] - }; - } - else if (request.Params.Name == "echoSessionId") - { - return new CallToolResult - { - Content = [new TextContentBlock { Text = request.Server.SessionId ?? string.Empty }] + ] }; - } - else if (request.Params.Name == "sampleLLM") + }, + + CallToolHandler = async (request, cancellationToken) => { - if (request.Params.Arguments is null || - !request.Params.Arguments.TryGetValue("prompt", out var prompt) || - !request.Params.Arguments.TryGetValue("maxTokens", out var maxTokens)) + if (request.Params is null) { - throw new McpProtocolException("Missing required arguments 'prompt' and 'maxTokens'", McpErrorCode.InvalidParams); + throw new McpProtocolException("Missing required parameter 'name'", McpErrorCode.InvalidParams); } - var sampleResult = await request.Server.SampleAsync(CreateRequestSamplingParams(prompt.ToString(), "sampleLLM", Convert.ToInt32(maxTokens.ToString())), - cancellationToken: cancellationToken); - return new CallToolResult + if (request.Params.Name == "echo") { - Content = [new TextContentBlock { Text = $"LLM sampling result: {sampleResult.Content.OfType().FirstOrDefault()?.Text}" }] - }; - } - else if (request.Params.Name == "longRunning") - { - if (request.Params.Arguments is null || !request.Params.Arguments.TryGetValue("durationMs", out var durationMsValue)) + if (request.Params.Arguments is null || !request.Params.Arguments.TryGetValue("message", out var message)) + { + throw new McpProtocolException("Missing required argument 'message'", McpErrorCode.InvalidParams); + } + return new CallToolResult + { + Content = [new TextContentBlock { Text = $"Echo: {message}" }] + }; + } + else if (request.Params.Name == "echoSessionId") { - throw new McpProtocolException("Missing required argument 'durationMs'", McpErrorCode.InvalidParams); + return new CallToolResult + { + Content = [new TextContentBlock { Text = request.Server.SessionId ?? string.Empty }] + }; } - int durationMs = Convert.ToInt32(durationMsValue.ToString()); - await Task.Delay(durationMs, cancellationToken); - return new CallToolResult + else if (request.Params.Name == "sampleLLM") { - Content = [new TextContentBlock { Text = $"Long-running operation completed after {durationMs}ms" }] - }; - } - else - { - throw new McpProtocolException($"Unknown tool: '{request.Params.Name}'", McpErrorCode.InvalidParams); - } - }; + if (request.Params.Arguments is null || + !request.Params.Arguments.TryGetValue("prompt", out var prompt) || + !request.Params.Arguments.TryGetValue("maxTokens", out var maxTokens)) + { + throw new McpProtocolException("Missing required arguments 'prompt' and 'maxTokens'", McpErrorCode.InvalidParams); + } + var sampleResult = await request.Server.SampleAsync(CreateRequestSamplingParams(prompt.ToString(), "sampleLLM", Convert.ToInt32(maxTokens.ToString())), + cancellationToken: cancellationToken); - options.Handlers.ListResourceTemplatesHandler = async (request, cancellationToken) => - { - return new ListResourceTemplatesResult - { - ResourceTemplates = [ - new ResourceTemplate - { - UriTemplate = "test://dynamic/resource/{id}", - Name = "Dynamic Resource", + return new CallToolResult + { + Content = [new TextContentBlock { Text = $"LLM sampling result: {sampleResult.Content.OfType().FirstOrDefault()?.Text}" }] + }; } - ] - }; - }; - - options.Handlers.ListResourcesHandler = async (request, cancellationToken) => - { - int startIndex = 0; - var requestParams = request.Params ?? new(); - - if (requestParams.Cursor is not null) - { - try + else if (request.Params.Name == "longRunning") { - var startIndexAsString = Encoding.UTF8.GetString(Convert.FromBase64String(requestParams.Cursor)); - startIndex = Convert.ToInt32(startIndexAsString); + if (request.Params.Arguments is null || !request.Params.Arguments.TryGetValue("durationMs", out var durationMsValue)) + { + throw new McpProtocolException("Missing required argument 'durationMs'", McpErrorCode.InvalidParams); + } + int durationMs = Convert.ToInt32(durationMsValue.ToString()); + await Task.Delay(durationMs, cancellationToken); + return new CallToolResult + { + Content = [new TextContentBlock { Text = $"Long-running operation completed after {durationMs}ms" }] + }; } - catch (Exception e) + else { - throw new McpProtocolException($"Invalid cursor: '{requestParams.Cursor}'", e, McpErrorCode.InvalidParams); + throw new McpProtocolException($"Unknown tool: '{request.Params.Name}'", McpErrorCode.InvalidParams); } - } - - int endIndex = Math.Min(startIndex + pageSize, resources.Count); - string? nextCursor = null; + }, - if (endIndex < resources.Count) + ListResourceTemplatesHandler = async (request, cancellationToken) => { - nextCursor = Convert.ToBase64String(Encoding.UTF8.GetBytes(endIndex.ToString())); - } + return new ListResourceTemplatesResult + { + ResourceTemplates = [ + new ResourceTemplate + { + UriTemplate = "test://dynamic/resource/{id}", + Name = "Dynamic Resource", + } + ] + }; + }, - return new ListResourcesResult + ListResourcesHandler = async (request, cancellationToken) => { - NextCursor = nextCursor, - Resources = resources.GetRange(startIndex, endIndex - startIndex) - }; - }; + int startIndex = 0; + var requestParams = request.Params ?? new(); - options.Handlers.ReadResourceHandler = async (request, cancellationToken) => - { - if (request.Params?.Uri is null) - { - throw new McpProtocolException("Missing required argument 'uri'", McpErrorCode.InvalidParams); - } + if (requestParams.Cursor is not null) + { + try + { + var startIndexAsString = Encoding.UTF8.GetString(Convert.FromBase64String(requestParams.Cursor)); + startIndex = Convert.ToInt32(startIndexAsString); + } + catch (Exception e) + { + throw new McpProtocolException($"Invalid cursor: '{requestParams.Cursor}'", e, McpErrorCode.InvalidParams); + } + } - if (request.Params.Uri.StartsWith("test://dynamic/resource/")) - { - var id = request.Params.Uri.Split('/').LastOrDefault(); - if (string.IsNullOrEmpty(id)) + int endIndex = Math.Min(startIndex + pageSize, resources.Count); + string? nextCursor = null; + + if (endIndex < resources.Count) { - throw new McpProtocolException($"Invalid resource URI: '{request.Params.Uri}'", McpErrorCode.InvalidParams); + nextCursor = Convert.ToBase64String(Encoding.UTF8.GetBytes(endIndex.ToString())); } - return new ReadResourceResult + return new ListResourcesResult { - Contents = [ - new TextResourceContents - { - Uri = request.Params.Uri, - MimeType = "text/plain", - Text = $"Dynamic resource {id}: This is a plaintext resource" - } - ] + NextCursor = nextCursor, + Resources = resources.GetRange(startIndex, endIndex - startIndex) }; - } - - ResourceContents? contents = resourceContents.FirstOrDefault(r => r.Uri == request.Params.Uri) ?? - throw new McpProtocolException($"Resource not found: '{request.Params.Uri}'", McpErrorCode.ResourceNotFound); + }, - return new ReadResourceResult + ReadResourceHandler = async (request, cancellationToken) => { - Contents = [contents] - }; - }; + if (request.Params?.Uri is null) + { + throw new McpProtocolException("Missing required argument 'uri'", McpErrorCode.InvalidParams); + } - options.Handlers.ListPromptsHandler = async (request, cancellationToken) => - { - return new ListPromptsResult - { - Prompts = [ - new Prompt - { - Name = "simple_prompt", - Description = "A prompt without arguments" - }, - new Prompt + if (request.Params.Uri.StartsWith("test://dynamic/resource/")) + { + var id = request.Params.Uri.Split('/').LastOrDefault(); + if (string.IsNullOrEmpty(id)) { - Name = "complex_prompt", - Description = "A prompt with arguments", - Arguments = - [ - new PromptArgument - { - Name = "temperature", - Description = "Temperature setting", - Required = true - }, - new PromptArgument - { - Name = "style", - Description = "Output style", - Required = false - } - ], + throw new McpProtocolException($"Invalid resource URI: '{request.Params.Uri}'", McpErrorCode.InvalidParams); } - ] - }; - }; - options.Handlers.GetPromptHandler = async (request, cancellationToken) => - { - if (request.Params is null) - { - throw new McpProtocolException("Missing required parameter 'name'", McpErrorCode.InvalidParams); - } + return new ReadResourceResult + { + Contents = [ + new TextResourceContents + { + Uri = request.Params.Uri, + MimeType = "text/plain", + Text = $"Dynamic resource {id}: This is a plaintext resource" + } + ] + }; + } - List messages = []; + ResourceContents? contents = resourceContents.FirstOrDefault(r => r.Uri == request.Params.Uri) ?? + throw new McpProtocolException($"Resource not found: '{request.Params.Uri}'", McpErrorCode.ResourceNotFound); - if (request.Params.Name == "simple_prompt") + return new ReadResourceResult + { + Contents = [contents] + }; + }, + + ListPromptsHandler = async (request, cancellationToken) => { - messages.Add(new PromptMessage + return new ListPromptsResult { - Role = Role.User, - Content = new TextContentBlock { Text = "This is a simple prompt without arguments." }, - }); - } - else if (request.Params.Name == "complex_prompt") + Prompts = [ + new Prompt + { + Name = "simple_prompt", + Description = "A prompt without arguments" + }, + new Prompt + { + Name = "complex_prompt", + Description = "A prompt with arguments", + Arguments = + [ + new PromptArgument + { + Name = "temperature", + Description = "Temperature setting", + Required = true + }, + new PromptArgument + { + Name = "style", + Description = "Output style", + Required = false + } + ], + } + ] + }; + }, + + GetPromptHandler = async (request, cancellationToken) => { - string temperature = request.Params.Arguments?["temperature"].ToString() ?? "unknown"; - string style = request.Params.Arguments?["style"].ToString() ?? "unknown"; - messages.Add(new PromptMessage + if (request.Params is null) { - Role = Role.User, - Content = new TextContentBlock { Text = $"This is a complex prompt with arguments: temperature={temperature}, style={style}" }, - }); - messages.Add(new PromptMessage + throw new McpProtocolException("Missing required parameter 'name'", McpErrorCode.InvalidParams); + } + + List messages = []; + + if (request.Params.Name == "simple_prompt") { - Role = Role.User, - Content = new TextContentBlock { Text = "I understand. You've provided a complex prompt with temperature and style arguments. How would you like me to proceed?" }, - }); - messages.Add(new PromptMessage + messages.Add(new PromptMessage + { + Role = Role.User, + Content = new TextContentBlock { Text = "This is a simple prompt without arguments." }, + }); + } + else if (request.Params.Name == "complex_prompt") { - Role = Role.User, - Content = new ImageContentBlock + string temperature = request.Params.Arguments?["temperature"].ToString() ?? "unknown"; + string style = request.Params.Arguments?["style"].ToString() ?? "unknown"; + messages.Add(new PromptMessage { - Data = System.Text.Encoding.UTF8.GetBytes(MCP_TINY_IMAGE), - MimeType = "image/png" - } - }); - } - else - { - throw new McpProtocolException($"Unknown prompt: {request.Params.Name}", McpErrorCode.InvalidParams); - } + Role = Role.User, + Content = new TextContentBlock { Text = $"This is a complex prompt with arguments: temperature={temperature}, style={style}" }, + }); + messages.Add(new PromptMessage + { + Role = Role.User, + Content = new TextContentBlock { Text = "I understand. You've provided a complex prompt with temperature and style arguments. How would you like me to proceed?" }, + }); + messages.Add(new PromptMessage + { + Role = Role.User, + Content = new ImageContentBlock + { + Data = System.Text.Encoding.UTF8.GetBytes(MCP_TINY_IMAGE), + MimeType = "image/png" + } + }); + } + else + { + throw new McpProtocolException($"Unknown prompt: {request.Params.Name}", McpErrorCode.InvalidParams); + } - return new GetPromptResult - { - Messages = messages - }; + return new GetPromptResult + { + Messages = messages + }; + }, }; }