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

.NET MCP Server 开发教程

.NET MCP Server 开发教程

本教程基于实际项目经验,(注意:该教程基于实际项目反向使用ai生成,难免留有遗漏)详细介绍如何使用 .NET 8 开发 Model Context Protocol (MCP) 服务器。

目录

  • 环境准备
  • 项目创建
  • MCP 基础概念
  • 项目结构
  • 开发步骤
  • 工具方法实现
  • 错误处理和日志
  • 部署和测试
  • 最佳实践
  • 常见问题

环境准备

1. 开发环境要求

  • .NET 8.0 SDK: 确保安装了 .NET 8.0 或更高版本
  • IDE: Visual Studio 2022 或 Visual Studio Code
  • 操作系统: Windows 10/11 (推荐,某些库可能需要)

2. 验证 .NET 环境

dotnet --version
# 应显示: 8.0.x 或更高版本

项目创建

1. 创建新的控制台项目

dotnet new console -n MyMcpServer -f net8.0
cd MyMcpServer

2. 添加必要的 NuGet 包

<Project Sdk="Microsoft.NET.Sdk"><PropertyGroup><OutputType>Exe</OutputType><TargetFramework>net8.0</TargetFramework><ImplicitUsings>enable</ImplicitUsings><Nullable>enable</Nullable><AssemblyName>MyMcpServer</AssemblyName><RootNamespace>MyMcpServer</RootNamespace></PropertyGroup><ItemGroup><PackageReference Include="McpToolkit" Version="0.1.3" /><PackageReference Include="McpToolkit.Server" Version="0.1.3" /><PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.8" /><PackageReference Include="ModelContextProtocol-SemanticKernel" Version="0.3.0" /><PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" /></ItemGroup></Project>

MCP 基础概念

1. Model Context Protocol (MCP)

MCP 是一种标准化的协议,用于 AI 模型与外部工具和数据源之间的通信。

2. 核心组件

  • MCP Server: 提供工具和资源的服务器
  • MCP Client: 使用工具和资源的客户端
  • Tools: 可执行的功能方法
  • Resources: 可访问的数据源
  • stdio: 标准输入输出通信协议

3. 通信方式

MCP 使用 stdio 进行通信:

  • 输入: JSON-RPC 2.0 请求
  • 输出: JSON-RPC 2.0 响应

项目结构

MyMcpServer/
├── Program.cs                 # 主程序入口
├── MyTools.cs                 # 工具方法实现
├── MyMcpServer.csproj         # 项目文件
├── appsettings.json          # 配置文件
├── Models/                    # 数据模型
│   ├── ToolResult.cs
│   └── ...
└── Services/                  # 服务层└── ...

开发步骤

1. 创建主程序入口

// Program.cs
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using McpToolkit.Server;
using System.ComponentModel;namespace MyMcpServer;class Program
{static async Task Main(string[] args){var builder = Host.CreateApplicationBuilder(args);// 配置 MCP 服务builder.Services.AddMcpServer(options =>{// 配置服务器信息options.ServerInfo = new(){Name = "My MCP Server",Version = "1.0.0"};});// 注册工具类型builder.Services.AddMcpServerToolType<MyTools>();var host = builder.Build();// 启动 MCP 服务器await host.RunMcpAsync();}
}

2. 创建工具类

// MyTools.cs
using ModelContextProtocol.Server;
using System.ComponentModel;namespace MyMcpServer;[McpServerToolType]
public static class MyTools
{[McpServerTool, Description("简单的问候工具")]public static string Greet([Description("要问候的名字")] string name){return $"你好, {name}! 欢迎使用 MCP 服务器。";}[McpServerTool, Description("计算两个数字的和")]public static int Add([Description("第一个数字")] int a,[Description("第二个数字")] int b){return a + b;}[McpServerTool, Description("获取当前时间")]public static string GetCurrentTime(){return DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");}
}

工具方法实现

1. 基本工具方法

[McpServerTool, Description("工具描述")]
public static ReturnType ToolName([Description("参数描述")] ParameterType parameterName,CancellationToken cancellationToken = default)
{try{// 实现逻辑var result = new ResultType{Success = true,Data = processData(parameterName)};return result;}catch (Exception ex){return new ResultType{Success = false,ErrorMessage = ex.Message};}
}

2. 异步工具方法

[McpServerTool, Description("异步工具示例")]
public static Task<AsyncResult> AsyncTool([Description("输入数据")] string input,CancellationToken cancellationToken = default)
{return Task.Run(() =>{// 模拟异步操作Task.Delay(1000, cancellationToken);return new AsyncResult{Success = true,ProcessedData = input.ToUpper()};}, cancellationToken);
}

3. 文件处理工具

[McpServerTool, Description("读取文件内容")]
public static FileResult ReadFile([Description("文件路径")] string filePath)
{var result = new FileResult { Success = false };try{if (!File.Exists(filePath)){result.ErrorMessage = $"文件不存在: {filePath}";return result;}var content = File.ReadAllText(filePath);result.Success = true;result.Content = content;result.FileSize = new FileInfo(filePath).Length;}catch (Exception ex){result.ErrorMessage = $"读取文件失败: {ex.Message}";}return result;
}

错误处理和日志

1. 错误处理模式

public static ResultType SafeOperation(string input)
{var result = new ResultType { Success = false };try{// 参数验证if (string.IsNullOrEmpty(input)){result.ErrorMessage = "输入参数不能为空";return result;}// 业务逻辑var processed = ProcessInput(input);result.Success = true;result.Data = processed;return result;}catch (ArgumentException ex){result.ErrorMessage = $"参数错误: {ex.Message}";return result;}catch (InvalidOperationException ex){result.ErrorMessage = $"操作无效: {ex.Message}";return result;}catch (Exception ex){// 记录未预期的错误LogError($"未预期的错误: {ex}");result.ErrorMessage = "系统错误,请稍后重试";return result;}
}

2. 日志记录

public static class Logger
{private static readonly string LogPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory,"mcp_server.log");public static void LogInfo(string message){LogToFile("INFO", message);}public static void LogError(string message){LogToFile("ERROR", message);// 同时输出到 stderr (MCP 标准)Console.Error.WriteLine($"[ERROR] {message}");}private static void LogToFile(string level, string message){try{var timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");var logMessage = $"[{timestamp}] [{level}] {message}";File.AppendAllText(LogPath, logMessage + Environment.NewLine);}catch{// 忽略日志写入错误}}
}

数据模型定义

1. 基础结果模型

// Models/OperationResult.cs
public class OperationResult
{public bool Success { get; set; }public string? ErrorMessage { get; set; }public long ElapsedMilliseconds { get; set; }
}public class DataResult<T> : OperationResult
{public T? Data { get; set; }
}public class FileResult : OperationResult
{public string? Content { get; set; }public long FileSize { get; set; }public string? FileName { get; set; }
}

2. 复杂数据模型

// Models/TextBlock.cs
public class TextBlock
{public string Text { get; set; } = string.Empty;public double Confidence { get; set; }public BoundingBox BoundingBox { get; set; } = new();
}public class BoundingBox
{public int X { get; set; }public int Y { get; set; }public int Width { get; set; }public int Height { get; set; }
}

部署和测试

1. 编译项目

# Release 编译
dotnet build --configuration Release# 发布自包含应用
dotnet publish --configuration Release --self-contained -r win-x64

2. 本地测试

# 直接运行
./bin/Release/net8.0/MyMcpServer.exe# 或使用 dotnet 运行
dotnet run --configuration Release

3. Claude Code 配置

在 Claude Code 的配置文件中添加你的 MCP 服务器:

{"mcpServers": {"myMcpServer": {"command": "D:\\path\\to\\MyMcpServer.exe","args": []}}
}

最佳实践

1. 代码组织

  • 单一职责: 每个工具方法只做一件事
  • 命名规范: 使用清晰的方法和参数名
  • 文档注释: 为所有工具方法添加 Description 特性

2. 错误处理

  • 输入验证: 总是验证输入参数
  • 异常捕获: 捕获并处理预期的异常
  • 错误信息: 提供有意义的错误消息

3. 性能考虑

  • 异步操作: 对于耗时操作使用异步方法
  • 资源管理: 正确使用 using 语句管理资源
  • 缓存: 对于重复计算考虑使用缓存

4. 安全考虑

  • 输入验证: 防止注入攻击
  • 路径验证: 验证文件路径的合法性
  • 权限检查: 确保只访问授权的资源

常见问题

1. 编译错误

问题: 找不到 McpToolkit 相关类型
解决: 确保正确安装了 NuGet 包

<PackageReference Include="McpToolkit" Version="0.1.3" />
<PackageReference Include="McpToolkit.Server" Version="0.1.3" />

2. 运行时错误

问题: MCP 服务器无法启动
解决: 检查 Program.cs 中的服务配置

builder.Services.AddMcpServerToolType<MyTools>();

3. 通信问题

问题: Claude Code 无法连接到 MCP 服务器
解决:

  • 确保服务器程序路径正确
  • 检查服务器是否正常输出 JSON-RPC 响应
  • 验证 stdio 通信是否正常

4. 工具调用失败

问题: 工具方法返回错误
解决:

  • 检查方法签名是否正确
  • 确保参数类型匹配
  • 添加详细的错误日志

实际项目示例

基于我们开发的 OCR MCP 服务器,这里展示一个完整的实际项目结构:

1. 项目文件 (OCRMCP.Server.csproj)

<Project Sdk="Microsoft.NET.Sdk"><PropertyGroup><OutputType>Exe</OutputType><TargetFramework>net8.0</TargetFramework><ImplicitUsings>enable</ImplicitUsings><Nullable>enable</Nullable><AssemblyName>OCRMCP.Server</AssemblyName><RootNamespace>OCRMCP.Server</RootNamespace></PropertyGroup><ItemGroup><PackageReference Include="McpToolkit" Version="0.1.3" /><PackageReference Include="McpToolkit.Server" Version="0.1.3" /><PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.8" /><PackageReference Include="ModelContextProtocol-SemanticKernel" Version="0.3.0" /><PackageReference Include="PaddleOCRSharp" Version="5.1.0" /><PackageReference Include="PdfiumViewer" Version="2.13.0" /><PackageReference Include="SixLabors.ImageSharp" Version="3.1.5" /><PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" /></ItemGroup>
</Project>

2. 主程序 (Program.cs)

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using McpToolkit.Server;namespace OCRMCP.Server;class Program
{static async Task Main(string[] args){var builder = Host.CreateApplicationBuilder(args);builder.Services.AddMcpServer(options =>{options.ServerInfo = new(){Name = "OCR MCP Server",Version = "1.0.0"};});builder.Services.AddMcpServerToolType<OCRTools>();var host = builder.Build();await host.RunMcpAsync();}
}

3. 核心工具类 (OCRTools.cs)

using ModelContextProtocol.Server;
using System.ComponentModel;
using PaddleOCRSharp;namespace OCRMCP.Server;[McpServerToolType]
public static class OCRTools
{private static PaddleOCREngine? _ocrEngine;private static readonly object _lockObject = new object();private static bool _isInitialized = false;static OCRTools(){InitializeOCREngine();}[McpServerTool, Description("识别图片中的文本内容")]public static Task<OCRResult> RecognizeImage([Description("图片文件路径")] string imagePath,[Description("是否预处理图片以提高识别率")] bool preprocess = true,CancellationToken cancellationToken = default){var result = new OCRResult { Success = false };try{// 参数验证if (string.IsNullOrEmpty(imagePath)){result.ErrorMessage = "缺少必需参数:imagePath";return Task.FromResult(result);}if (!File.Exists(imagePath)){result.ErrorMessage = $"图片文件不存在: {imagePath}";return Task.FromResult(result);}// 初始化 OCR 引擎InitializeOCREngine();if (!_isInitialized || _ocrEngine == null){result.ErrorMessage = "OCR引擎初始化失败";return Task.FromResult(result);}// 执行 OCR 识别var paddleResult = _ocrEngine.DetectText(imagePath);result = ConvertToOCRResult(paddleResult, imagePath);result.Success = true;return Task.FromResult(result);}catch (Exception ex){result.Success = false;result.ErrorMessage = $"识别失败: {ex.Message}";return Task.FromResult(result);}}private static void InitializeOCREngine(){// OCR 引擎初始化逻辑// ...}private static OCRResult ConvertToOCRResult(PaddleOCRSharp.OCRResult paddleResult, string sourcePath){// 结果转换逻辑// ...}
}

总结

通过本教程,你应该能够:

  1. ✅ 创建一个基本的 .NET 8 MCP 服务器
  2. ✅ 实现各种类型的工具方法
  3. ✅ 处理错误和日志记录
  4. ✅ 部署和测试 MCP 服务器
  5. ✅ 遵循最佳实践开发高质量的服务器

MCP 服务器开发是一个不断发展的领域,建议持续关注官方文档和社区更新。希望这个教程对你有所帮助!


参考资源:

  • Model Context Protocol 官方文档
  • MCP Toolkit GitHub
  • .NET 8 官方文档

项目示例: 本教程基于实际的 OCR MCP 服务器项目,你可以参考完整的实现代码。

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

相关文章:

  • LeetCode 124. 二叉树中的最大路径和(困难)
  • 建设南大街小学网站wordpress首页调用指定文章列表
  • 大型语言模型(LLM)基础:从原理到核心概念详解(GPT-4 / 文心一言 / 通义千问)
  • python高级03——多任务编程
  • 树模型优劣大比拼xgboost/lightgbm/RF/catboost,股价预测怎么选模型
  • 哈尔滨快速建站公司推荐营销型网站建设实战》
  • 4.3-中间件之Kafka
  • 方寸之间见天地:新兴高端印章的当代破局与价值重构
  • 如何改善基于深度学习的场重构
  • Maven 进行项目构建settings.xml 配置教程
  • 磁力搜索网站怎么做的网站和app设计区别
  • 西安网站建设公司都有哪些网站设计开发文档模板下载
  • C++设计模式_结构型模式_桥接模式Bridge
  • 关于flutter插件的存储位置问题
  • 把“Mixed Content”吃干抹净——一次 https→http 踩坑实录
  • 中山大学联合项目 论文解读 | iManip:面向机器人操作的技能增量学习
  • Unity:Json笔记——Json文件格式、JsonUtlity序列化和反序列化
  • 第八章 惊喜15 小萍收获初会
  • RabbitMQ基础知识与Spring Boot 3.x集成案例
  • 租房网站建设多少钱网站域名怎么改
  • Redis CPU高负载案例分析
  • ARMv9 CCA机密计算架构演进技术解析:重塑云原生时代的数据安全基石
  • 湖州网站设计浙北数据最新发布的手机有哪些
  • AD加域账号权限设置
  • 解决idea报错:Error running TrustApexCrmApplication. Command line is too long
  • 网站开发淄博进口商品代理平台
  • systme V共享内存(version1)
  • 万网网站制作wordpress投稿管理系统
  • python(47) : 快速截图[Windows工具(2)]
  • VSCODE GDB调试