第四章: 服务集成抽象
Chapter 4: 服务集成抽象
🌟 从上一章到本章
在第三章:传输机制中,我们学习了如何通过STDIO和SSE协议让LLM与不同服务器通信。现在想象这样的场景:你的AI助手需要同时操作本地文件和云端数据库。这时问题来了——如何让LLM像操作一个工具一样协调多个服务器?
本章将介绍服务集成抽象,它就像“交响乐指挥”,让多个服务器像合奏一样协同工作,为LLM提供无缝的工具使用体验!
🎯 中心用例:AI助手同时管理文件和数据
假设你要开发一个AI助手,需要以下功能:
- 读取本地PDF合同(通过文件系统服务器)
- 查询云端数据库中的订单记录(通过Third-Party服务器)
- 生成包含两者的报告
- 挑战:两个服务器可能使用不同协议、不同参数,如何让LLM统一调用?
- 目标:让LLM像使用一个工具一样操作多个服务
🔍 服务集成抽象的三个核心概念
通过以下三层结构,我们将复杂服务抽象成简单接口:
1. 统一接口层(Unified Interface)
- 类比:把不同语言的菜单翻译成同一语言
- 功能:将不同服务器的API参数、响应格式标准化
- 示例:
# 调用文件系统和数据库的统一方式 contract = mcp.invoke_tool("文件系统", "读取文件", {"路径": "/合同/2023合同.pdf"}) 订单数据 = mcp.invoke_tool("数据库", "查询", {"SQL": "SELECT * FROM 订单 WHERE 客户='张三'"})
2. 服务注册表(Service Registry)
- 类比:电话簿,记录所有可用服务的联系方式
- 功能:记录服务器名称、启动命令、参数配置
- 示例配置:
{"服务列表": {"文件系统": {"启动命令": "npx @modelcontextprotocol/server-filesystem","参数": ["/安全目录"]},"数据库": {"启动命令": "npx @aws/server-postgres","传输协议": "sse"}} }
3. 抽象逻辑层(Abstraction Logic)
- 类比:智能翻译官,自动处理不同协议和数据格式
- 功能:
- 根据工具名称查找对应服务器
- 将LLM的请求转换为服务器特定格式
- 将服务器响应转换为LLM可理解的格式
🛠️ 如何用抽象层解决用例?
步骤1:配置服务注册表
在mcp_config.json
中注册两个服务器:
{"mcpServers": {"文件系统": {"command": "npx","args": ["@modelcontextprotocol/server-filesystem", "/data"]},"数据库": {"command": "npx","args": ["@aws/server-postgres"],"transport": "sse"}}
}
步骤2:编写统一调用代码
LLM通过抽象层调用两个服务:
# 读取文件并查询数据库
合同内容 = mcp.invoke("文件系统", "读取文件", {"路径": "合同.pdf"})
订单数据 = mcp.invoke("数据库", "执行查询", {"SQL": "SELECT * FROM 订单"})# 生成报告
报告 = 生成报告(合同内容, 订单数据)
🕵️ 内部实现揭秘
时序图:抽象层协调两个服务
关键代码片段(简化版)
统一接口层实现
class MCP抽象层:def invoke(self, 服务名, 工具名, 参数):# 步骤1:查找服务配置服务配置 = 注册表[服务名]# 步骤2:启动/连接服务器if 服务配置["transport"] == "stdio":响应 = 启动并执行STDIO命令(...)else:响应 = 通过SSE发送请求(...)# 步骤3:格式化响应return self.标准化响应(响应)
💡 总结与展望
本章我们学到:
- 服务集成抽象的三层结构:统一接口、注册表、逻辑层
- 如何让多个服务器协同工作:通过配置和服务调用
- 标准化带来的好处:LLM无需关心底层差异
接下来,我们将深入探索工具抽象框架,学习如何通过框架快速构建自己的MCP服务器——例如用几行代码创建数据库查询工具!
🚀 尝试将本地文件系统和云端API整合到一个项目中,让AI助手同时操作两者!