最近我们完成了一次系统协议迁移,把旧的自定义AI工具协议,迁移到了标准的MCP(Model Context Protocol)协议。

整个迁移过程持续了一个月,遇到了很多挑战,也积累了不少经验。这篇文章,我想分享一下这次迁移的实战过程,包括MCP协议的介绍、迁移策略、遇到的问题、解决方案,以及最终的效果。

什么是MCP协议

先简单说说什么是MCP协议。

MCP(Model Context Protocol)是Anthropic在2024年推出的一个开放协议,用于连接AI模型和外部工具、数据源。它的目标是建立一个标准化的协议,让AI模型能够统一地访问各种外部资源,比如文件系统、数据库、API、第三方服务等。

在MCP出现之前,每个AI应用都有自己的工具调用方式。OpenAI有Function Calling,Anthropic有Tool Use,各家的实现都不一样。如果你想让你的工具同时支持多个AI模型,就需要为每个模型写一套适配代码,维护成本很高。

MCP的出现,就是为了解决这个问题。它定义了一套标准的协议,包括:

  • 工具(Tools):AI模型可以调用的函数或操作
  • 资源(Resources):AI模型可以读取的数据或文件
  • 提示词模板(Prompts):可复用的提示词模板
  • 采样(Sampling):AI模型生成文本的能力

只要你的工具实现了MCP协议,任何支持MCP的AI模型都可以直接使用,不需要额外的适配。这大大降低了工具开发和维护的成本。

MCP协议采用客户端-服务器架构。MCP服务器负责提供工具和资源,MCP客户端(通常是AI应用)负责连接服务器并调用工具。通信方式支持STDIO(标准输入输出)和HTTP/SSE(服务器发送事件)两种。

为什么要迁移

我们的旧系统是两年前搭建的,用的是自定义的工具调用协议。当时MCP还没出来,我们自己设计了一套JSON-RPC风格的协议,来连接AI模型和外部工具。

这套自定义协议在当时够用,但随着业务的发展,问题越来越多。

第一个问题是兼容性差。我们的自定义协议只支持我们自己的AI应用。如果想接入其他AI平台,比如Claude、ChatGPT、Cursor等,就需要写专门的适配器。每接入一个新平台,就要写一套新的适配代码,维护成本很高。

第二个问题是生态不完善。自定义协议没有社区支持,所有的工具和客户端都要自己开发。而MCP协议有丰富的生态,已经有很多现成的MCP服务器和客户端,可以直接使用。

第三个问题是扩展性不足。我们的自定义协议在设计的时候,没有考虑到很多高级功能,比如资源订阅、提示词模板、进度通知等。随着业务的发展,这些功能越来越需要,但在旧协议上实现起来很麻烦。

第四个问题是团队协作困难。因为是自定义协议,新成员加入的时候,需要花很多时间学习协议细节。而MCP是标准协议,有完善的文档和社区资源,新人上手很快。

基于这些问题,我们决定把旧系统迁移到MCP协议。

迁移策略

迁移是一个大工程,不能一蹴而就。我们制定了详细的迁移策略。

第一个策略是渐进式迁移。不搞一次性切换,而是分模块、分阶段迁移。先迁移非核心的工具,再迁移核心工具;先迁移流量小的服务,再迁移流量大的服务。这样可以降低风险,出问题也能及时回滚。

第二个策略是双协议并行。在迁移过程中,旧协议和MCP协议同时运行。旧的客户端继续用旧协议,新的客户端用MCP协议。等所有客户端都迁移到MCP之后,再下线旧协议。这样可以保证迁移过程中服务不中断。

第三个策略是自动化测试。迁移过程中,我们写了大量的自动化测试,确保迁移之后功能和之前一致。每个工具迁移完成之后,都要跑一遍完整的测试,确保输入输出和旧系统一致。

第四个策略是文档先行。在迁移之前,我们先把MCP协议的文档和规范整理好,让团队所有人都理解协议的细节。这样开发的时候就有统一的标准,不会出现各写各的情况。

第一阶段:MCP服务器搭建

迁移的第一阶段,是搭建MCP服务器框架。

我们用的是官方的Python SDK来搭建MCP服务器。SDK提供了很方便的装饰器,可以快速定义工具、资源和提示词模板。

搭建过程中,我们做了以下几件事情:

第一件事是,定义工具的标准格式。每个工具都需要有名称、描述、参数schema。我们按照MCP协议的规范,把旧系统中的所有工具都重新定义了一遍。参数schema用JSON Schema来描述,这样AI模型可以自动理解参数的格式和要求。

第二件事是,实现工具的执行逻辑。大部分工具的执行逻辑和旧系统是一样的,只是接口格式变了。我们把旧系统的业务逻辑复用过来,只需要在外面包一层MCP协议的适配层。

第三件事是,实现资源访问。MCP协议的资源功能,可以让AI模型读取文件、数据库等数据。我们把旧系统中的数据访问接口,改造成了MCP资源。这样AI模型可以通过标准的资源接口来读取数据,不需要专门的工具。

第四件事是,实现提示词模板。MCP协议支持提示词模板,可以把常用的提示词封装成模板,AI模型可以直接调用。我们把旧系统中常用的提示词整理成了模板,方便复用。

MCP服务器搭建完成之后,我们用官方的测试客户端做了验证,确保所有工具和资源都能正常工作。

第二阶段:客户端迁移

第二阶段,是把AI客户端从旧协议迁移到MCP协议。

我们的AI客户端是基于LangChain开发的。LangChain已经支持MCP协议,可以很方便地连接MCP服务器。

迁移过程中,我们做了以下几件事情:

第一件事是,替换工具调用层。旧的客户端用的是自定义的工具调用类,我们把它替换成了LangChain的MCP工具类。这样,客户端就可以通过MCP协议来调用服务器上的工具了。

第二件事是,处理流式响应。MCP协议支持流式响应,工具的执行过程可以实时返回进度。我们利用这个特性,优化了用户体验。以前用户要等工具执行完才能看到结果,现在可以实时看到执行进度,等待的焦虑感降低了很多。

第三件事是,错误处理。MCP协议有标准的错误码和错误信息格式。我们按照协议规范,实现了统一的错误处理。当工具执行出错的时候,客户端可以根据错误码做出相应的处理,比如重试、提示用户、记录日志等。

第四件事是,性能优化。MCP协议的HTTP/SSE通信方式,比我们旧的自定义协议性能更好。我们还做了连接池、请求合并等优化,进一步提升了响应速度。

客户端迁移完成之后,我们做了对比测试,确保迁移之后的功能和性能都不低于旧系统。

第三阶段:工具迁移

第三阶段,是把旧系统中的工具逐个迁移到MCP服务器。

我们总共有五十多个工具,按照重要性和复杂度,分成了三批迁移。

第一批是简单工具,比如计算器、单位转换、日期处理等。这些工具逻辑简单,迁移起来很快,也用来验证迁移流程是否顺畅。

第二批是中等复杂度的工具,比如数据库查询、文件操作、API调用等。这些工具涉及到外部资源,需要处理连接、认证、错误等问题,迁移难度稍大。

第三批是复杂工具,比如代码执行、数据分析、工作流编排等。这些工具逻辑复杂,涉及到多个步骤和状态管理,迁移难度最大。

每个工具迁移的流程是:

  1. 分析旧工具的输入输出
  2. 按照MCP规范定义工具的schema
  3. 实现工具的执行逻辑(复用旧代码)
  4. 编写自动化测试
  5. 在测试环境验证
  6. 灰度上线,观察运行情况
  7. 全量上线

在迁移过程中,我们遇到了一些问题。

第一个问题是,参数格式不兼容。旧系统的参数格式比较随意,有的用位置参数,有的用关键字参数,有的用JSON字符串。MCP协议要求参数必须是结构化的JSON对象。我们花了很多时间,把所有工具的参数都统一成了结构化的格式。

第二个问题是,长耗时工具的处理。有些工具执行时间很长,比如数据分析、代码执行等。MCP协议支持进度通知,我们利用这个特性,在工具执行过程中实时推送进度,让用户知道当前的状态。

第三个问题是,工具之间的依赖。有些工具需要调用其他工具的结果。在旧系统中,我们用的是自定义的依赖管理机制。迁移到MCP之后,我们改用了工作流编排的方式,把多个工具的调用组合成一个工作流,由客户端来协调执行。

第四阶段:数据迁移和验证

第四阶段,是数据迁移和全面验证。

虽然MCP协议主要是工具调用协议,但我们的旧系统中还有一些配置数据和历史数据需要迁移。

第一件事是,配置数据迁移。旧系统中的工具配置、权限设置、用户偏好等数据,我们都迁移到了新的MCP服务器中。迁移之后,做了全面的核对,确保数据一致。

第二件事是,历史数据对比。我们抽取了旧系统中最近一个月的请求记录,在新系统中重新执行一遍,对比输出结果。如果有不一致的地方,就分析原因,修复问题。

第三件事是,性能测试。我们对新系统做了全面的性能测试,包括响应时间、吞吐量、并发能力等。确保新系统的性能不低于旧系统,甚至更好。

第四件事是,安全审计。MCP协议涉及到工具调用和数据访问,安全很重要。我们做了全面的安全审计,包括权限控制、输入验证、数据加密、日志审计等,确保新系统的安全性。

第五阶段:全量切换和旧系统下线

最后一个阶段,是全量切换和旧系统下线。

我们用了灰度发布的方式,逐步把流量从旧系统切到新系统。

最开始只切10%的流量,观察新系统的运行情况。如果一切正常,就逐步增加流量比例:30%、50%、80%、100%。每个阶段都观察至少24小时,确保没有问题再继续。

在流量切换的过程中,我们做了详细的监控,包括:请求量、响应时间、错误率、工具调用成功率、资源利用率等。如果发现异常,立刻把流量切回旧系统,排查问题。

整个切换过程持续了一周。最终,100%的流量都切到了新系统,旧系统正式下线。

遇到的坑

在迁移过程中,我们遇到了不少坑,分享几个比较典型的。

第一个坑是,MCP SDK的版本兼容性。MCP协议是新协议,SDK更新很快,不同版本之间可能有不兼容的地方。我们在开发过程中,遇到过几次SDK升级导致代码不工作的情况。后来我们固定了SDK版本,并且在升级之前先做充分的测试。

第二个坑是,STDIO和HTTP的选择。MCP支持STDIO和HTTP两种通信方式。我们一开始用的是STDIO,因为简单。但在生产环境中,STDIO方式有很多限制,比如进程管理、日志收集、负载均衡都不方便。后来我们改成了HTTP/SSE方式,运维起来方便很多。

第三个坑是,工具描述的重要性。MCP协议中,工具的描述(description)非常重要,AI模型是根据描述来决定是否调用这个工具的。我们一开始写的描述太简单,导致AI模型经常调用错误的工具,或者不知道该调用哪个工具。后来我们花了很多时间优化工具描述,把每个工具的功能、参数、使用场景都写清楚,AI模型的调用准确率大大提升。

第四个坑是,大参数的处理。有些工具需要传入很大的参数,比如长文本、文件内容等。MCP协议对请求大小有限制,直接传大参数会失败。我们的解决方案是,大参数通过资源的方式传递,工具只接收资源的URI,执行的时候再去读取资源内容。

第五个坑是,错误信息的可读性。MCP协议的错误信息是结构化的,但AI模型有时候不能很好地理解错误信息。我们在错误信息中加入了人类可读的描述,并且给出了建议的解决方案,这样AI模型可以根据错误信息自动调整,而不是直接失败。

迁移效果

迁移完成之后,效果非常明显。

开发效率方面:新工具的开发时间从平均三天缩短到了一天。因为有了标准的协议和SDK,开发人员只需要关注业务逻辑,不需要处理协议细节。

兼容性方面:现在我们的工具可以同时支持多个AI平台,包括Claude、ChatGPT、Cursor等。不需要为每个平台写适配器,维护成本大大降低。

生态方面:我们可以直接使用社区提供的MCP服务器,比如文件系统、数据库、GitHub等,不需要自己开发。这大大丰富了我们的工具生态。

性能方面:新系统的响应时间比旧系统降低了20%,吞吐量提升了50%。主要得益于MCP协议的高效通信和连接池优化。

可维护性方面:代码量减少了30%,因为很多通用的协议处理逻辑都由SDK负责了。新人上手时间也从两周缩短到了三天。

总的来说,这次迁移是成功的。虽然过程很辛苦,遇到了很多问题,但最终的结果值得这些付出。

一些经验总结

最后,总结一些经验。

第一,迁移之前要充分理解新协议。MCP协议虽然不复杂,但有很多细节需要注意。在迁移之前,要仔细阅读官方文档,理解协议的设计思想和最佳实践。

第二,不要急于求成。迁移是一个渐进的过程,要分阶段进行。每个阶段都要有明确的目标和验证标准,确保质量。

第三,自动化测试是关键。迁移过程中,最担心的就是功能不一致。有了完善的自动化测试,就能放心地迁移,出了问题也能及时发现。

第四,重视文档和工具描述。MCP协议中,工具的描述直接影响AI模型的使用效果。要花时间写好每个工具的描述,确保AI模型能正确理解和使用。

第五,关注社区动态。MCP协议还在快速发展中,新功能和新工具不断出现。要关注社区动态,及时跟进最新的进展。

写在最后

MCP协议是一个很有前景的标准,它为AI模型和外部工具的连接提供了统一的解决方案。

如果你也在使用自定义的工具调用协议,或者正在构建AI应用的工具生态,我建议你考虑迁移到MCP协议。虽然迁移过程需要一些投入,但长期来看,收益是很大的。

希望这篇文章能给正在考虑MCP迁移的朋友一些参考。如果你有迁移的经验,欢迎在评论区交流。