基于.Net与Ollama的MCP服务端工具调用实践
一、技术背景与架构设计
MCP(Model Context Protocol)作为新兴的AI服务协议,通过标准化接口实现大模型与外部工具的解耦交互。其核心价值在于将工具调用能力抽象为可复用的服务组件,使模型能够动态调用数据库查询、API接口、本地脚本等外部资源。
在架构设计上,采用分层模型:
- 协议层:实现MCP标准接口,处理HTTP请求/响应
- 工具管理层:维护工具注册表,管理工具元数据
- 执行层:调用本地或远程工具,处理参数转换
- 模型层:集成Ollama等本地大模型服务
graph TDA[客户端] --> B[MCP服务端]B --> C[协议解析]C --> D[工具管理]D --> E[工具执行]E --> F[Ollama模型]E --> G[数据库/API]
二、.Net实现MCP服务端核心步骤
1. 创建ASP.NET Core Web API项目
dotnet new webapi -n McpServercd McpServer
2. 实现MCP协议接口
定义符合MCP规范的DTO模型:
public class McpRequest{public string Id { get; set; }public List<McpTool> Tools { get; set; }public McpCommand Command { get; set; }}public class McpResponse{public string Id { get; set; }public List<McpToolCall> ToolCalls { get; set; }public string Text { get; set; }}
创建MCP控制器:
[ApiController][Route("mcp")]public class McpController : ControllerBase{private readonly IToolManager _toolManager;public McpController(IToolManager toolManager){_toolManager = toolManager;}[HttpPost]public async Task<McpResponse> HandleRequest([FromBody] McpRequest request){// 1. 解析模型请求var context = new McpContext(request);// 2. 执行工具调用var toolCalls = await _toolManager.ExecuteTools(context);// 3. 构建响应return new McpResponse{Id = request.Id,ToolCalls = toolCalls};}}
3. 工具管理系统实现
定义工具接口:
public interface ITool{string Name { get; }string Description { get; }Task<ToolResult> Execute(ToolParameters parameters);}
实现具体工具(以数据库查询为例):
public class DatabaseTool : ITool{public string Name => "database_query";public string Description => "执行SQL查询";public async Task<ToolResult> Execute(ToolParameters parameters){var query = parameters.GetString("query");// 使用Dapper等ORM执行查询using var connection = new SqlConnection("连接字符串");var results = await connection.QueryAsync<dynamic>(query);return new ToolResult{Data = results};}}
三、Ollama模型集成方案
1. 模型服务部署
通过行业常见技术方案部署Ollama服务:
# 示例:使用Docker部署docker run -d -p 11434:11434 ollama/ollama
2. 创建模型客户端
public class OllamaClient{private readonly HttpClient _httpClient;public OllamaClient(string baseUrl){_httpClient = new HttpClient{BaseAddress = new Uri(baseUrl)};}public async Task<string> GenerateText(string prompt){var request = new{model = "llama2",prompt = prompt,stream = false};var response = await _httpClient.PostAsJsonAsync("api/generate", request);response.EnsureSuccessStatusCode();var result = await response.Content.ReadAsStringAsync();// 解析JSON获取生成文本return ParseResponse(result);}}
四、工具调用流程实现
1. 工具注册机制
public class ToolRegistry{private readonly Dictionary<string, ITool> _tools = new();public void RegisterTool(ITool tool){_tools[tool.Name] = tool;}public ITool GetTool(string name){if (_tools.TryGetValue(name, out var tool)){return tool;}throw new KeyNotFoundException($"工具 {name} 未注册");}}
2. 调用流程示例
public async Task<List<McpToolCall>> ExecuteTools(McpContext context){var calls = new List<McpToolCall>();foreach (var toolReq in context.Request.Tools){var tool = _toolRegistry.GetTool(toolReq.Name);var parameters = ParseParameters(toolReq.Parameters);var result = await tool.Execute(parameters);calls.Add(new McpToolCall{Id = toolReq.Id,Function = tool.Name,Arguments = result.Data});}return calls;}
五、性能优化与异常处理
1. 并发控制策略
public class ConcurrentToolExecutor{private readonly SemaphoreSlim _semaphore = new(10); // 限制并发数public async Task ExecuteWithConcurrency(ITool tool, ToolParameters parameters){await _semaphore.WaitAsync();try{return await tool.Execute(parameters);}finally{_semaphore.Release();}}}
2. 异常处理机制
public class ToolExecutionHandler{public async Task<ToolResult> SafeExecute(ITool tool, ToolParameters parameters){try{return await tool.Execute(parameters);}catch (Exception ex){return new ToolResult{Error = new ToolError{Message = ex.Message,Type = ex.GetType().Name}};}}}
六、部署与监控建议
-
容器化部署:使用Docker Compose编排MCP服务与Ollama模型
version: '3.8'services:mcp-server:build: ./McpServerports:- "5000:80"environment:- OLLAMA_BASE_URL=http://ollama:11434ollama:image: ollama/ollamaports:- "11434:11434"
-
监控指标:
- 工具调用成功率
- 平均响应时间
- 模型生成延迟
- 并发请求数
-
日志设计:
{"timestamp": "2023-07-20T12:34:56Z","requestId": "abc123","toolName": "database_query","status": "success","durationMs": 45,"parameters": {"query": "SELECT * FROM users"}}
七、最佳实践总结
-
工具设计原则:
- 保持工具功能单一
- 提供清晰的输入/输出规范
- 实现幂等性操作
-
安全考虑:
- 实施工具调用权限控制
- 对输入参数进行验证
- 限制敏感工具的访问
-
性能优化:
- 对耗时工具实现异步调用
- 使用缓存机制存储工具结果
- 实施请求限流策略
通过上述实现方案,开发者可以快速构建具备工具调用能力的MCP服务端,并与本地大模型服务形成完整解决方案。这种架构既保持了模型的灵活性,又通过标准化接口实现了工具资源的复用,特别适合需要动态扩展AI能力的企业级应用场景。