Skip to content

Commit 4597bbd

Browse files
authored
Integrate Microsoft.Extensions.AI as a foundational building block (#94)
* Integrate Microsoft.Extensions.AI as a foundational building block As with logging abstractions coming from M.E.Logging and DI abstractions coming from M.E.DependencyInjection, M.E.AI provides the relevant AI abstractions. - Adds AsAIFunction and GetAIFunctionsAsync methods for getting functions for tools via a client. - Uses AIFunctionFactory to implement McpServerBuilderExtensions.WithTools. - Adds a RequestSamplingAsync overload that accepts ChatMessages/Options. - Adds an AsSamplingChatClient method that provides an IChatClient usable on the server to request sampling of the client. - Adds a CreateSamplingHandler method to enable an IChatClient to be easily used to satisfy sampling requests on the client. - Deprecate McpDotNet.Extensions.AI. * Address PR feedback
1 parent a0afc28 commit 4597bbd

27 files changed

+801
-927
lines changed

README.MD

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,21 @@ Additional examples and documentation will be added as in the near future.
9999

100100
Remember you can connect to any MCP server, not just ones created using mcpdotnet. The protocol is designed to be server-agnostic, so you can use this library to connect to any compliant server.
101101

102+
Tools can be exposed easily as `AIFunction` instances so that they are immediately usable with `IChatClient`s.
103+
```csharp
104+
// Get available functions.
105+
IList<AIFunction> tools = await client.GetAIFunctionsAsync();
106+
107+
// Call the chat client using the tools.
108+
IChatClient chatClient = ...;
109+
var response = await chatClient.GetResponseAsync(
110+
"your prompt here",
111+
new()
112+
{
113+
Tools = [.. tools],
114+
});
115+
```
116+
102117
## Getting Started (Server)
103118

104119
Here is an example of how to create an MCP server and register all tools from the current application.

mcpdotnet.sln

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mcpdotnet.TestServer", "tes
1515
EndProject
1616
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "McpDotNet.Extensions.AI", "src\McpDotNet.Extensions.AI\McpDotNet.Extensions.AI.csproj", "{B3E019B8-3459-4D52-864E-703DDA2C02AD}"
1717
EndProject
18-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "McpDotNet.Extensions.AI.Tests", "tests\McpDotNet.Extensions.AI.Tests\McpDotNet.Extensions.AI.Tests.csproj", "{67BEF596-AD39-4BDD-B505-31DE7FF0C8D2}"
19-
EndProject
2018
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestServerWithHosting", "samples\TestServerWithHosting\TestServerWithHosting.csproj", "{6499876E-2F76-44A8-B6EB-5B889C6E9B7F}"
2119
EndProject
2220
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}"
@@ -53,10 +51,6 @@ Global
5351
{B3E019B8-3459-4D52-864E-703DDA2C02AD}.Debug|Any CPU.Build.0 = Debug|Any CPU
5452
{B3E019B8-3459-4D52-864E-703DDA2C02AD}.Release|Any CPU.ActiveCfg = Release|Any CPU
5553
{B3E019B8-3459-4D52-864E-703DDA2C02AD}.Release|Any CPU.Build.0 = Release|Any CPU
56-
{67BEF596-AD39-4BDD-B505-31DE7FF0C8D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
57-
{67BEF596-AD39-4BDD-B505-31DE7FF0C8D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
58-
{67BEF596-AD39-4BDD-B505-31DE7FF0C8D2}.Release|Any CPU.ActiveCfg = Release|Any CPU
59-
{67BEF596-AD39-4BDD-B505-31DE7FF0C8D2}.Release|Any CPU.Build.0 = Release|Any CPU
6054
{6499876E-2F76-44A8-B6EB-5B889C6E9B7F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
6155
{6499876E-2F76-44A8-B6EB-5B889C6E9B7F}.Debug|Any CPU.Build.0 = Debug|Any CPU
6256
{6499876E-2F76-44A8-B6EB-5B889C6E9B7F}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -70,7 +64,6 @@ Global
7064
{76E295FA-9E85-7B99-332A-2CDBFCD5860A} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
7165
{CA0BB450-1903-2F92-A68D-1285976551D6} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
7266
{7C229573-A085-4ECC-8131-958CDA2BE731} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
73-
{67BEF596-AD39-4BDD-B505-31DE7FF0C8D2} = {2A77AF5C-138A-4EBB-9A13-9205DCD67928}
7467
{6499876E-2F76-44A8-B6EB-5B889C6E9B7F} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
7568
EndGlobalSection
7669
GlobalSection(ExtensibilityGlobals) = postSolution
Lines changed: 61 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,92 +1,79 @@
11
using McpDotNet.Client;
22
using McpDotNet.Configuration;
3-
using McpDotNet.Extensions.AI;
43
using McpDotNet.Protocol.Transport;
54
using Microsoft.Extensions.AI;
65
using OpenAI;
76

8-
internal class Program
7+
try
98
{
10-
private static async Task<IMcpClient> GetMcpClientAsync()
11-
{
12-
McpClientOptions clientOptions = new()
13-
{
14-
ClientInfo = new() { Name = "SimpleToolsConsole", Version = "1.0.0" }
15-
};
16-
17-
McpServerConfig serverConfig = new()
18-
{
19-
Id = "everything",
20-
Name = "Everything",
21-
TransportType = TransportTypes.StdIo,
22-
TransportOptions = new Dictionary<string, string>
23-
{
24-
["command"] = "npx",
25-
["arguments"] = "-y @modelcontextprotocol/server-everything",
26-
}
27-
};
28-
29-
return await McpClientFactory.CreateAsync(serverConfig, clientOptions);
30-
}
9+
Console.WriteLine("Initializing MCP 'everything' server");
10+
await using var client = await GetMcpClientAsync();
3111

32-
private static async Task Main(string[] args)
12+
Console.WriteLine("MCP 'everything' server initialized");
13+
Console.WriteLine("Listing tools...");
14+
var mappedTools = await client.GetAIFunctionsAsync();
15+
16+
Console.WriteLine("Tools available:");
17+
foreach (var tool in mappedTools)
3318
{
34-
try
35-
{
36-
Console.WriteLine("Initializing MCP 'everything' server");
37-
await using var client = await GetMcpClientAsync();
38-
Console.WriteLine("MCP 'everything' server initialized");
39-
Console.WriteLine("Listing tools...");
40-
var mappedTools = await client.ListToolsAsync().Select(t => t.ToAITool(client)).ToListAsync();
41-
Console.WriteLine("Tools available:");
42-
foreach (var tool in mappedTools)
43-
{
44-
Console.WriteLine(" " + tool);
45-
}
46-
47-
Console.WriteLine("Starting chat with GPT-4o-mini...");
19+
Console.WriteLine($" {tool}");
20+
}
4821

49-
// Note: We use then Microsoft.Extensions.AI.OpenAI client here, but it could be any other MEAI client.
50-
// Provide your own OPENAI_API_KEY via an environment variable, secret or file-based appsettings. Do not hardcode it.
51-
IChatClient openaiClient = new OpenAIClient(Environment.GetEnvironmentVariable("OPENAI_API_KEY"))
52-
.AsChatClient("gpt-4o-mini");
22+
Console.WriteLine("Starting chat with GPT-4o-mini...");
5323

54-
// Note: To use the ChatClientBuilder you need to install the Microsoft.Extensions.AI package
55-
IChatClient chatClient = new ChatClientBuilder(openaiClient)
56-
.UseFunctionInvocation()
57-
.Build();
24+
// Note: We use then Microsoft.Extensions.AI.OpenAI client here, but it could be any other MEAI client.
25+
// Provide your own OPENAI_API_KEY via an environment variable, secret or file-based appsettings. Do not hardcode it.
26+
IChatClient chatClient = new OpenAIClient(Environment.GetEnvironmentVariable("OPENAI_API_KEY"))
27+
.AsChatClient("gpt-4o-mini")
28+
.AsBuilder()
29+
.UseFunctionInvocation()
30+
.Build();
5831

59-
// Create message list
60-
IList<Microsoft.Extensions.AI.ChatMessage> messages =
61-
[
62-
// Add a system message
63-
new(ChatRole.System, "You are a helpful assistant, helping us test MCP server functionality."),
64-
];
65-
// If MCP server provides instructions, add them as an additional system message (you could also add it as a content part)
66-
if (!string.IsNullOrEmpty(client.ServerInstructions))
67-
{
68-
messages.Add(new(ChatRole.System, client.ServerInstructions));
69-
}
70-
// Add a user message
71-
messages.Add(new(ChatRole.User, "Please call the echo tool with the string 'Hello MCP!' and give me the response as-is."));
32+
// Create message list
33+
IList<Microsoft.Extensions.AI.ChatMessage> messages =
34+
[
35+
// Add a system message
36+
new(ChatRole.System, "You are a helpful assistant, helping us test MCP server functionality."),
37+
];
38+
// If MCP server provides instructions, add them as an additional system message (you could also add it as a content part)
39+
if (!string.IsNullOrEmpty(client.ServerInstructions))
40+
{
41+
messages.Add(new(ChatRole.System, client.ServerInstructions));
42+
}
43+
// Add a user message
44+
messages.Add(new(ChatRole.User, "Please call the echo tool with the string 'Hello MCP!' and give me the response as-is."));
7245

73-
// Call the chat client
74-
Console.WriteLine("Asking GPT-4o-mini to call the Echo Tool...");
75-
var response = chatClient.GetStreamingResponseAsync(
76-
messages,
77-
new() { Tools = mappedTools });
46+
// Call the chat client
47+
Console.WriteLine("Asking GPT-4o-mini to call the Echo Tool...");
48+
await foreach (var update in chatClient.GetStreamingResponseAsync(messages, new() { Tools = [.. mappedTools] }))
49+
{
50+
Console.Write(update);
51+
}
52+
Console.WriteLine();
53+
}
54+
catch (Exception ex)
55+
{
56+
Console.WriteLine($"Error occurred: {ex.Message}");
57+
}
7858

79-
await foreach (var update in response)
80-
{
81-
Console.Write(update);
82-
}
83-
Console.WriteLine();
59+
async Task<IMcpClient> GetMcpClientAsync()
60+
{
61+
McpClientOptions clientOptions = new()
62+
{
63+
ClientInfo = new() { Name = "SimpleToolsConsole", Version = "1.0.0" }
64+
};
8465

85-
Console.WriteLine("Chat with GPT-4o-mini complete");
86-
}
87-
catch (Exception ex)
66+
McpServerConfig serverConfig = new()
67+
{
68+
Id = "everything",
69+
Name = "Everything",
70+
TransportType = TransportTypes.StdIo,
71+
TransportOptions = new Dictionary<string, string>
8872
{
89-
Console.WriteLine("Error occurred: " + ex.Message);
73+
["command"] = "npx",
74+
["arguments"] = "-y @modelcontextprotocol/server-everything",
9075
}
91-
}
76+
};
77+
78+
return await McpClientFactory.CreateAsync(serverConfig, clientOptions);
9279
}

src/McpDotNet.Extensions.AI/AIFunctionUtilities.cs

Lines changed: 0 additions & 26 deletions
This file was deleted.

src/McpDotNet.Extensions.AI/McpAIFunction.cs

Lines changed: 0 additions & 60 deletions
This file was deleted.

src/McpDotNet.Extensions.AI/McpDotNet.Extensions.AI.csproj

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,6 @@
3333
<None Include="README.md" Pack="true" PackagePath="/" />
3434
</ItemGroup>
3535

36-
<ItemGroup>
37-
<InternalsVisibleTo Include="McpDotNet.Extensions.AI.Tests" />
38-
</ItemGroup>
39-
40-
<ItemGroup>
41-
<ProjectReference Include="..\mcpdotnet\mcpdotnet.csproj" />
42-
43-
<PackageReference Include="Microsoft.Extensions.AI.Abstractions" Version="9.3.0-preview.1.25161.3" />
44-
<PackageReference Include="Microsoft.Extensions.AI" Version="9.3.0-preview.1.25161.3" />
45-
</ItemGroup>
46-
4736
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
4837
<PackageReference Include="System.Text.Json" Version="9.0.3" />
4938
</ItemGroup>

0 commit comments

Comments
 (0)