当前位置: 首页 > news >正文

(一) Dotnet使用MCP的Csharp SDK

image.png
微软官方定义如下:

模型上下文协议(MCP)是一种开放协议,旨在标准化 AI 应用与外部工具和数据源之间的集成。 通过使用 MCP,开发人员可以增强 AI 模型的功能,使他们能够生成更准确、更相关和上下文感知的响应。

整体设计如下(来自微软官方):
Pasted image 20251015012435.png

Server

项目引入Microsoft.Extensions.HostingModelContextProtocol
前者用于构建主机环境,后者用于提供MCP SDK 相关函数。

<ItemGroup><PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.0-rc.1.25451.107" /><PackageReference Include="ModelContextProtocol" Version="0.4.0-preview.2" />
</ItemGroup>

stdio

通过命令行实现服务的创建,适用于同主机范围内,工具的直接调用。
引入服务MCP 服务并指定为stdio方式。

internal class Program
{static async Task Main(string[] args){// 创建主机构建器实例var builder = Host.CreateApplicationBuilder(args);// 引入控制台日志输出builder.Logging.AddConsole(consoleLogOptions =>{// 配置所有日志输出到stderrconsoleLogOptions.LogToStandardErrorThreshold = LogLevel.Trace;});// 添加MCPServer服务builder.Services.AddMcpServer() // 注册Mcp服务.WithStdioServerTransport() // 添加stdio传输配置用于接收控制台输入输出流.WithToolsFromAssembly(); // 配置Mcp工具通过当前程序集获取// 运行宿主应用await builder.Build().RunAsync();}
}

httpsse

需要注意的是对于httpsse 实际都是使用的AspNetCore,对应需要引入NugetModelContextProtocol.AspNetCore

<ItemGroup><PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.0-rc.1.25451.107" /><PackageReference Include="ModelContextProtocol" Version="0.4.0-preview.2" /><PackageReference Include="ModelContextProtocol.AspNetCore" Version="0.4.0-preview.2" />
</ItemGroup>

对应Host的构建器转换为WebApplication.CreateBuilder(args),而不是Host.CreateApplicationBuilder(args)

static async Task Main(string[] args)
{// 创建主机构建器实例var builder = WebApplication.CreateBuilder(args);// 引入控制台日志输出builder.Logging.AddConsole(consoleLogOptions =>{// 配置所有日志输出到stderrconsoleLogOptions.LogToStandardErrorThreshold = LogLevel.Trace;});// 添加MCPServer服务builder.Services.AddMcpServer() // 注册Mcp服务//.WithStdioServerTransport() // 添加stdio传输配置用于接收控制台输入输出流.WithHttpTransport() // 添加http传输配置用于接收http请求输入输出.WithToolsFromAssembly(); // 配置Mcp工具通过当前程序集获取// 运行宿主应用var app = builder.Build();app.MapMcp(); // streamable http(http://[ip]:[port]/) 与 sse (http://[ip]:[port]/sse)await app.RunAsync();
}

运行服务,本地访问地址为http://localhost:5000

info: Microsoft.Hosting.Lifetime[14]Now listening on: http://localhost:5000
info: Microsoft.Hosting.Lifetime[0]Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]Hosting environment: Production
info: Microsoft.Hosting.Lifetime[0]

连接类型转换为SSE 或者 Streamable http,需要注意的是,选择SSE时,以当前服务为例,连接时,访问地址默认应该为http://localhost:5000/sse;选择Streamable HTTP时,访问地址为http://localhost:5000/。也可以按照自身需求进行调整。
SSE
Pasted image 20251014003548.png
Streamable HTTP
Pasted image 20251014003649.png

工具列表:
Pasted image 20251014003727.png

MCP服务调试

npx

可以通过npx 执行@modelcontextprotocol/inspector 以及程序运行指令用于调试Server 端。
node 版本为15.x 及其以上。否则会出现AbortController is not defined
查看版本。

node --version

切换目录到项目根目录,运行dotnet run --project <project_name>.csproj;实际生产环境直接执行应用程序集,与控制台执行命令行无差异。

>npx @modelcontextprotocol/inspector dotnet run --project <project_name>.csproj
Need to install the following packages:
@modelcontextprotocol/inspector@0.17.0
Ok to proceed? (y) y

或者。

>npx -y @modelcontextprotocol/inspector dotnet run --project <project_name>.csproj
Need to install the following packages:
@modelcontextprotocol/inspector@0.17.0

也可以直接运行npx -y @modelcontextprotocol/inspector,进入页面后再进行连接配置。
运行效果如下:
Pasted image 20251013231808.png
左侧点击连接,连接成功,右侧内容将显示出来,包括ToolsPing 等。
Pasted image 20251013231858.png

点击工具,获取工具列表,选择工具项,可对工具进行交互测试。
Pasted image 20251013232126.png

Pasted image 20251013232306.png

MCP服务资源

作为MCP 服务器,暴露给模型上下文的资源,可以是文本,二进制文件,数据库记录,API 响应,实时系统数据,截图和图像以及更多;每个资源都由唯一的 URI(统一资源标识符)标识。

[协议]://[主机]/[路径] 
[protocol]://[host]/[path]

使用[McpServerResourceType] 作为资源类型,[McpServerResource] 配置资源。
创建一个资源生成器ResourceGenerator,用于模拟资源,直接拷贝的官方案例代码。

static class ResourceGenerator
{private static readonly List<Resource> _resources = Enumerable.Range(1, 100).Select(i =>{var uri = $"test://template/resource/{i}";if (i % 2 != 0){return new Resource{Uri = uri,Name = $"Resource {i}",MimeType = "text/plain",Description = $"Resource {i}: This is a plaintext resource"};}else{var buffer = System.Text.Encoding.UTF8.GetBytes($"Resource {i}: This is a base64 blob");return new Resource{Uri = uri,Name = $"Resource {i}",MimeType = "application/octet-stream",Description = Convert.ToBase64String(buffer)};}}).ToList();public static IReadOnlyList<Resource> Resources => _resources;
}

创建服务资源MyResources

/// <summary>
/// 自定义资源
/// </summary>
[McpServerResourceType]
internal class MyResources
{[McpServerResource(UriTemplate = "test://direct/text/resource", Name = "定向文本资源", MimeType = "text/plain")]//[Description("一个定向文本资源")]public static string DirectTextResource() => "这是一个定向文本资源";[McpServerResource(UriTemplate = "test://template/resource/{id}", Name = "通过id获取资源的模板资源")]//[Description("通过id获取资源的资源模板")]public static ResourceContents TemplateResource(RequestContext<ReadResourceRequestParams> requestContext, int id){int index = id - 1;if ((uint)index >= ResourceGenerator.Resources.Count){throw new NotSupportedException($"Unknown resource: {requestContext.Params?.Uri}");}var resource = ResourceGenerator.Resources[index];return resource.MimeType == "text/plain" ?new TextResourceContents{Text = resource.Description!,MimeType = resource.MimeType,Uri = resource.Uri,} :new BlobResourceContents{Blob = resource.Description!,MimeType = resource.MimeType,Uri = resource.Uri,};}
}

程序集注册(自动)

使用WithResourcesFromAssembly() 进行自动注册。

// 添加MCPServer服务
builder.Services
.AddMcpServer() // 注册Mcp服务
//.WithStdioServerTransport() // 添加stdio传输配置用于接收控制台输入输出流
.WithHttpTransport() // 添加http传输配置用于接收http请求输入输出
//---------------------------通过程序集加载资源------------------------
.WithResourcesFromAssembly()
//---------------------------通过程序集加载资源------------------------

手动配置

也可以通过WithResources进行手动注册资源类型。

// 添加MCPServer服务
builder.Services
.AddMcpServer() // 注册Mcp服务
//.WithStdioServerTransport() // 添加stdio传输配置用于接收控制台输入输出流
.WithHttpTransport() // 添加http传输配置用于接收http请求输入输出
//---------------------------通过程序集加载资源------------------------
//.WithResourcesFromAssembly()
//---------------------------通过程序集加载资源------------------------
//---------------------------通过手动配置工具------------------------
.WithTools<CommonTools>()
//---------------------------通过手动配置工具------------------------
//---------------------------手动配置提示词------------------------
.WithPrompts<MyPrompts>()
//---------------------------手动配置提示词------------------------
//---------------------------手动配置访问资源------------------------
.WithResources<MyResources>()
//---------------------------手动配置访问资源------------------------

运行效果如下:
定向资源。
Pasted image 20251015011050.png

模板资源。
Pasted image 20251015011151.png

服务提示词

使用[McpServerPromptType] 实现对服务端特定提示词类型的自定义声明,使用McpServerPrompt 用于定义对应的服务提示词。

/// <summary>
/// 服务端提示词
/// </summary>
[McpServerPromptType]
internal class MyPrompts
{[McpServerPrompt, Description("创建一个提示词获取天气模板提供给大模型.")]public static ChatMessage Weather([Description("需要获取天气的地点")] string address) =>new(ChatRole.User, $"获取:{address}当前天气");
}

程序集注册(自动)

Program的主函数中使用.WithPromptsFromAssembly() 实现程序集注册Prompt

// 添加MCPServer服务
builder.Services
.AddMcpServer() // 注册Mcp服务
.WithHttpTransport() // 添加http传输配置用于接收http请求输入输出
//---------------------------通过程序集加载提示词------------------------
//.WithToolsFromAssembly() // 配置Mcp工具通过当前程序集获取
//---------------------------通过程序集加载提示词------------------------
.WithPromptsFromAssembly()
;

手动配置

也可以使用WithPrompts实现提示词类型手动配置。

// 添加MCPServer服务
builder.Services
.AddMcpServer() // 注册Mcp服务
//.WithStdioServerTransport() // 添加stdio传输配置用于接收控制台输入输出流
.WithHttpTransport() // 添加http传输配置用于接收http请求输入输出
//---------------------------通过程序集加载工具------------------------
//.WithToolsFromAssembly() // 配置Mcp工具通过当前程序集获取
//---------------------------通过程序集加载工具------------------------
//---------------------------通过程序集加载提示词------------------------
//.WithPromptsFromAssembly()
//---------------------------通过程序集加载提示词------------------------
//---------------------------通过手动配置工具------------------------
.WithTools<CommonTools>()
//---------------------------通过手动配置工具------------------------
//---------------------------手动配置提示词------------------------
.WithPrompts<MyPrompts>()
//---------------------------手动配置提示词------------------------

调测效果如下:

工具编写与注册

创建工具类,需要注意的是类顶部需要添加特性[McpServerToolType],工具函数添加[McpServerTool],工具函数描述尽可能描述清晰,.WithToolsFromAssembly() 简化了工具的注册和解析过程。

/// <summary>
/// 通用命令工具
/// </summary>
[McpServerToolType]
internal class CommonTools
{/// <summary>/// Echo 输出工具/// </summary>/// <param name="message">客户端发送信息</param>/// <returns></returns>[McpServerTool, Description("Echo 输出工具,将客户端发送进行返回输出")]public static string Echo(string message) => $"你好 {message}";/// <summary>/// 获取当前天气/// </summary>/// <returns></returns>[McpServerTool, Description("获取当前天气,通过调用为客户端返回当前天气")]internal static string GetCurrentWeather() => Random.Shared.NextDouble() > 0.5 ? "It's sunny" : "It's raining";
}

程序集注册(自动)

        // 添加MCPServer服务builder.Services.AddMcpServer() // 注册Mcp服务.WithStdioServerTransport().WithToolsFromAssembly(); // 配置Mcp工具通过当前程序集获取// 运行宿主应用await builder.Build().RunAsync();

项目运行如下:

info: ModelContextProtocol.Server.StdioServerTransport[857250842]Server (stream) (EchoMcpServer) transport reading messages.
info: Microsoft.Hosting.Lifetime[0]Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]Hosting environment: Production
info: Microsoft.Hosting.Lifetime[0]

手动配置

手动配置通过WithTools<>() 配置[McpServerToolType] 实现类。

static async Task Main(string[] args)
{// 省略不变部分// 添加MCPServer服务builder.Services.AddMcpServer() // 注册Mcp服务//.WithStdioServerTransport() // 添加stdio传输配置用于接收控制台输入输出流.WithHttpTransport() // 添加http传输配置用于接收http请求输入输出//---------------------------通过程序集加载工具------------------------//.WithToolsFromAssembly() // 配置Mcp工具通过当前程序集获取//---------------------------通过程序集加载工具------------------------//---------------------------通过手动配置工具------------------------.WithTools<CommonTools>()//---------------------------通过手动配置工具------------------------;// 运行宿主应用var app = builder.Build();app.MapMcp(); // streamable http(http://[ip]:[port]/) 与 sse (http://[ip]:[port]/sse)await app.RunAsync();
}

依赖注入与请求参数

工具函数为静态函数,官方库也支持通过函数方式实现服务的依赖注入,前提条件为服务已经注册;请求参数通过json/form方式进行接收,对应描述使用[Description],希望后续能支持注释。
Program 中注册服务。

internal class Program
{static async Task Main(string[] args){// 创建主机构建器实例var builder = WebApplication.CreateBuilder(args);// 注册HttpClient服务(用于依赖注入)builder.Services.AddHttpClient();// 添加MCPServer服务builder.Services.AddMcpServer(); // 注册Mcp服务// 省略不变内容}
}

请求实体类RequestBody属性如下:

/// <summary>
/// 请求体
/// </summary>
[Description("请求体")]
internal class RequestBody
{/// <summary>/// 用户Id/// </summary>[Required][Description("用户Id,不允许值为0")]public int UserId { get; set; }/// <summary>/// 用户名/// </summary>[MaxLength(10)][Description("用户名称")]public string UserName { get; set; }
}

工具函数中进行依赖注入。

[McpServerTool, Description("获取客户端信息,通过调用该工具返回当前服务与客户端信息")]
public static string GetClientInfo(McpServer mcpServer,HttpClient httpClient,[Description("这是请求下载对应请求参数")]RequestBody requestBody,[Description("这是一个用于动态下载的请求连接")]string url) {return $"{mcpServer.SessionId}:{url}";
}

使用测试工具连接后,效果如下:
Pasted image 20251014233138.png

http://www.dtcms.com/a/487237.html

相关文章:

  • 网银网站模板网站开发实训报告总结
  • 男人互做网站温州网站建设成功案例
  • 隐私计算技术全景:从联邦学习到可信执行环境的实战指南—数据安全——隐私计算 联邦学习 多方安全计算 可信执行环境 差分隐私
  • 如何做交易网站微信营销技巧
  • 实验室软件如何提升实验室管理水平
  • SQL Server 报错 当 IDENTITY_INSERT 设置为 OFF 时,不能为表 ‘ORDER_BTN‘ 中的标识列插入显式值
  • 在百度上怎么建网站怎么设置网站字体
  • Linux MySQL 多实例部署与配置实践
  • 从0到1:打造专业级AI教学助手的完整开发实录
  • 练习python题目小记
  • 有没有做问卷还能赚钱的网站一线视频免费观看
  • JavaWeb后端实战(登录认证 令牌技术 拦截器 过滤器)
  • 中国绿色专利数据库(1985-2024)
  • 移动端公众号网站开发专业做球赛旅游的网站
  • 请人做网站需要注意什么如何注册公司网站域名
  • Android开发——设计模式技术总结
  • 做网站要搭建本地服务器么网站建设可行性研究
  • 表3-5企业网站建设可行性分析静态网页怎么放到网上
  • 荆州网站建设荆州手工制作书签简单又好看
  • 伪静态就是把网站地址如何自己创建小程序
  • GPT-2 技术报告
  • Tiger生成式推荐
  • 宿州企业网站建设小程序服务器可以做网站吗
  • Vue组件中Prop类型定义与泛型类型安全指南
  • 企业级流程平台权责模块架构升级:技术实现与核心价值
  • vscode如何链接远程服务器里面的docker里面的目录
  • 从B站提取视频或音频、音乐,下复制链接,然后到提取网站进行提取和下载
  • 新的网站怎么推广淘宝客返利网站程序
  • 算法沉淀第三天(统计二进制中1的个数 两个整数二进制位不同个数)
  • 制造业的未来:数字孪生正在重塑一切