前言

网上使用Python创建一个MCP客户端的教程已经有很多了,而使用C#创建一个MCP客户端的教程还很少。

为什么要创建一个MCP客户端呢?

创建了一个MCP客户端之后,你就可以使用别人写好的一些MCP服务了。

效果展示

为了方便大家复现,我没有使用WPF/Avalonia之类的做界面。只是一个简单的控制台程序,可以很容易看懂。

接入了fetch_mcp可以实现获取网页内容了,使用的模型只要具有tool use能力的应该都可以。

我使用的是Qwen/Qwen2.5-72B-Instruct。

开始实践

主要使用的包如下所示:

首先获取MCP服务器:

 private static async Task<IMcpClient> GetMcpClientAsync()
{
DotEnv.Load();
var envVars = DotEnv.Read();
McpClientOptions options = new()
{
ClientInfo = new() { Name = "SimpleToolsConsole", Version = "1.0.0" }
}; var config = new McpServerConfig
{
Id = "test",
Name = "Test",
TransportType = TransportTypes.StdIo,
TransportOptions = new Dictionary<string, string>
{
["command"] = envVars["MCPCommand"],
["arguments"] = envVars["MCPArguments"],
}
}; var factory = new McpClientFactory(
new[] { config },
options,
NullLoggerFactory.Instance
); return await factory.GetClientAsync("test");
}

写死的话就是这样写:

 private static async Task<IMcpClient> GetMcpClientAsync()
{
DotEnv.Load();
var envVars = DotEnv.Read();
McpClientOptions options = new()
{
ClientInfo = new() { Name = "SimpleToolsConsole", Version = "1.0.0" }
}; var config = new McpServerConfig
{
Id = "test",
Name = "Test",
TransportType = TransportTypes.StdIo,
TransportOptions = new Dictionary<string, string>
{
["command"] = node,
["arguments"] = D:/Learning/AI-related/fetch-mcp/dist/index.js,
}
}; var factory = new McpClientFactory(
new[] { config },
options,
NullLoggerFactory.Instance
); return await factory.GetClientAsync("test");
}

重点在:

 TransportOptions = new Dictionary<string, string>
{
["command"] = node,
["arguments"] = D:/Learning/AI-related/fetch-mcp/dist/index.js,
}

用于连接你想连接的MCP服务器。

如果能正确显示你连接mcp服务器提供的工具,说明连接成功。

  var listToolsResult = await client.ListToolsAsync();
var mappedTools = listToolsResult.Tools.Select(t => t.ToAITool(client)).ToList();
Console.WriteLine("Tools available:");
foreach (var tool in mappedTools)
{
Console.WriteLine(" " + tool);
}

开启一个聊天循环:

    Console.WriteLine("\nMCP Client Started!");
Console.WriteLine("Type your queries or 'quit' to exit."); ChatDemo chatDemo = new ChatDemo(); while (true)
{
try
{
Console.ForegroundColor = ConsoleColor.DarkYellow;
Console.Write("\nQuery: ");
string query = Console.ReadLine()?.Trim() ?? string.Empty; if (query.ToLower() == "quit")
break;
if (query.ToLower() == "clear")
{
Console.Clear();
chatDemo.Messages.Clear();
}
else
{
string response = await chatDemo.ProcessQueryAsync(query, mappedTools);
Console.ForegroundColor = ConsoleColor.DarkYellow;
Console.WriteLine($"AI回答:{response}");
Console.ForegroundColor = ConsoleColor.White;
}
}
catch (Exception ex)
{
Console.WriteLine($"\nError: {ex.Message}");
}
}
}

处理每次询问:

 public async Task<string> ProcessQueryAsync(string query, List<AITool> tools)
{
if(Messages.Count == 0)
{
Messages =
[
// Add a system message
new(ChatRole.System, "You are a helpful assistant, helping us test MCP server functionality."),
];
} // Add a user message
Messages.Add(new(ChatRole.User, query)); var response = await ChatClient.GetResponseAsync(
Messages,
new() { Tools = tools });
Messages.AddMessages(response);
var toolUseMessage = response.Messages.Where(m => m.Role == ChatRole.Tool); if (toolUseMessage.Count() > 0)
{
var functionMessage = response.Messages.Where(m => m.Text == "").First();
var functionCall = (FunctionCallContent)functionMessage.Contents[1];
Console.ForegroundColor = ConsoleColor.Green;
string arguments = "";
foreach (var arg in functionCall.Arguments)
{
arguments += $"{arg.Key}:{arg.Value};";
}
Console.WriteLine($"调用函数名:{functionCall.Name};参数信息:{arguments}");
foreach (var message in toolUseMessage)
{
var functionResultContent = (FunctionResultContent)message.Contents[0];
Console.WriteLine($"调用工具结果:{functionResultContent.Result}");
} Console.ForegroundColor = ConsoleColor.White;
}
else
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("本次没有调用工具");
Console.ForegroundColor = ConsoleColor.White;
} return response.Text;
}

代码已经放到GitHub,地址:https://github.com/Ming-jiayou/mcp_demo。

将.env-example修改为.env应该就可以运行,如果报错,设置成嵌入的资源即可。

.env配置示例:

API_KEY=sk-xxx
BaseURL=https://api.siliconflow.cn/v1
ModelID=Qwen/Qwen2.5-72B-Instruct
MCPCommand=node
MCPArguments=D:/Learning/AI-related/fetch-mcp/dist/index.js

最后

对C#使用MCP感兴趣的朋友可以关注这个项目:https://github.com/PederHP/mcpdotnet。

有问题欢迎一起交流学习。

使用C#创建一个MCP客户端的更多相关文章

  1. [Swift通天遁地]四、网络和线程-(13)创建一个Socket客户端

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

  2. cxf的使用及安全校验-02创建简单的客户端接口

    上一篇文章中,我们已经讲了如果简单的创建一个webservice接口 http://www.cnblogs.com/snowstar123/p/3395568.html 现在我们创建一个简单客户端接口 ...

  3. [Swift通天遁地]四、网络和线程-(14)创建一个Socket服务端

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

  4. kubenetes创建一个pod应用

    Pod是可以创建和管理Kubernetes计算的最小可部署单元.一个Pod代表着集群中运行的一个进程.每个pod都有一个唯一的ip. 一个pod类似一个豌豆荚,包含一个或多个容器(通常是docker) ...

  5. 搭建QQ聊天通信的程序:(1)基于 networkcomms.net 创建一个WPF聊天客户端服务器应用程序 (1)

    搭建QQ聊天通信的程序:(1)基于 networkcomms.net 创建一个WPF聊天客户端服务器应用程序 原文地址(英文):http://www.networkcomms.net/creating ...

  6. 一个关于如何创建类似于QQ客户端聊天窗口的模拟小项目

    对于不久之前学习到的一个有关的类似于QQ聊天框的模拟项目,对其中涉及到的知识在这里做一下总结. 首先,你要先创建一个客户端聊天框(取名为:ChatClient,它是你创建的类),这个类继承了Frame ...

  7. 管理员技术(四): 配置NTP网络时间客户端、 创建一个备份包、 配置用户和组账号、配置一个cron任务

    一. 配置NTP网络时间客户端 目标: 本例要求配置虚拟机 server0,能够自动校对系统时间.相关信息如下: 1> NTP服务器位于 classroom.example.com        ...

  8. 在一个空ASP.NET Web项目上创建一个ASP.NET Web API 2.0应用

    由于ASP.NET Web API具有与ASP.NET MVC类似的编程方式,再加上目前市面上专门介绍ASP.NET Web API 的书籍少之又少(我们看到的相关内容往往是某本介绍ASP.NET M ...

  9. ASP.NET Core管道深度剖析(2):创建一个“迷你版”的管道来模拟真实管道请求处理流程

    从<ASP.NET Core管道深度剖析(1):采用管道处理HTTP请求>我们知道ASP.NET Core请求处理管道由一个服务器和一组有序的中间件组成,所以从总体设计来讲是非常简单的,但 ...

  10. Step by Step 创建一个 Web Service

    原创地址:http://www.cnblogs.com/jfzhu/p/4022139.html 转载请注明出处 (一)创建Web Service 创建第一个项目,类型选择ASP.NET Empty ...

随机推荐

  1. Qt音视频开发36-超时检测和自动重连的设计

    一.前言 如果网络环境正常设备正常,视频监控系统一般都是按照正常运行下去,不会出现什么问题,但是实际情况会很不同,奇奇怪怪七七八八的问题都会出现,就比如网络出了问题都有很多情况(交换机故障.网线故障. ...

  2. Qt数据库应用23-个人信息报表

    一.前言 自从上次做完的图文报表,又新来了个需求需要实现个人信息报表,类似个人简历一样的格式,数据从数据库中取出来,然后一个人的信息就打印一张,传入查询的多个人员信息,自动分页打印个人信息报表,报表可 ...

  3. CSP-J2/S2 2024 游记

    前情提要:CSP-J/S 2023 写这篇文章的时候,心情比较复杂. 哎,结局还算圆满. 初赛 之前那个写的不好再写一遍() 两个都在 WFLS,也就是本校考 qaq. J 在大礼堂考,没啥好说的,太 ...

  4. 提供Chrome浏览器插件网站

    提供Chrome浏览器插件网站: 1.收藏猫插件 2.极简插件

  5. 跟着源码学IM(八):万字长文,手把手教你用Netty打造IM聊天

    本文作者芋艿,原题"使用 Netty 实现 IM 聊天贼简单",本底价有修订和改动. 一.本文引言 上篇<跟着源码学IM(七):手把手教你用WebSocket打造Web端IM ...

  6. Linux 检查磁盘空间命令合集

    1. DF df 是检查Linux安装程序上可用分区空间的最常用的命令之一.可以使用"df -TH"以直观易读的格式打印分区类型和分区大小.此命令将显示每个部分的总可用空间.已用空 ...

  7. Vanity Intermediate 统配符提权

    nmap扫描 ┌──(root㉿kali)-[~] └─# nmap -p- -A 192.168.167.234 Starting Nmap 7.94SVN ( https://nmap.org ) ...

  8. 微信小程序音频播放

    微信小程序音频播放 // 开启播放音频 startAudio(){ const innerAudioContext = uni.createInnerAudioContext();//创建并返回内部 ...

  9. 设置npm、yarn和pnpm的国内镜像地址和yarn命令相关问题

    1.npm 全局设置: 输入如下命令查看镜像地址: npm config get registry 输入如下命令设置镜像地址为淘宝: // 推荐地址 npm config set registry h ...

  10. useradd usermod userdel passwd groupadd groupmod groupdel等命令详解

    linux命令参数记忆有些模糊了,记录下.学而时习之,不亦说乎? 1.useradd命令用来建立用户帐号和创建用户的起始目录,使用权限是终极用户.创建新用户useradd,默认的用户家目录会被存放在/ ...