尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

旧系统AI化实战:MCP架构下的最小侵入式适配层设计

旧系统AI化实战:MCP架构下的最小侵入式适配层设计 1. 项目概述为什么老系统必须“带电升级”而不是推倒重来“旧系统平台接入 MCP 实践指南在不重写核心的前提下为老系统接上 AI 能力”——这个标题里藏着一个被无数技术负责人深夜挠头的真实困境你手里的那套跑了八年、数据库还是 SQL Server 2016、中间件用着 Windows Server 2016 上的 IIS、业务逻辑全在 ASP.NET WebForms 里硬编码的订单系统它没坏但已经“哑”了。它不报错但也不说话它能跑但不会思考它能查库存但猜不出客户下周要买什么它能录工单但没法自动归类、打标、推送责任人。这不是技术债这是能力断层。而MCP——不是某个具体厂商的私有协议而是当前工业级AI集成中正在快速收敛的一种模型能力代理Model Capability Proxy架构范式它的本质是把大模型的推理能力、工具调用能力、记忆管理能力、多步规划能力封装成一组标准化、可发现、可编排、可鉴权的 HTTP 接口服务。它不替代你的业务系统而是像给一台老式柴油机加装智能电控单元发动机本体不动油路气路照旧但喷油时机、空燃比、故障预警全由新模块实时调控。我做过三个大型制造业客户的旧系统AI化改造最典型的一个案例是某汽车零部件厂的 MES 系统。它上线于2014年核心数据库是 SQL Server 2012前端是 IE6 兼容模式的 ActiveX 控件连 HTTPS 都是后期打补丁加上的。客户明确要求六个月内上线“智能工单推荐”功能能根据历史维修记录、设备传感器数据来自另一套独立的 SCADA 系统、备件库存状态自动给出维修方案优先级和预计耗时。预算只够买两台 GPU 服务器不允许动现有代码库一行。最后我们用 MCP 架构在两周内完成了适配层开发三个月上线灰度零停机。关键就卡在“不重写核心”这五个字上——不是不能重写而是重写成本是接入 MCP 的 7 倍以上且风险不可控。所以这篇指南不讲“如何用 LangChain 搭建一个完美 Agent”而是聚焦在当你的系统还在用 ADO.NET 直连 SQL Server当你的日志还写在 Windows Event Log 里当你的用户认证还是 NTLM你该怎么让这套系统“听懂人话”并“说出人话”。核心关键词 MCP、AI、旧系统、Server、适配层每一个都不是虚词MCP 是方法论AI 是目标能力旧系统是约束条件Server 是运行载体适配层是唯一可行的解法。适合谁适合所有手握“活着但已失语”的系统的技术负责人、架构师、资深后端工程师——尤其是那些刚被老板问“咱们的系统什么时候能接入AI”的人。这不是未来时是进行时不是选修课是必修课。2. 整体设计思路为什么 MCP 是旧系统 AI 化的“最小侵入式手术”2.1 旧系统的核心顽疾与 MCP 的精准匹配点旧系统不是技术落后而是设计契约固化。它的顽疾有三数据孤岛化、交互命令化、扩展黑盒化。数据孤岛化指业务数据深埋在 SQL Server 的存储过程里字段含义靠文档和老人记忆交互命令化指所有操作都是“点击按钮→执行存储过程→刷新页面”没有上下文、没有意图理解、没有多轮对话扩展黑盒化指任何新功能都要走需求评审→代码修改→测试→UAT→上线的长周期根本无法响应“今天下午要加个根据聊天记录自动填工单”的临时需求。而 MCP 架构恰恰是为破解这三点而生的。MCP 不要求你把 SQL Server 表结构改成向量数据库它只要求你提供一个“数据能力接口”——比如一个 REST API输入是 {“device_id”: “MOT-203”, “time_range”: “last_7d”}输出是 JSON 格式的传感器读数数组。这个接口可以是用 C# 写的 ASP.NET Core Minimal API包装一层老系统的 ADO.NET 查询也可以是 PowerShell 脚本调用 SQLCMD再用 Python Flask 封装。重点在于MCP Server 只认这个接口的契约输入/输出格式、鉴权方式、超时时间不关心你内部怎么实现。这就解决了数据孤岛化——你不用迁移数据只需暴露能力。交互命令化呢MCP 的核心组件之一是“意图识别网关”。它接收自然语言请求如“帮我查一下注塑机 M203 昨天的温度异常点”通过轻量级 LLM我们常用的是 Phi-3 或 Qwen2-0.5B16GB 显存就能跑做意图分类和槽位填充然后路由到你刚才暴露的那个传感器数据接口再把结果喂给另一个“报告生成器”MCP 服务最终返回一段带时间戳和图表链接的中文摘要。整个过程对老系统完全透明它只看到一次 HTTP GET 请求。至于扩展黑盒化MCP 的“能力注册中心”就是答案。你写好一个新能力比如“根据维修日志生成知识图谱节点”按约定格式JSON Schema 描述输入输出、Swagger 文档地址、健康检查端点注册到中心MCP Server 自动发现、自动负载均衡、自动熔断。下周一上午写的代码下午就能被 AI Agent 调用无需重启任何老服务。这才是真正的敏捷。2.2 为什么不是直接调用大模型 API——成本、延迟与可控性的铁三角有人会问既然目标是 AI 能力那我的老系统后端直接调用 OpenAI 或千问的 API 不就行了我试过也踩过坑。在真实生产环境里这条路走不通原因有三构成一个死循环。第一是成本失控。一个典型的旧系统业务流程比如“客户投诉处理”涉及查订单、查物流、查历史投诉、查产品规格、生成回复草稿、推送客服主管。如果每一步都调用一次大模型 API按 GPT-4 Turbo 的价格约 $0.01/千 token一次完整流程消耗 8000 token成本就是 $0.08。系统日均处理 5000 单单日成本 $400月成本 $12,000。而我们的 MCP 方案核心 LLM 只用于最关键的“意图解析”和“终稿润色”其他步骤全部由轻量级规则引擎或预训练小模型完成单次成本压到 $0.003 以内降幅 96%。这不是省小钱是决定项目能否过预算的关键。第二是延迟不可控。大模型 API 的 P95 延迟通常在 1.5~3 秒而旧系统对关键操作如下单、支付的 SLA 要求是 500ms 内。你不可能让客户在支付页面等三秒看“正在思考您的优惠券”。MCP 的解法是“能力分层”。高频、确定性高的能力如“查余额”、“校验密码强度”用本地部署的 ONNX 模型或 Redis 缓存实现延迟 50ms中频、需一定推理的能力如“分析聊天记录情绪”用量化后的 Phi-3延迟 300ms真正需要大模型创造力的如“起草一封致歉信”才走外网 API且必须异步化——先返回“已受理稍后推送结果”避免阻塞主流程。第三是可控性归零。大模型 API 的输出是黑盒你无法保证它明天不会把“SQL Server”拼成“SQL Sever”也无法让它严格遵守你公司的《对外沟通话术规范》。而 MCP 的核心价值在于“可插拔的治理层”。我们在 MCP Server 和下游能力之间插入了一个“输出过滤器”中间件所有大模型返回的文本必须经过正则规则屏蔽敏感词、模板校验强制包含“尊敬的客户”、“感谢您的反馈”等固定开头结尾、事实核查调用知识库 API 验证提到的产品型号是否存在三道关卡才能发给前端。这个治理层是你对 AI 输出的唯一控制权。没有 MCP你就只能祈祷模型别出错有了 MCP你就能定义什么叫“合规的 AI”。2.3 适配层旧系统与 MCP 之间的“翻译官”与“安全阀”适配层Adapter Layer是整个方案的物理锚点它不是可有可无的胶水代码而是承载了三大不可替代职能的“数字海关”。首先是协议翻译。旧系统讲的是“SQL Server T-SQL”、“Windows COM 组件”、“SOAP XML”MCP 讲的是“REST/JSON”、“gRPC”、“OpenAPI 3.0”。适配层就是那个能把“EXEC sp_GetOrderStatus OrderID12345”翻译成 “GET /api/v1/orders/12345/status?include_historytrue” 的翻译官。它不改变语义只转换语法。我们通常用 C# 的 HttpClient 或 Python 的 requests 库实现关键是要做连接池管理——SQL Server 连接字符串里有 Connection Timeout30但 HTTP 客户端的 timeout 必须设为 2500ms否则一次慢查询就会拖垮整个 MCP 的线程池。其次是数据映射。老系统的字段名可能是 “CustNm”、“OrdDt”、“ShpQty”而 MCP 要求的是 “customer_name”、“order_date”、“shipped_quantity”。适配层必须内置一套双向映射表且支持运行时热更新。我们用 JSON 文件配置结构如下{ mcp_service: order_status, source_system: legacy_mis, field_mapping: [ {mcp: customer_name, legacy: CustNm, type: string, default: 未知客户}, {mcp: order_date, legacy: OrdDt, type: datetime, format: yyyy-MM-dd HH:mm:ss}, {mcp: shipped_quantity, legacy: ShpQty, type: int, default: 0} ] }每次 MCP Server 发起调用适配层先读取此配置再执行数据转换。这样当业务方说“把发货数量字段改成从新表取”你只需改配置不用动一行 C# 代码。最后是安全阀。这是适配层最隐蔽也最重要的职能。它必须实现①请求熔断——当 SQL Server 连接池耗尽我们监控sys.dm_exec_sessions中login_time超过 5 分钟的会话数适配层立即返回 503并记录告警②响应限流——老系统一次最多返回 1000 条订单但 MCP 的 Agent 可能发起“查所有未发货订单”的请求适配层必须截断并返回 400 错误附带建议分页参数③凭证脱敏——所有从老系统日志里提取的调试信息如 SQL 执行计划在返回给 MCP Server 前必须用正则擦除所有password、key字样。这三层防护让适配层成了旧系统免受 AI 流量冲击的实体防火墙。3. 核心细节解析适配层开发的七处生死关3.1 数据源接入如何让 SQL Server “开口说话”而不惊动 DBA让 SQL Server 为 MCP 提供数据能力绝不是简单地开个新账号、给个 db_datareader 角色就完事。DBA 的红线很清晰不许建视图、不许改存储过程、不许开 xp_cmdshell。我们的解法是“只读快照代理”它满足所有安全要求且性能极佳。第一步创建一个专用的只读登录名。不是用 sa也不是用域账号而是用 SQL Server 2012 支持的“contained database user”-- 在目标数据库中执行 CREATE USER [mcp_reader] WITHOUT LOGIN; ALTER ROLE [db_datareader] ADD MEMBER [mcp_reader]; -- 关键授予 SELECT 权限到具体对象而非整个 schema GRANT SELECT ON OBJECT::[dbo].[Orders] TO [mcp_reader]; GRANT SELECT ON OBJECT::[dbo].[OrderItems] TO [mcp_reader]; GRANT SELECT ON OBJECT::[dbo].[Customers] TO [mcp_reader];这样即使账号泄露攻击者也只能查这三张表且无法执行任何 DML。第二步用SELECT INTO创建轻量级快照表。我们不查原表而是每天凌晨 2 点用 SQL Agent Job 执行-- 创建快照表带时间戳便于回溯 SELECT OrderID as order_id, CustomerID as customer_id, OrderDate as order_date, Status as status_code, GETDATE() as snapshot_time INTO dbo.Orders_Snapshot_20240520 FROM dbo.Orders WHERE OrderDate DATEADD(day, -30, GETDATE()); -- 然后授权给 mcp_reader GRANT SELECT ON dbo.Orders_Snapshot_20240520 TO [mcp_reader];快照表只有关键字段且做了日期分区查询速度比原表快 5 倍。DBA 看到的是“一个只读的、有明确生命周期的、不影响业务的辅助表”没有任何反对理由。第三步在适配层中用连接字符串指向快照表。C# 示例// 连接字符串中指定初始目录为快照库 var connectionString ServerLEGACY-SQL;DatabaseLegacyMIS_Snapshots;User Idmcp_reader;Password***;; using var conn new SqlConnection(connectionString); var cmd new SqlCommand(SELECT * FROM Orders_Snapshot_20240520 WHERE order_id id, conn); cmd.Parameters.AddWithValue(id, orderId); // 执行查询映射到 MCP 要求的 DTO实测下来单次查询平均耗时 12msP99 45ms完全满足 MCP 的 SLA。记住永远不要在生产环境让 MCP 直连业务表快照是底线。3.2 身份认证绕过 NTLM用 JWT 实现“老系统用户”与“MCP 用户”的无缝映射旧系统用 Windows 集成认证NTLM/KerberosMCP 用 JWT Token。如果让前端同时维护两套会话用户体验会崩。我们的方案是“Token 桥接”让一次登录双系统生效。原理很简单当用户在旧系统登录成功后ASP.NET 的 Global.asax 中触发Session_Start事件此时我们不生成 Session ID而是调用 MCP Server 的/auth/bridge接口// 在 Session_Start 中 var jwtPayload new { sub User.Identity.Name, // 域用户名如 CORP\zhangsan exp DateTime.UtcNow.AddHours(8), iat DateTime.UtcNow, legacy_session_id Session.SessionID, permissions GetPermissionsFromAD(User.Identity.Name) // 从 AD 获取角色 }; var token JwtSecurityTokenHandler.CreateEncodedJwt( new SecurityTokenDescriptor { Subject new ClaimsIdentity(new[] { new Claim(sub, jwtPayload.sub) }), Expires jwtPayload.exp, SigningCredentials signingCredentials } ); // POST 到 MCP Server var response await httpClient.PostAsJsonAsync(https://mcp.corp/auth/bridge, new { token });MCP Server 收到后验证 JWT 签名然后将sub即域用户名作为其内部用户 ID 存入 Redis设置过期时间与 JWT 一致。后续所有 MCP 请求只需在 Header 中带Authorization: Bearer tokenMCP Server 解析出sub就能知道这是“CORP\zhangsan”并从 Redis 中取出其权限列表完成鉴权。整个过程对用户完全透明他只在旧系统登录了一次却能无缝使用所有 MCP 能力。我们甚至把 MCP 的菜单项如“智能报表”、“AI 客服”动态注入到旧系统的左侧导航栏里点击即跳转URL 中自动携带该 JWT。这是提升采纳率的关键细节。3.3 错误处理如何把 SQL Server 的“Login failed for user xxx”翻译成 MCP 的“服务暂时不可用”错误码是系统间信任的基石。旧系统抛出的异常五花八门SQL Server 的18456错误、IIS 的500.19、.NET 的NullReferenceException而 MCP 要求统一的 HTTP 状态码和语义化错误体。适配层必须做“错误语义升维”。我们定义了一套三级错误映射表SQL Server Error Number.NET Exception TypeMCP HTTP StatusMCP Error CodeMCP Error Message Template18456 (Login failed)SqlException503SERVICE_UNAVAILABLE“数据服务暂时不可用请稍后重试”2627 (PK violation)SqlException400VALIDATION_FAILED“{field} 值 {value} 已存在请更换”8152 (String truncation)SqlException400VALIDATION_FAILED“{field} 长度超出限制最大 {max_len} 字符”任意其他 SqlException—500INTERNAL_ERROR“系统繁忙请联系管理员”关键在模板中的{field}和{value}占位符。适配层捕获 SqlException 后会解析其Message字段用正则提取// 例如 Message: Cannot insert duplicate key row in object dbo.Customers with unique index IX_Customer_Email. The duplicate key value is (zhangcorp.com). var emailMatch Regex.Match(ex.Message, The duplicate key value is \(([^])\)); if (emailMatch.Success) { errorTemplate errorTemplate.Replace({value}, emailMatch.Groups[1].Value); errorTemplate errorTemplate.Replace({field}, 邮箱); }这样返回给 MCP Server 的错误体就是{ error_code: VALIDATION_FAILED, message: 邮箱值 zhangcorp.com 已存在请更换, timestamp: 2024-05-20T10:30:45Z }而不是冰冷的 “Login failed for user mcp_reader”。这种翻译让前端能精准提示用户也让运维能快速定位是数据问题还是服务问题。我们曾用此机制在 3 分钟内定位出一个因数据库镜像切换导致的连接字符串失效问题——因为所有错误都变成了 503 SERVICE_UNAVAILABLE且timestamp高度集中立刻排除了代码逻辑问题。3.4 日志与追踪在没有 OpenTelemetry 的旧系统里如何实现全链路可观测旧系统没有分布式追踪日志散落在 Windows Event Log、IIS 日志、自定义文本文件里。而 MCP 的调试依赖完整的请求链路。我们的解法是“手动埋点 日志聚合”。在适配层的每个关键节点我们插入结构化日志// 开始处理 MCP 请求 _logger.LogInformation(MCP_ADAPTER_START: {RequestId} | {ServiceName} | {InputParams}, httpContext.TraceIdentifier, serviceName, JsonConvert.SerializeObject(input)); // 调用 SQL Server 前 _logger.LogInformation(MCP_SQL_START: {RequestId} | {Query} | {Parameters}, httpContext.TraceIdentifier, sqlQuery, JsonConvert.SerializeObject(parameters)); // SQL 执行后 _logger.LogInformation(MCP_SQL_END: {RequestId} | {DurationMs}ms | {RowCount} rows, httpContext.TraceIdentifier, stopwatch.ElapsedMilliseconds, reader.RowCount); // 返回 MCP 响应前 _logger.LogInformation(MCP_ADAPTER_END: {RequestId} | {StatusCode} | {OutputSize} bytes, httpContext.TraceIdentifier, httpContext.Response.StatusCode, output.Length);所有日志都带httpContext.TraceIdentifierASP.NET Core 自动生成的唯一请求 ID这样一条请求的所有日志无论来自哪个组件都能用同一个 ID 关联起来。然后用一个轻量级的 Logstash 配置把这些日志从文本文件实时采集添加字段service: mcp-adapter并发送到 ELK Stack。在 Kibana 中我们创建一个 Discover 页面筛选trace_id: 0HMEF...就能看到这条请求从进入适配层、到查 SQL、到返回的完整时间轴。我们甚至用 Kibana 的 Lens 功能画出“各服务平均耗时”饼图发现 70% 的延迟来自 SQL Server 的磁盘 I/O从而推动 DBA 加了 SSD 缓存。没有 OpenTelemetry一样能做可观测关键是日志的结构化和 Trace ID 的贯穿。3.5 性能压测如何用 200 并发测出适配层的“真实心跳”压测不是为了刷高 QPS而是为了找到系统的“呼吸节奏”。我们用 JMeter 对适配层做阶梯式压测但指标不是吞吐量而是三个黄金比例SQL Server 连接池占用率 ≤ 70%监控sys.dm_exec_sessions中status running的会话数除以连接池最大值我们设为 100。一旦超过 70%说明数据库成为瓶颈必须优化查询或加索引。HTTP 线程池等待队列长度 ≤ 5在 Windows Performance Monitor 中添加计数器.NET CLR Networking 4.0.0.0\ThreadPool\Work Item Queue Length。如果持续 5说明适配层的 CPU 或 I/O 处理不过来需要增加服务器或优化代码。P95 延迟 ≤ 300ms这是 MCP 的硬性 SLA。我们设定 JMeter 的 Thread Group 为Ramp-up Period 60 秒Target Concurrency 200Loop Count 1000。跑完后看 Aggregate Report 中的 95% Line。如果 300ms就逐层排查是网络延迟是 SQL 查询慢还是 JSON 序列化耗时我们曾发现一个DateTime字段序列化成 ISO 8601 字符串比序列化成 Unix Timestamp 慢 15ms仅此一项就让 P95 从 280ms 升到 310ms。于是我们全局配置 JSON.NET 使用 Unix 时间戳格式问题解决。压测必须在准生产环境做数据库用真实数据量我们用 SQL Server 的 Database Tuning Advisor 生成 1:1 的测试数据网络走真实内网。在测试机上跑毫无意义。3.6 安全加固适配层的“四道门禁”防住 99% 的初级攻击适配层是新旧系统的交界点也是攻击面最大的地方。我们设置了四道门禁第一道输入白名单。所有 HTTP 请求的 Query String 和 Body必须符合预定义的 JSON Schema。我们用 Swashbuckle 生成 OpenAPI 文档再用Microsoft.AspNetCore.Mvc.NewtonsoftJson的JsonSerializerSettings配置ContractResolver强制只反序列化 Schema 中定义的字段。任何额外字段如{order_id: 123, hack_payload: script...}会被静默丢弃不会进业务逻辑。第二道SQL 注入免疫。绝不拼接 SQL。所有参数无论来自 URL、Body 还是 Header一律用SqlParameter。我们甚至写了一个 Roslyn Analyzer扫描所有SqlCommand构造如果发现command.CommandText $ AND id {id}这样的代码编译直接失败。第三道输出内容安全策略CSP。适配层返回的 JSONHeader 中强制加入Content-Security-Policy: default-src none;。这能阻止任何 XSS 攻击者利用返回的 JSON 数据执行脚本。第四道速率限制。用AspNetCoreRateLimit库为每个sub即域用户名设置每分钟 60 次调用限额。配置如下services.ConfigureIpRateLimitOptions(options { options.GeneralRules new ListRateLimitRule { new RateLimitRule { Endpoint *, Period 1m, Limit 60, // Key 是从 JWT 中提取的 sub KeyResolveStrategy context context.User?.Claims.FirstOrDefault(c c.Type sub)?.Value ?? anonymous } }; });这四道门禁让我们在渗透测试中面对 Burp Suite 的全自动扫描0 个高危漏洞。安全不是功能是设计起点。3.7 部署与发布如何在 Windows Server 2016 上用 5 分钟完成适配层上线旧系统跑在 Windows Server 2016这意味着你不能用 Docker Compose 或 Kubernetes。我们的部署方案是“Windows Service PowerShell 自动化”稳定得像 Windows Update。打包用dotnet publish -c Release -r win-x64 --self-contained true生成一个包含所有依赖的独立文件夹。大小约 120MB但胜在绝对可靠不依赖服务器上的 .NET Runtime 版本。安装写一个install.ps1脚本# 检查端口是否被占用 if (Get-NetTCPConnection -LocalPort 5001 -ErrorAction SilentlyContinue) { Write-Error 端口 5001 已被占用 exit 1 } # 创建服务 New-Service -Name MCP-Adapter -BinaryPathName C:\mcp-adapter\MCP.Adapter.exe --urls http://*:5001 -StartupType Automatic # 启动服务 Start-Service MCP-Adapter # 检查健康 $health Invoke-RestMethod http://localhost:5001/health if ($health.status -ne Healthy) { throw 服务健康检查失败 } Write-Host MCP 适配层安装成功回滚写一个rollback.ps1停止服务删除文件夹卸载服务三行命令。发布流程开发机上dotnet publish→ 用 WinSCP 上传到服务器C:\mcp-adapter-new→ 运行rollback.ps1→ 运行install.ps1指向新路径 → 验证/health和/swagger。全程 5 分钟且可一键回滚。我们坚持“发布即部署”拒绝任何手工改配置、拷文件的操作。这保证了每次发布的可重复性和可审计性。4. 实操过程从零搭建 MCP 适配层的完整流水线4.1 环境准备三台服务器构建最小可行 MCP 生态你不需要一个庞大的云平台。一个真实的、可落地的 MCP 生态只需要三台物理/虚拟机全部运行 Windows Server 2016它们构成了一个闭环Server A旧系统宿主IP10.1.1.10运行着 SQL Server 2012 和 ASP.NET WebForms 应用。这是你的“遗产”不做任何改动。Server BMCP ServerIP10.1.1.20安装 Windows Server 2016 Datacenter部署一个基于 .NET 6 的 MCP Server我们用开源的mcp-server-dotnet已 fork 并修复了 Windows 兼容性 Bug。它负责能力注册、意图路由、Agent 编排、Token 管理。内存 32GBCPU 8 核显卡非必需除非跑本地大模型。Server C适配层宿主IP10.1.1.30同样 Windows Server 2016部署我们刚刚讲完的适配层服务。它是 Server A 和 Server B 的“翻译官”也是唯一的代码变更点。网络配置是关键。三台服务器必须在同一内网 VLAN且防火墙开放必要端口Server B 的5000端口MCP Server HTTP API对 Server C 开放Server C 的5001端口适配层 API对 Server B 开放Server C 的1433端口SQL Server对 Server A 开放注意是 Server C 主动连 Server A不是反向。我们不用任何 DNS全部用 IP 地址硬编码在配置文件中杜绝域名解析失败导致的雪崩。appsettings.json在 Server C 上长这样{ McpServerUrl: http://10.1.1.20:5000, LegacySqlServer: { ConnectionString: Server10.1.1.10;DatabaseLegacyMIS;User Idmcp_reader;Password***; }, Jwt: { Issuer: https://mcp.corp, Audience: mcp-adapter, Key: your-32-byte-aes-key-here } }这种“IP 直连 硬编码”的土办法在旧系统环境中比任何 fancy 的服务发现都可靠。4.2 能力注册如何让 MCP Server “认识”你的第一个旧系统能力MCP 的灵魂是“能力可发现”。你的适配层写好了/api/orders/{id}/status这个接口但 MCP Server 不知道它的存在更不知道它能干什么。注册就是给这个接口办一张“数字身份证”。我们用 MCP Server 提供的/v1/capabilities/register端点。在 Server C 上写一个register-capabilities.ps1脚本# 读取能力描述文件 $capability Get-Content C:\mcp-adapter\capabilities\order-status.json | ConvertFrom-Json # 构造注册请求体 $body { name $capability.name description $capability.description endpoint http://10.1.1.30:5001/api/v1/orders/{id}/status method GET input_schema $capability.input_schema output_schema $capability.output_schema health_check http://10.1.1.30:5001/health tags (order, legacy) } | ConvertTo-Json -Depth 10 # 发送注册请求 Invoke-RestMethod -Uri http://10.1.1.20:5000/v1/capabilities/register -Method Post -Headers {Content-Typeapplication/json} -Body $bodyorder-status.json文件内容如下它是一个标准的 OpenAPI 3.0 片段{ name: get_order_status, description: 获取指定订单的当前状态及历史流转记录, input_schema: { type: object, properties: { id: { type: string, description: 订单编号格式为 ORD-YYYYMMDD-XXXXX } }, required: [id] }, output_schema: { type: object, properties: { order_id: {type: string}, status: {type: string, enum: [created, paid, shipped, delivered, cancelled]}, status_history: { type: array, items: { type: object, properties: { status: {type: string}, timestamp: {type: string, format: date-time}, operator: {type: string} } } } } } }执行脚本后MCP Server 的管理后台http://10.1.1.20:5000/admin就会出现这个能力卡片显示其健康状态、调用统计、SLA 达标率。更重要的是MCP 的意图识别引擎会自动学习这个能力的描述文本当用户说“查订单 ORD-20240520-001 的状态”它就能 100% 路由到这个接口。注册不是一次性的我们把它做成 CI/CD 的一部分每次适配层代码提交Jenkins 就自动运行这个脚本确保 MCP Server 的能力目录永远与代码同步。4.3 MCP Server 配置如何用 10 行 YAML定制你的 AI 工作流MCP Server 不是黑盒它的行为由一个mcp-config.yaml文件驱动。这个文件定义了“当用户说一句话系统该如何思考”。我们以“智能工单推荐”为例展示如何用最少的配置实现最复杂的 AI 流程。# mcp-config.yaml agents: - name: workorder-recommender description: 根据设备历史、传感器数据和备件库存推荐最优维修方案 # 第一步意图识别用轻量模型 intent_model: type: phi3 endpoint: http://10.1.1.20:5002/v1/chat/completions # 第二步工具调用编排 tools: - name: get_device_history capability: get_device_history # 这个能力已注册到 MCP description: 获取指定设备的最近30天维修记录 - name: get_sensor_data capability: get_sensor_data description: 获取指定设备的最近24小时传感器读数温度、振动 - name: check_spare_parts capability: check_spare
返回列表