diff --git a/ModelContextProtocol.sln b/ModelContextProtocol.sln
index 4b9250c..c0d470e 100644
--- a/ModelContextProtocol.sln
+++ b/ModelContextProtocol.sln
@@ -7,10 +7,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModelContextProtocol", "src
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModelContextProtocol.Tests", "tests\ModelContextProtocol.Tests\ModelContextProtocol.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
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModelContextProtocol.TestServer", "tests\ModelContextProtocol.TestServer\ModelContextProtocol.TestServer.csproj", "{7C229573-A085-4ECC-8131-958CDA2BE731}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestServerWithHosting", "samples\TestServerWithHosting\TestServerWithHosting.csproj", "{6499876E-2F76-44A8-B6EB-5B889C6E9B7F}"
@@ -47,6 +43,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{
.github\workflows\ci.yml = .github\workflows\ci.yml
EndProjectSection
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChatWithTools", "samples\ChatWithTools\ChatWithTools.csproj", "{0C6D0512-D26D-63D3-5019-C5F7A657B28C}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -61,14 +59,6 @@ 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
{7C229573-A085-4ECC-8131-958CDA2BE731}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7C229573-A085-4ECC-8131-958CDA2BE731}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7C229573-A085-4ECC-8131-958CDA2BE731}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -85,6 +75,10 @@ Global
{B6F42305-423F-56FF-090F-B7263547F924}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B6F42305-423F-56FF-090F-B7263547F924}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B6F42305-423F-56FF-090F-B7263547F924}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0C6D0512-D26D-63D3-5019-C5F7A657B28C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0C6D0512-D26D-63D3-5019-C5F7A657B28C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0C6D0512-D26D-63D3-5019-C5F7A657B28C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0C6D0512-D26D-63D3-5019-C5F7A657B28C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -92,13 +86,12 @@ Global
GlobalSection(NestedProjects) = preSolution
{12260CD2-AFFC-4B2E-8898-F442CAA1FA0F} = {A2F1F52A-9107-4BF8-8C3F-2F6670E7D0AD}
{FF41F619-833D-4FA2-8C53-04D0A1D5AA61} = {2A77AF5C-138A-4EBB-9A13-9205DCD67928}
- {76E295FA-9E85-7B99-332A-2CDBFCD5860A} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
- {CA0BB450-1903-2F92-A68D-1285976551D6} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
{7C229573-A085-4ECC-8131-958CDA2BE731} = {2A77AF5C-138A-4EBB-9A13-9205DCD67928}
{6499876E-2F76-44A8-B6EB-5B889C6E9B7F} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
{79B94BF9-E557-33DB-3F19-B2C7D9BF8C56} = {2A77AF5C-138A-4EBB-9A13-9205DCD67928}
{B6F42305-423F-56FF-090F-B7263547F924} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
{20AACB9B-307D-419C-BCC6-1C639C402295} = {1288ADA5-1BF1-4A7F-A33E-9EA29097AA40}
+ {0C6D0512-D26D-63D3-5019-C5F7A657B28C} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {384A3888-751F-4D75-9AE5-587330582D89}
diff --git a/samples/microsoft.extensions.ai/tools/ToolsConsole/MEAIToolsConsole.csproj b/samples/ChatWithTools/ChatWithTools.csproj
similarity index 77%
rename from samples/microsoft.extensions.ai/tools/ToolsConsole/MEAIToolsConsole.csproj
rename to samples/ChatWithTools/ChatWithTools.csproj
index d04a44e..e3ae1b7 100644
--- a/samples/microsoft.extensions.ai/tools/ToolsConsole/MEAIToolsConsole.csproj
+++ b/samples/ChatWithTools/ChatWithTools.csproj
@@ -10,11 +10,12 @@
+
-
+
diff --git a/samples/ChatWithTools/Program.cs b/samples/ChatWithTools/Program.cs
new file mode 100644
index 0000000..feeb06a
--- /dev/null
+++ b/samples/ChatWithTools/Program.cs
@@ -0,0 +1,52 @@
+using ModelContextProtocol.Client;
+using ModelContextProtocol.Protocol.Transport;
+using Microsoft.Extensions.AI;
+using OpenAI;
+
+// Connect to an MCP server
+Console.WriteLine("Connecting client to MCP 'everything' server");
+var mcpClient = await McpClientFactory.CreateAsync(
+ new()
+ {
+ Id = "everything",
+ Name = "Everything",
+ TransportType = TransportTypes.StdIo,
+ TransportOptions = new()
+ {
+ ["command"] = "npx", ["arguments"] = "-y @modelcontextprotocol/server-everything",
+ }
+ },
+ new() { ClientInfo = new() { Name = "ChatClient", Version = "1.0.0" } });
+
+// Get all available tools
+Console.WriteLine("Tools available:");
+var tools = await mcpClient.GetAIFunctionsAsync();
+foreach (var tool in tools)
+{
+ Console.WriteLine($" {tool}");
+}
+Console.WriteLine();
+
+// Create an IChatClient. (This shows using OpenAIClient, but it could be any other IChatClient implementation.)
+// Provide your own OPENAI_API_KEY via an environment variable.
+using IChatClient chatClient =
+ new OpenAIClient(Environment.GetEnvironmentVariable("OPENAI_API_KEY")).AsChatClient("gpt-4o-mini")
+ .AsBuilder().UseFunctionInvocation().Build();
+
+// Have a conversation, making all tools available to the LLM.
+List messages = [];
+while (true)
+{
+ Console.Write("Q: ");
+ messages.Add(new(ChatRole.User, Console.ReadLine()));
+
+ List updates = [];
+ await foreach (var update in chatClient.GetStreamingResponseAsync(messages, new() { Tools = [.. tools] }))
+ {
+ Console.Write(update);
+ updates.Add(update);
+ }
+ Console.WriteLine();
+
+ messages.AddMessages(updates);
+}
\ No newline at end of file
diff --git a/samples/README.md b/samples/README.md
deleted file mode 100644
index 4715337..0000000
--- a/samples/README.md
+++ /dev/null
@@ -1,41 +0,0 @@
-# Samples
-
-This directory contains example projects demonstrating how to use ModelContextProtocol 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 ModelContextProtocol. 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 ModelContextProtocol 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 ModelContextProtocol usage, you can also refer to the integration tests in the `tests/ModelContextProtocol.IntegrationTests` project.
\ No newline at end of file
diff --git a/samples/anthropic/tools/ToolsConsole/AnthropicToolsConsole.csproj b/samples/anthropic/tools/ToolsConsole/AnthropicToolsConsole.csproj
deleted file mode 100644
index cd61195..0000000
--- a/samples/anthropic/tools/ToolsConsole/AnthropicToolsConsole.csproj
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
- Exe
- net8.0
- enable
- enable
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/samples/anthropic/tools/ToolsConsole/McpToolExtensions.cs b/samples/anthropic/tools/ToolsConsole/McpToolExtensions.cs
deleted file mode 100644
index 6b534f9..0000000
--- a/samples/anthropic/tools/ToolsConsole/McpToolExtensions.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-using Anthropic.SDK.Common;
-using System.Text.Json;
-using System.Text.Json.Nodes;
-
-namespace ModelContextProtocol;
-
-public static class McpToolExtensions
-{
- public static IList ToAnthropicTools(this IEnumerable tools)
- {
- if (tools is null)
- {
- throw new ArgumentNullException(nameof(tools));
- }
-
- List result = [];
- foreach (var tool in tools)
- {
- var function = new Function(tool.Name, tool.Description, JsonSerializer.SerializeToNode(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