diff --git a/README.MD b/README.MD
index f4c9a9f..a147e2f 100644
--- a/README.MD
+++ b/README.MD
@@ -80,6 +80,8 @@ Note that you should pass CancellationToken objects suitable for your use case,
It is also highly recommended that you pass a proper LoggerFactory instance to the factory constructor, to enable logging of MCP client operations.
+You can find samples demonstrating how to use mcpdotnet with an LLM SDK in the [samples](samples) directory, and also refer to the [IntegrationTests](test/McpDotNet.IntegrationTests) project for more examples.
+
Additional examples and documentation will be added as in the near future.
## Roadmap
@@ -89,7 +91,7 @@ Additional examples and documentation will be added as in the near future.
- Transport configuration
- Error handling and recovery
- Increase test coverage
-- Add example applications
+- Add additional samples and examples
- Performance optimization and profiling
## License
diff --git a/src/mcpdotnet.sln b/mcpdotnet.sln
similarity index 53%
rename from src/mcpdotnet.sln
rename to mcpdotnet.sln
index 874f1b3..11078af 100644
--- a/src/mcpdotnet.sln
+++ b/mcpdotnet.sln
@@ -3,9 +3,13 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.13.35507.96
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mcpdotnet", "mcpdotnet\mcpdotnet.csproj", "{12260CD2-AFFC-4B2E-8898-F442CAA1FA0F}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mcpdotnet", "src\mcpdotnet\mcpdotnet.csproj", "{12260CD2-AFFC-4B2E-8898-F442CAA1FA0F}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mcpdotnet.Tests", "mcpdotnet.Tests\mcpdotnet.Tests.csproj", "{FF41F619-833D-4FA2-8C53-04D0A1D5AA61}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mcpdotnet.Tests", "tests\mcpdotnet.Tests\mcpdotnet.Tests.csproj", "{FF41F619-833D-4FA2-8C53-04D0A1D5AA61}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MEAIToolsConsole", "samples\microsoft.extensions.ai\tools\ToolsConsole\MEAIToolsConsole.csproj", "{76E295FA-9E85-7B99-332A-2CDBFCD5860A}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AnthropicToolsConsole", "samples\anthropic\tools\ToolsConsole\AnthropicToolsConsole.csproj", "{CA0BB450-1903-2F92-A68D-1285976551D6}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -21,6 +25,14 @@ Global
{FF41F619-833D-4FA2-8C53-04D0A1D5AA61}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FF41F619-833D-4FA2-8C53-04D0A1D5AA61}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FF41F619-833D-4FA2-8C53-04D0A1D5AA61}.Release|Any CPU.Build.0 = Release|Any CPU
+ {76E295FA-9E85-7B99-332A-2CDBFCD5860A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {76E295FA-9E85-7B99-332A-2CDBFCD5860A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {76E295FA-9E85-7B99-332A-2CDBFCD5860A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {76E295FA-9E85-7B99-332A-2CDBFCD5860A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {CA0BB450-1903-2F92-A68D-1285976551D6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {CA0BB450-1903-2F92-A68D-1285976551D6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CA0BB450-1903-2F92-A68D-1285976551D6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {CA0BB450-1903-2F92-A68D-1285976551D6}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/samples/README.md b/samples/README.md
new file mode 100644
index 0000000..2c543f0
--- /dev/null
+++ b/samples/README.md
@@ -0,0 +1,41 @@
+# Samples
+
+This directory contains example projects demonstrating how to use mcpdotnet with different LLM SDKs and platforms.
+
+## Environment Setup
+
+Before running the samples, you'll need to set up the following environment variables:
+
+- `ANTHROPIC_API_KEY` - Required for the Anthropic sample
+- `OPENAI_API_KEY` - Required for the MEAI/OpenAI sample
+
+## Sample Projects
+
+### Anthropic Integration
+
+Located in `samples/anthropic`, this sample demonstrates integration with Anthropic's Claude API using mcpdotnet. The example shows how to:
+- Configure an MCP client for use with Anthropic
+- Map between MCP protocol types and Anthropic SDK types
+- Handle tool invocations and responses
+
+### Microsoft.Extensions.AI Integration
+
+Located in `samples/microsoft.extensions.ai`, this sample shows how to use mcpdotnet with Microsoft's AI SDK. It demonstrates:
+- Setting up an MCP client with MEAI
+- Mapping MCP tools to MEAI function calls
+- Handling streaming responses and tool invocations
+
+## Implementation Notes
+
+Each sample focuses on the mapping between MCP types and SDK-specific types, which is the primary integration point when working with different LLM SDKs. The samples provide reusable mapping code that can serve as a starting point for your own implementations.
+
+The complexity of this mapping varies depending on how closely the SDK's design aligns with typical LLM APIs. The provided samples demonstrate best practices for both straightforward and more complex mapping scenarios.
+
+## Running the Samples
+
+1. Clone the repository
+2. Set up the required environment variables
+3. Navigate to the desired sample directory
+4. Run `dotnet run` to execute the sample
+
+For more detailed examples of mcpdotnet usage, you can also refer to the integration tests in the `tests/McpDotNet.IntegrationTests` project.
\ No newline at end of file
diff --git a/samples/anthropic/tools/ToolsConsole/AnthropicToolsConsole.csproj b/samples/anthropic/tools/ToolsConsole/AnthropicToolsConsole.csproj
new file mode 100644
index 0000000..04a14b4
--- /dev/null
+++ b/samples/anthropic/tools/ToolsConsole/AnthropicToolsConsole.csproj
@@ -0,0 +1,18 @@
+
+
+
+ Exe
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/anthropic/tools/ToolsConsole/McpToolExtensions.cs b/samples/anthropic/tools/ToolsConsole/McpToolExtensions.cs
new file mode 100644
index 0000000..c9dbd20
--- /dev/null
+++ b/samples/anthropic/tools/ToolsConsole/McpToolExtensions.cs
@@ -0,0 +1,32 @@
+using Anthropic.SDK.Common;
+using System.Text.Json;
+using System.Text.Json.Nodes;
+
+public static class McpToolExtensions
+{
+ public static IList ToAnthropicTools(this IEnumerable tools)
+ {
+ List result = new();
+ foreach (var tool in tools)
+ {
+ var function = tool.InputSchema == null
+ ? new Function(tool.Name, tool.Description)
+ : new Function(tool.Name, tool.Description, JsonSerializer.Serialize(tool.InputSchema));
+ result.Add(function);
+ }
+ return result;
+ }
+
+ public static Dictionary? ToMCPArguments(this JsonNode jsonNode)
+ {
+ if (jsonNode == null)
+ return null;
+
+ // Convert JsonNode to Dictionary
+ return jsonNode.AsObject()
+ .ToDictionary(
+ prop => prop.Key,
+ prop => JsonSerializer.Deserialize(prop.Value)!
+ );
+ }
+}
\ No newline at end of file
diff --git a/samples/anthropic/tools/ToolsConsole/Program.cs b/samples/anthropic/tools/ToolsConsole/Program.cs
new file mode 100644
index 0000000..11f540e
--- /dev/null
+++ b/samples/anthropic/tools/ToolsConsole/Program.cs
@@ -0,0 +1,97 @@
+using McpDotNet.Client;
+using McpDotNet.Configuration;
+using Microsoft.Extensions.Logging.Abstractions;
+using Anthropic.SDK;
+using Anthropic.SDK.Messaging;
+using Anthropic.SDK.Constants;
+
+internal class Program
+{
+ private static async Task GetMcpClientAsync()
+ {
+
+ McpClientOptions options = new()
+ {
+ ClientInfo = new() { Name = "SimpleToolsConsole", Version = "1.0.0" }
+ };
+
+ var config = new McpServerConfig
+ {
+ Id = "everything",
+ Name = "Everything",
+ TransportType = "stdio",
+ TransportOptions = new Dictionary
+ {
+ ["command"] = "npx",
+ ["arguments"] = "-y @modelcontextprotocol/server-everything",
+ }
+ };
+
+ var factory = new McpClientFactory(
+ [config],
+ options,
+ NullLoggerFactory.Instance
+ );
+
+ return await factory.GetClientAsync("everything");
+ }
+
+ private static async Task Main(string[] args)
+ {
+ try
+ {
+ Console.WriteLine("Initializing MCP 'everything' server");
+ var client = await GetMcpClientAsync();
+ Console.WriteLine("MCP 'everything' server initialized");
+ Console.WriteLine("Listing tools...");
+ var tools = await client.ListToolsAsync();
+ var anthropicTools = tools.Tools.ToAnthropicTools();
+ Console.WriteLine("Tools available:");
+ foreach (var tool in anthropicTools)
+ {
+ Console.WriteLine(" " + tool.Function.Name);
+ }
+
+ Console.WriteLine("Starting chat with Claude Haiku 3.5...");
+ using var antClient = new AnthropicClient(Environment.GetEnvironmentVariable("ANTHROPIC_API_KEY")!);
+
+ Console.WriteLine("Asking Claude to call the Echo Tool...");
+
+ var messages = new List
+ {
+ new Message(RoleType.User, "Please call the echo tool with the string 'Hello MCP!' and give me the response as-is.")
+ };
+
+ var parameters = new MessageParameters()
+ {
+ Messages = messages,
+ MaxTokens = 2048,
+ Model = AnthropicModels.Claude35Haiku,
+ Stream = false,
+ Temperature = 1.0m,
+ Tools = anthropicTools
+ };
+ var res = await antClient.Messages.GetClaudeMessageAsync(parameters);
+
+ messages.Add(res.Message);
+
+ foreach (var toolCall in res.ToolCalls)
+ {
+ var response = await client.CallToolAsync(toolCall.Name, toolCall.Arguments?.ToMCPArguments());
+
+ messages.Add(new Message(toolCall, response.Content[0].Text));
+ }
+
+ var finalResult = await antClient.Messages.GetClaudeMessageAsync(parameters);
+ Console.WriteLine("Final result: " + finalResult.Message.ToString());
+
+ Console.WriteLine();
+
+ Console.WriteLine("Chat with Claude Haiku 3.5 complete");
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine("Error occurred: " + ex.Message);
+ }
+ }
+}
diff --git a/samples/anthropic/tools/ToolsConsole/Properties/launchSettings.json b/samples/anthropic/tools/ToolsConsole/Properties/launchSettings.json
new file mode 100644
index 0000000..68cd89e
--- /dev/null
+++ b/samples/anthropic/tools/ToolsConsole/Properties/launchSettings.json
@@ -0,0 +1,7 @@
+{
+ "profiles": {
+ "SimpleToolsConsole": {
+ "commandName": "Project"
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/microsoft.extensions.ai/tools/ToolsConsole/MEAIToolsConsole.csproj b/samples/microsoft.extensions.ai/tools/ToolsConsole/MEAIToolsConsole.csproj
new file mode 100644
index 0000000..fa62786
--- /dev/null
+++ b/samples/microsoft.extensions.ai/tools/ToolsConsole/MEAIToolsConsole.csproj
@@ -0,0 +1,16 @@
+
+
+
+ Exe
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
diff --git a/samples/microsoft.extensions.ai/tools/ToolsConsole/McpAIFunction.cs b/samples/microsoft.extensions.ai/tools/ToolsConsole/McpAIFunction.cs
new file mode 100644
index 0000000..bc0bd1e
--- /dev/null
+++ b/samples/microsoft.extensions.ai/tools/ToolsConsole/McpAIFunction.cs
@@ -0,0 +1,75 @@
+using McpDotNet.Client;
+using McpDotNet.Protocol.Types;
+using Microsoft.Extensions.AI;
+using SimpleToolsConsole;
+
+namespace SimpleToolsConsole;
+
+public class McpAIFunction : AIFunction
+{
+ private readonly Tool _tool;
+ private readonly IMcpClient _client;
+ private readonly AIFunctionMetadata _metadata;
+
+ public McpAIFunction(Tool tool, IMcpClient client)
+ {
+ _tool = tool ?? throw new ArgumentNullException(nameof(tool));
+ _client = client ?? throw new ArgumentNullException(nameof(client));
+ _metadata = new AIFunctionMetadata(tool.Name)
+ {
+ Description = tool.Description,
+ Parameters = MapFunctionParameters(tool.InputSchema),
+ ReturnParameter = new AIFunctionReturnParameterMetadata()
+ {
+ ParameterType = typeof(string),
+ }
+ };
+ }
+
+ public override string ToString() => _tool.Name;
+
+ protected async override Task InvokeCoreAsync(IEnumerable> arguments, CancellationToken cancellationToken)
+ {
+ // Convert arguments to dictionary format expected by mcpdotnet
+ Dictionary argDict = new();
+ foreach (var arg in arguments)
+ {
+ if (arg.Value is not null)
+ {
+ argDict[arg.Key] = arg.Value;
+ }
+ }
+
+ // Call the tool through mcpdotnet
+ var result = await _client.CallToolAsync(
+ _tool.Name,
+ argDict.Count == 0 ? null: argDict,
+ cancellationToken: cancellationToken
+ );
+
+ // Extract the text content from the result
+ // For simplicity in this sample, we'll just concatenate all text content
+ return string.Join("\n", result.Content
+ .Where(c => c.Type == "text")
+ .Select(c => c.Text));
+ }
+
+ public override AIFunctionMetadata Metadata => _metadata;
+
+ private static List MapFunctionParameters(JsonSchema? jsonSchema)
+ {
+ var properties = jsonSchema?.Properties;
+ if (properties == null)
+ {
+ return new();
+ }
+ HashSet requiredProperties = new(jsonSchema!.Required ?? []);
+ return properties.Select(kvp =>
+ new AIFunctionParameterMetadata(kvp.Key)
+ {
+ Description = kvp.Value.Description,
+ ParameterType = McpTypeMapper.MapJsonToDotNetType(kvp.Value.Type, requiredProperties.Contains(kvp.Key)),
+ IsRequired = requiredProperties.Contains(kvp.Key)
+ }).ToList();
+ }
+}
diff --git a/samples/microsoft.extensions.ai/tools/ToolsConsole/McpToolExtensions.cs b/samples/microsoft.extensions.ai/tools/ToolsConsole/McpToolExtensions.cs
new file mode 100644
index 0000000..dc4d9f5
--- /dev/null
+++ b/samples/microsoft.extensions.ai/tools/ToolsConsole/McpToolExtensions.cs
@@ -0,0 +1,11 @@
+using McpDotNet.Client;
+using McpDotNet.Protocol.Types;
+using Microsoft.Extensions.AI;
+
+namespace SimpleToolsConsole;
+
+public static class McpToolExtensions
+{
+ public static AITool ToAITool(this Tool tool, IMcpClient client)
+ => new McpAIFunction(tool, client);
+}
\ No newline at end of file
diff --git a/samples/microsoft.extensions.ai/tools/ToolsConsole/McpTypeMapper.cs b/samples/microsoft.extensions.ai/tools/ToolsConsole/McpTypeMapper.cs
new file mode 100644
index 0000000..f1784d5
--- /dev/null
+++ b/samples/microsoft.extensions.ai/tools/ToolsConsole/McpTypeMapper.cs
@@ -0,0 +1,31 @@
+// Enable nullable reference types, as we need this for dynamic mapping of JSON schema to .NET types
+#nullable enable
+
+namespace SimpleToolsConsole;
+
+public static class McpTypeMapper
+{
+ public static Type MapJsonToDotNetType(string jsonType, bool required)
+ {
+ // For simplicity, we don't handle complex types in this sample, but use object instead
+ var baseType = jsonType switch
+ {
+ "string" => typeof(string),
+ "integer" => typeof(int),
+ "number" => typeof(double),
+ "boolean" => typeof(bool),
+ "array" => typeof(IEnumerable),
+ "object" => typeof(IDictionary),
+ _ => typeof(object)
+ };
+
+ // If it's a value type and not required, make it nullable
+ if (!required && baseType.IsValueType)
+ {
+ return typeof(Nullable<>).MakeGenericType(baseType);
+ }
+
+ // Reference types are already nullable when not required
+ return baseType;
+ }
+}
diff --git a/samples/microsoft.extensions.ai/tools/ToolsConsole/Program.cs b/samples/microsoft.extensions.ai/tools/ToolsConsole/Program.cs
new file mode 100644
index 0000000..333aec6
--- /dev/null
+++ b/samples/microsoft.extensions.ai/tools/ToolsConsole/Program.cs
@@ -0,0 +1,85 @@
+using McpDotNet.Client;
+using McpDotNet.Configuration;
+using Microsoft.Extensions.AI;
+using Microsoft.Extensions.Logging.Abstractions;
+using OpenAI;
+using SimpleToolsConsole;
+
+internal class Program
+{
+ private static async Task GetMcpClientAsync()
+ {
+
+ McpClientOptions options = new()
+ {
+ ClientInfo = new() { Name = "SimpleToolsConsole", Version = "1.0.0" }
+ };
+
+ var config = new McpServerConfig
+ {
+ Id = "everything",
+ Name = "Everything",
+ TransportType = "stdio",
+ TransportOptions = new Dictionary
+ {
+ ["command"] = "npx",
+ ["arguments"] = "-y @modelcontextprotocol/server-everything",
+ }
+ };
+
+ var factory = new McpClientFactory(
+ [config],
+ options,
+ NullLoggerFactory.Instance
+ );
+
+ return await factory.GetClientAsync("everything");
+ }
+
+ private static async Task Main(string[] args)
+ {
+ try
+ {
+ Console.WriteLine("Initializing MCP 'everything' server");
+ var client = await GetMcpClientAsync();
+ Console.WriteLine("MCP 'everything' server initialized");
+ Console.WriteLine("Listing tools...");
+ var tools = await client.ListToolsAsync();
+ var mappedTools = tools.Tools.Select(t => t.ToAITool(client)).ToList();
+ Console.WriteLine("Tools available:");
+ foreach (var tool in mappedTools)
+ {
+ Console.WriteLine(" " + tool);
+ }
+
+ Console.WriteLine("Starting chat with GPT-4o-mini...");
+
+ // Note: We use then Microsoft.Extensions.AI.OpenAI client here, but it could be any other MEAI client.
+ // Provide your own OPENAI_API_KEY via an environment variable, secret or file-based appsettings. Do not hardcode it.
+ IChatClient openaiClient = new OpenAIClient(Environment.GetEnvironmentVariable("OPENAI_API_KEY"))
+ .AsChatClient("gpt-4o-mini");
+
+ // Note: To use the ChatClientBuilder you need to install the Microsoft.Extensions.AI package
+ IChatClient chatClient = new ChatClientBuilder(openaiClient)
+ .UseFunctionInvocation()
+ .Build();
+
+ Console.WriteLine("Asking GPT-4o-mini to call the Echo Tool...");
+ var response = chatClient.CompleteStreamingAsync(
+ "Please call the echo tool with the string 'Hello MCP!' and give me the response as-is.",
+ new() { Tools = mappedTools });
+
+ await foreach (var update in response)
+ {
+ Console.Write(update);
+ }
+ Console.WriteLine();
+
+ Console.WriteLine("Chat with GPT-4o-mini complete");
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine("Error occurred: " + ex.Message);
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/microsoft.extensions.ai/tools/ToolsConsole/Properties/launchSettings.json b/samples/microsoft.extensions.ai/tools/ToolsConsole/Properties/launchSettings.json
new file mode 100644
index 0000000..68cd89e
--- /dev/null
+++ b/samples/microsoft.extensions.ai/tools/ToolsConsole/Properties/launchSettings.json
@@ -0,0 +1,7 @@
+{
+ "profiles": {
+ "SimpleToolsConsole": {
+ "commandName": "Project"
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/mcpdotnet/Protocol/Transport/SseTransport.cs b/src/mcpdotnet/Protocol/Transport/SseTransport.cs
index 4aabf45..2b26db1 100644
--- a/src/mcpdotnet/Protocol/Transport/SseTransport.cs
+++ b/src/mcpdotnet/Protocol/Transport/SseTransport.cs
@@ -84,6 +84,7 @@ public sealed class SseTransport : TransportBase
}
}
+ ///
public override async Task SendMessageAsync(
IJsonRpcMessage message,
CancellationToken cancellationToken = default)
diff --git a/src/mcpdotnet/Protocol/Types/Annotations.cs b/src/mcpdotnet/Protocol/Types/Annotations.cs
index 39a12ec..6622a65 100644
--- a/src/mcpdotnet/Protocol/Types/Annotations.cs
+++ b/src/mcpdotnet/Protocol/Types/Annotations.cs
@@ -1,7 +1,7 @@
-namespace McpDotNet.Protocol.Types;
-
+
using System.Text.Json.Serialization;
+namespace McpDotNet.Protocol.Types;
///
/// Represents annotations that can be attached to content.
///
diff --git a/src/mcpdotnet/Protocol/Types/CallToolResponse.cs b/src/mcpdotnet/Protocol/Types/CallToolResponse.cs
index e19daf5..5005ced 100644
--- a/src/mcpdotnet/Protocol/Types/CallToolResponse.cs
+++ b/src/mcpdotnet/Protocol/Types/CallToolResponse.cs
@@ -9,10 +9,12 @@ public class CallToolResponse
///
/// The server's response to a tools/call request from the client.
///
+ [System.Text.Json.Serialization.JsonPropertyName("content")]
public List Content { get; set; } = new();
///
/// Whether the tool call was unsuccessful. If true, the call was unsuccessful.
///
+ [System.Text.Json.Serialization.JsonPropertyName("isError")]
public bool IsError { get; set; }
}
diff --git a/src/mcpdotnet/Protocol/Types/Capabilities.cs b/src/mcpdotnet/Protocol/Types/Capabilities.cs
index 2c5273a..53a75e2 100644
--- a/src/mcpdotnet/Protocol/Types/Capabilities.cs
+++ b/src/mcpdotnet/Protocol/Types/Capabilities.cs
@@ -1,7 +1,7 @@
-namespace McpDotNet.Protocol.Types;
-
+
using System.Text.Json.Serialization;
+namespace McpDotNet.Protocol.Types;
///
/// Represents the capabilities that a client may support.
///
diff --git a/src/mcpdotnet/Protocol/Types/Content.cs b/src/mcpdotnet/Protocol/Types/Content.cs
index 8bfbe87..46ab08b 100644
--- a/src/mcpdotnet/Protocol/Types/Content.cs
+++ b/src/mcpdotnet/Protocol/Types/Content.cs
@@ -31,7 +31,7 @@ public class Content
///
/// The MIME type of the image.
///
- [JsonPropertyName("mime_type")]
+ [JsonPropertyName("mimeType")]
public string? MimeType { get; set; }
///
diff --git a/src/mcpdotnet/Protocol/Types/CreateMessageRequestParams.cs b/src/mcpdotnet/Protocol/Types/CreateMessageRequestParams.cs
index 66cd3ea..040de51 100644
--- a/src/mcpdotnet/Protocol/Types/CreateMessageRequestParams.cs
+++ b/src/mcpdotnet/Protocol/Types/CreateMessageRequestParams.cs
@@ -13,40 +13,48 @@ public class CreateMessageRequestParams
///
/// A request to include context from one or more MCP servers (including the caller), to be attached to the prompt. The client MAY ignore this request.
///
+ [System.Text.Json.Serialization.JsonPropertyName("includeContext")]
public ContextInclusion? IncludeContext { get; init; }
///
/// The maximum number of tokens to sample, as requested by the server. The client MAY choose to sample fewer tokens than requested.
///
+ [System.Text.Json.Serialization.JsonPropertyName("maxTokens")]
public int MaxTokens { get; init; }
///
/// Messages requested by the server to be included in the prompt.
///
+ [System.Text.Json.Serialization.JsonPropertyName("messages")]
public required IReadOnlyList Messages { get; init; }
///
/// Optional metadata to pass through to the LLM provider. The format of this metadata is provider-specific.
///
+ [System.Text.Json.Serialization.JsonPropertyName("metadata")]
public object? Metadata { get; init; }
///
/// The server's preferences for which model to select. The client MAY ignore these preferences.
///
+ [System.Text.Json.Serialization.JsonPropertyName("modelPreferences")]
public ModelPreferences? ModelPreferences { get; init; }
///
/// Optional stop sequences that the server wants to use for sampling.
///
+ [System.Text.Json.Serialization.JsonPropertyName("stopSequences")]
public IReadOnlyList? StopSequences { get; init; }
///
/// An optional system prompt the server wants to use for sampling. The client MAY modify or omit this prompt.
///
+ [System.Text.Json.Serialization.JsonPropertyName("systemPrompt")]
public string? SystemPrompt { get; init; }
///
/// The temperature to use for sampling, as requested by the server.
///
+ [System.Text.Json.Serialization.JsonPropertyName("temperature")]
public float? Temperature { get; init; }
}
diff --git a/src/mcpdotnet/Protocol/Types/CreateMessageResult.cs b/src/mcpdotnet/Protocol/Types/CreateMessageResult.cs
index 48352ce..ff2dd44 100644
--- a/src/mcpdotnet/Protocol/Types/CreateMessageResult.cs
+++ b/src/mcpdotnet/Protocol/Types/CreateMessageResult.cs
@@ -24,7 +24,7 @@ public class CreateMessageResult
///
/// The reason why sampling stopped, if known.
///
- [JsonPropertyName("stop_reason")]
+ [JsonPropertyName("stopReason")]
public string? StopReason { get; init; }
///
diff --git a/src/mcpdotnet/Protocol/Types/GetPromptResult.cs b/src/mcpdotnet/Protocol/Types/GetPromptResult.cs
index 0c24c9c..ec5939e 100644
--- a/src/mcpdotnet/Protocol/Types/GetPromptResult.cs
+++ b/src/mcpdotnet/Protocol/Types/GetPromptResult.cs
@@ -9,10 +9,12 @@ public class GetPromptResult
///
/// An optional description for the prompt.
///
+ [System.Text.Json.Serialization.JsonPropertyName("description")]
public string? Description { get; set; }
///
/// The prompt or prompt template that the server offers.
///
+ [System.Text.Json.Serialization.JsonPropertyName("messages")]
public List Messages { get; set; } = new();
}
diff --git a/src/mcpdotnet/Protocol/Types/JsonSchema.cs b/src/mcpdotnet/Protocol/Types/JsonSchema.cs
index d322f31..8dc868b 100644
--- a/src/mcpdotnet/Protocol/Types/JsonSchema.cs
+++ b/src/mcpdotnet/Protocol/Types/JsonSchema.cs
@@ -9,15 +9,18 @@ public class JsonSchema
///
/// The type of the schema, should be "object".
///
+ [System.Text.Json.Serialization.JsonPropertyName("type")]
public string Type { get; set; } = string.Empty;
///
/// Map of property names to property definitions.
///
+ [System.Text.Json.Serialization.JsonPropertyName("properties")]
public Dictionary? Properties { get; set; }
///
/// List of required property names.
///
+ [System.Text.Json.Serialization.JsonPropertyName("required")]
public List? Required { get; set; }
}
diff --git a/src/mcpdotnet/Protocol/Types/JsonSchemaProperty.cs b/src/mcpdotnet/Protocol/Types/JsonSchemaProperty.cs
index 35a5ede..f472ea5 100644
--- a/src/mcpdotnet/Protocol/Types/JsonSchemaProperty.cs
+++ b/src/mcpdotnet/Protocol/Types/JsonSchemaProperty.cs
@@ -9,10 +9,12 @@ public class JsonSchemaProperty
///
/// The type of the property. Should be a JSON Schema type and is required.
///
+ [System.Text.Json.Serialization.JsonPropertyName("type")]
public string Type { get; set; } = string.Empty;
///
/// A human-readable description of the property.
///
+ [System.Text.Json.Serialization.JsonPropertyName("description")]
public string? Description { get; set; }
}
diff --git a/src/mcpdotnet/Protocol/Types/ListPromptsResult.cs b/src/mcpdotnet/Protocol/Types/ListPromptsResult.cs
index aef5718..749d2e0 100644
--- a/src/mcpdotnet/Protocol/Types/ListPromptsResult.cs
+++ b/src/mcpdotnet/Protocol/Types/ListPromptsResult.cs
@@ -11,5 +11,6 @@ public class ListPromptsResult : PaginatedResult
///
/// A list of prompts or prompt templates that the server offers.
///
+ [System.Text.Json.Serialization.JsonPropertyName("prompts")]
public List Prompts { get; set; } = new();
}
\ No newline at end of file
diff --git a/src/mcpdotnet/Protocol/Types/ListResourcesResult.cs b/src/mcpdotnet/Protocol/Types/ListResourcesResult.cs
index b6e8c74..afa60a4 100644
--- a/src/mcpdotnet/Protocol/Types/ListResourcesResult.cs
+++ b/src/mcpdotnet/Protocol/Types/ListResourcesResult.cs
@@ -11,5 +11,6 @@ public class ListResourcesResult : PaginatedResult
///
/// A list of resources that the server offers.
///
+ [System.Text.Json.Serialization.JsonPropertyName("resources")]
public List Resources { get; set; } = new();
}
diff --git a/src/mcpdotnet/Protocol/Types/ListRootsRequestParams.cs b/src/mcpdotnet/Protocol/Types/ListRootsRequestParams.cs
index 7000b47..b4f6d0b 100644
--- a/src/mcpdotnet/Protocol/Types/ListRootsRequestParams.cs
+++ b/src/mcpdotnet/Protocol/Types/ListRootsRequestParams.cs
@@ -8,5 +8,6 @@ public class ListRootsRequestParams
///
/// Optional progress token for out-of-band progress notifications.
///
+ [System.Text.Json.Serialization.JsonPropertyName("progressToken")]
public string? ProgressToken { get; init; }
}
diff --git a/src/mcpdotnet/Protocol/Types/ListRootsResult.cs b/src/mcpdotnet/Protocol/Types/ListRootsResult.cs
index 1107129..da87358 100644
--- a/src/mcpdotnet/Protocol/Types/ListRootsResult.cs
+++ b/src/mcpdotnet/Protocol/Types/ListRootsResult.cs
@@ -8,10 +8,12 @@ public class ListRootsResult
///
/// Additional metadata for the result. Reserved by the protocol for future use.
///
+ [System.Text.Json.Serialization.JsonPropertyName("meta")]
public object? Meta { get; init; }
///
/// The list of root URIs provided by the client.
///
+ [System.Text.Json.Serialization.JsonPropertyName("roots")]
public required IReadOnlyList Roots { get; init; }
}
diff --git a/src/mcpdotnet/Protocol/Types/ListToolsResult.cs b/src/mcpdotnet/Protocol/Types/ListToolsResult.cs
index b89c991..15e59d0 100644
--- a/src/mcpdotnet/Protocol/Types/ListToolsResult.cs
+++ b/src/mcpdotnet/Protocol/Types/ListToolsResult.cs
@@ -11,5 +11,6 @@ public class ListToolsResult : PaginatedResult
///
/// The server's response to a tools/list request from the client.
///
+ [System.Text.Json.Serialization.JsonPropertyName("tools")]
public List Tools { get; set; } = new();
}
diff --git a/src/mcpdotnet/Protocol/Types/ModelHint.cs b/src/mcpdotnet/Protocol/Types/ModelHint.cs
index 01026af..dedc237 100644
--- a/src/mcpdotnet/Protocol/Types/ModelHint.cs
+++ b/src/mcpdotnet/Protocol/Types/ModelHint.cs
@@ -18,5 +18,6 @@ public class ModelHint
/// The client MAY also map the string to a different provider's model name or a different model family, as long as it fills a similar niche; for example:
/// - `gemini-1.5-flash` could match `claude-3-haiku-20240307`
///
+ [System.Text.Json.Serialization.JsonPropertyName("name")]
public string? Name { get; init; }
}
\ No newline at end of file
diff --git a/src/mcpdotnet/Protocol/Types/ModelPreferences.cs b/src/mcpdotnet/Protocol/Types/ModelPreferences.cs
index 6fa469f..e0b8d2b 100644
--- a/src/mcpdotnet/Protocol/Types/ModelPreferences.cs
+++ b/src/mcpdotnet/Protocol/Types/ModelPreferences.cs
@@ -18,6 +18,7 @@ public class ModelPreferences
/// How much to prioritize cost when selecting a model. A value of 0 means cost\nis not important, while a value of 1 means cost is the most important
/// factor.
///
+ [System.Text.Json.Serialization.JsonPropertyName("costPriority")]
public float? CostPriority { get; init; }
///
@@ -29,20 +30,23 @@ public class ModelPreferences
/// The client SHOULD prioritize these hints over the numeric priorities, but
/// MAY still use the priorities to select from ambiguous matches.
///
+ [System.Text.Json.Serialization.JsonPropertyName("hints")]
public IReadOnlyList? Hints { get; init; }
- ///
- /// How much to prioritize intelligence and capabilities when selecting a
- /// model. A value of 0 means intelligence is not important, while a value of 1
- /// means intelligence is the most important factor.
- ///
- public float? SpeedPriority { get; init; }
-
///
/// How much to prioritize sampling speed (latency) when selecting a model. A
/// value of 0 means speed is not important, while a value of 1 means speed is
/// the most important factor.
///
+ [System.Text.Json.Serialization.JsonPropertyName("speedPriority")]
+ public float? SpeedPriority { get; init; }
+
+ ///
+ /// How much to prioritize intelligence and capabilities when selecting a
+ /// model. A value of 0 means intelligence is not important, while a value of 1
+ /// means intelligence is the most important factor.
+ ///
+ [System.Text.Json.Serialization.JsonPropertyName("intelligencePriority")]
public float? IntelligencePriority { get; init; }
///
diff --git a/src/mcpdotnet/Protocol/Types/Prompt.cs b/src/mcpdotnet/Protocol/Types/Prompt.cs
index 268bbb5..ff67506 100644
--- a/src/mcpdotnet/Protocol/Types/Prompt.cs
+++ b/src/mcpdotnet/Protocol/Types/Prompt.cs
@@ -9,15 +9,18 @@ public class Prompt
///
/// A list of arguments to use for templating the prompt.
///
+ [System.Text.Json.Serialization.JsonPropertyName("arguments")]
public List? Arguments { get; set; }
///
/// An optional description of what this prompt provides
///
+ [System.Text.Json.Serialization.JsonPropertyName("description")]
public string? Description { get; set; }
///
/// The name of the prompt or prompt template.
///
+ [System.Text.Json.Serialization.JsonPropertyName("name")]
public string Name { get; set; } = string.Empty;
}
diff --git a/src/mcpdotnet/Protocol/Types/PromptArgument.cs b/src/mcpdotnet/Protocol/Types/PromptArgument.cs
index d8f93cc..0a8d543 100644
--- a/src/mcpdotnet/Protocol/Types/PromptArgument.cs
+++ b/src/mcpdotnet/Protocol/Types/PromptArgument.cs
@@ -9,15 +9,18 @@ public class PromptArgument
///
/// The name of the argument.
///
+ [System.Text.Json.Serialization.JsonPropertyName("name")]
public string Name { get; set; } = string.Empty;
///
/// A human-readable description of the argument.
///
+ [System.Text.Json.Serialization.JsonPropertyName("description")]
public string? Description { get; set; } = string.Empty;
///
/// Whether this argument must be provided.
///
+ [System.Text.Json.Serialization.JsonPropertyName("required")]
public bool? Required { get; set; }
}
\ No newline at end of file
diff --git a/src/mcpdotnet/Protocol/Types/PromptMessage.cs b/src/mcpdotnet/Protocol/Types/PromptMessage.cs
index 8b3aa22..7bbc054 100644
--- a/src/mcpdotnet/Protocol/Types/PromptMessage.cs
+++ b/src/mcpdotnet/Protocol/Types/PromptMessage.cs
@@ -12,10 +12,12 @@ public class PromptMessage
///
/// The content of the message. Any of TextContent, ImageContent, EmbeddedResource.
///
+ [System.Text.Json.Serialization.JsonPropertyName("content")]
public Content Content { get; set; } = new();
///
/// The role of the message ("user" or "assistant").
///
+ [System.Text.Json.Serialization.JsonPropertyName("role")]
public Role Role { get; set; } = new();
}
diff --git a/src/mcpdotnet/Protocol/Types/ReadResourceResult.cs b/src/mcpdotnet/Protocol/Types/ReadResourceResult.cs
index 4f19061..c2d35bd 100644
--- a/src/mcpdotnet/Protocol/Types/ReadResourceResult.cs
+++ b/src/mcpdotnet/Protocol/Types/ReadResourceResult.cs
@@ -9,5 +9,6 @@ public class ReadResourceResult
///
/// A list of ResourceContents that this resource contains.
///
+ [System.Text.Json.Serialization.JsonPropertyName("contents")]
public List Contents { get; set; } = new();
}
diff --git a/src/mcpdotnet/Protocol/Types/ResourceContents.cs b/src/mcpdotnet/Protocol/Types/ResourceContents.cs
index 06bace9..7943431 100644
--- a/src/mcpdotnet/Protocol/Types/ResourceContents.cs
+++ b/src/mcpdotnet/Protocol/Types/ResourceContents.cs
@@ -16,7 +16,7 @@ public class ResourceContents
///
/// The type of content.
///
- [JsonPropertyName("mime_type")]
+ [JsonPropertyName("mimeType")]
public string? MimeType { get; set; }
///
diff --git a/src/mcpdotnet/Protocol/Types/Root.cs b/src/mcpdotnet/Protocol/Types/Root.cs
index cb29b9d..ee84529 100644
--- a/src/mcpdotnet/Protocol/Types/Root.cs
+++ b/src/mcpdotnet/Protocol/Types/Root.cs
@@ -8,15 +8,18 @@ public class Root
///
/// The URI of the root.
///
+ [System.Text.Json.Serialization.JsonPropertyName("uri")]
public required string Uri { get; init; }
///
/// A human-readable name for the root.
///
+ [System.Text.Json.Serialization.JsonPropertyName("name")]
public string? Name { get; init; }
///
/// Additional metadata for the root. Reserved by the protocol for future use.
///
+ [System.Text.Json.Serialization.JsonPropertyName("meta")]
public object? Meta { get; init; }
}
\ No newline at end of file
diff --git a/src/mcpdotnet/Protocol/Types/SamplingMessage.cs b/src/mcpdotnet/Protocol/Types/SamplingMessage.cs
index 1b36e6d..49dc769 100644
--- a/src/mcpdotnet/Protocol/Types/SamplingMessage.cs
+++ b/src/mcpdotnet/Protocol/Types/SamplingMessage.cs
@@ -1,4 +1,6 @@
-namespace McpDotNet.Protocol.Types;
+using System.Text.Json.Serialization;
+
+namespace McpDotNet.Protocol.Types;
///
/// Describes a message issued to or received from an LLM API.
@@ -8,11 +10,12 @@ public class SamplingMessage
///
/// Text or image content of the message.
///
+ [JsonPropertyName("content")]
public required Content Content { get; init; }
///
/// The role of the message ("user" or "assistant").
///
-
+ [JsonPropertyName("role")]
public required Role Role { get; init; } // "user" or "assistant"
}
diff --git a/src/mcpdotnet/Protocol/Types/Tool.cs b/src/mcpdotnet/Protocol/Types/Tool.cs
index 153cf17..42ad534 100644
--- a/src/mcpdotnet/Protocol/Types/Tool.cs
+++ b/src/mcpdotnet/Protocol/Types/Tool.cs
@@ -9,15 +9,18 @@ public class Tool
///
/// he name of the tool.
///
+ [System.Text.Json.Serialization.JsonPropertyName("name")]
public string Name { get; set; } = string.Empty;
///
/// A human-readable description of the tool.
///
+ [System.Text.Json.Serialization.JsonPropertyName("description")]
public string? Description { get; set; }
///
/// A JSON Schema object defining the expected parameters for the tool.
///
+ [System.Text.Json.Serialization.JsonPropertyName("inputSchema")]
public JsonSchema? InputSchema { get; set; }
}
diff --git a/src/mcpdotnet/mcpdotnet.csproj b/src/mcpdotnet/mcpdotnet.csproj
index 1007582..aa119d9 100644
--- a/src/mcpdotnet/mcpdotnet.csproj
+++ b/src/mcpdotnet/mcpdotnet.csproj
@@ -9,7 +9,7 @@
mcpdotnet
- 0.6.0.1
+ 0.7.0.1
PederHP
.NET client library for the Model Context Protocol (MCP)
https://github.com/PederHP/mcpdotnet
diff --git a/src/mcpdotnet.Tests/GlobalUsings.cs b/tests/mcpdotnet.Tests/GlobalUsings.cs
similarity index 100%
rename from src/mcpdotnet.Tests/GlobalUsings.cs
rename to tests/mcpdotnet.Tests/GlobalUsings.cs
diff --git a/src/mcpdotnet.Tests/IntegrationTestFixture.cs b/tests/mcpdotnet.Tests/IntegrationTestFixture.cs
similarity index 100%
rename from src/mcpdotnet.Tests/IntegrationTestFixture.cs
rename to tests/mcpdotnet.Tests/IntegrationTestFixture.cs
diff --git a/src/mcpdotnet.Tests/IntegrationTests.cs b/tests/mcpdotnet.Tests/IntegrationTests.cs
similarity index 100%
rename from src/mcpdotnet.Tests/IntegrationTests.cs
rename to tests/mcpdotnet.Tests/IntegrationTests.cs
diff --git a/src/mcpdotnet.Tests/McpClientFactoryTests.cs b/tests/mcpdotnet.Tests/McpClientFactoryTests.cs
similarity index 100%
rename from src/mcpdotnet.Tests/McpClientFactoryTests.cs
rename to tests/mcpdotnet.Tests/McpClientFactoryTests.cs
diff --git a/src/mcpdotnet.Tests/SseIntegrationTests.cs b/tests/mcpdotnet.Tests/SseIntegrationTests.cs
similarity index 100%
rename from src/mcpdotnet.Tests/SseIntegrationTests.cs
rename to tests/mcpdotnet.Tests/SseIntegrationTests.cs
diff --git a/src/mcpdotnet.Tests/SseTransportTests.cs b/tests/mcpdotnet.Tests/SseTransportTests.cs
similarity index 100%
rename from src/mcpdotnet.Tests/SseTransportTests.cs
rename to tests/mcpdotnet.Tests/SseTransportTests.cs
diff --git a/src/mcpdotnet.Tests/Utils/TestSseServer.cs b/tests/mcpdotnet.Tests/Utils/TestSseServer.cs
similarity index 100%
rename from src/mcpdotnet.Tests/Utils/TestSseServer.cs
rename to tests/mcpdotnet.Tests/Utils/TestSseServer.cs
diff --git a/src/mcpdotnet.Tests/mcpdotnet.Tests.csproj b/tests/mcpdotnet.Tests/mcpdotnet.Tests.csproj
similarity index 94%
rename from src/mcpdotnet.Tests/mcpdotnet.Tests.csproj
rename to tests/mcpdotnet.Tests/mcpdotnet.Tests.csproj
index 51dc6ef..0aa0385 100644
--- a/src/mcpdotnet.Tests/mcpdotnet.Tests.csproj
+++ b/tests/mcpdotnet.Tests/mcpdotnet.Tests.csproj
@@ -26,7 +26,7 @@
-
+