在当今数据驱动的世界中,如何高效、安全地访问和利用分散在不同数据库中的信息,是许多技术团队面临的挑战。本文详细解析一个基于MCP(Model Context Protocol)框架构建的项目。MCP是Anthropic于2024年11月推出的一个开放标准、开源的框架,旨在标准化大型语言模型等人工智能系统与外部工具、系统和数据源集成与共享数据的方式。本项目通过巧妙的客户端-服务器架构,结合强大的大型语言模型(LLM),为用户提供了一个通过自然语言与复杂数据库交互的智能查询引擎。
项目愿景
MCP项目的核心目标是解决一个普遍存在的问题:业务人员或数据分析师需要从专业的数据库中获取信息,但他们往往不具备编写复杂SQL查询的能力。通过实现Model Context Protocol,本项目将用户的自然语言问题转化为精确的数据库查询,并将结果以清晰、人性化的方式呈现出来,极大地降低了数据访问的门槛。
技术栈概览
在深入架构之前,我们先看一下项目所依赖的关键技术:
- 后端框架:
mcp(Model Context Protocol) - 本项目基于Anthropic推出的开源标准框架MCP。它规范了AI模型与外部工具交互的方式,使得后端服务的“工具化”和前端的AI集成变得无缝且标准化。 - 数据库交互:
asyncpg(用于与PostgreSQL进行异步通信) - 环境配置:
python-dotenv(管理环境变量) - AI集成:
openai(与大型语言模型API交互) - 数据库: PostgreSQL
这种技术选型体现了对异步性能、安全配置和前沿AI能力的重视。
架构设计:三层分离的艺术
MCP项目采用了经典且高效的三层分离架构:配置层、数据访问层和应用服务层,并辅以一个智能客户端。
1 | graph TB |
架构层次详解:
1. 配置层 (config.py)
- 职责: 环境变量管理、安全配置
- 关键文件:
.env+config.py - 安全特性: 敏感信息与代码分离
2. 数据访问层 (database.py)
- 核心组件:
DatabaseManager+ 异步连接池 - 功能: SQL抽象、数据序列化、连接管理
- 性能: asyncpg异步处理并发请求
3. 应用服务层 (mcp_server.py)
- 框架: Model Context Protocol (MCP)
- 工具定义: `@mcp.tool()`装饰器
- 业务封装: 复杂查询逻辑透明化
4. 智能客户端 (mcp_client.py)
- AI集成: LLM动态函数调用
- 决策流程: 自然语言→工具选择→参数生成
- 用户体验: 结果人性化展示
(这是一个根据代码结构推断的架构示意图)
1. 配置层 (config.py)
一个健壮的应用始于灵活的配置。MCP项目将所有敏感和环境相关的配置(如数据库地址、用户名、密码)都存储在.env文件中,并通过config.py进行加载。
- 安全性: 将凭证与代码分离,避免了敏感信息泄露。
- 灵活性: 在不同环境(开发、测试、生产)中部署时,只需更改
.env文件,无需修改任何代码。 - 集中管理: 所有配置项集中在一个文件中,方便维护。
2. 数据访问层 (database.py)
这是连接应用逻辑与物理数据库的桥梁。该层完全封装了数据库的连接、查询和数据转换的复杂性。
- 连接管理: 使用
asyncpg创建异步连接池,高效地处理并发请求,确保了服务器的高性能。 - 抽象查询:
DatabaseManager类提供了一系列抽象化的查询方法,例如query_six_table。应用服务层只需调用这些方法,传入表名和过滤条件,而无需关心底层的SQL拼接和执行细节。 - 数据序列化: 包含一个精巧的转换函数
convert_data_for_json,它可以自动将数据库返回的特殊类型(如datetime,Decimal)转换为JSON兼容的格式,解决了数据在不同层之间传递时的常见问题。 - 数据库
demo: 在该项目中,核心业务数据存储在一个名为demo的PostgreSQL数据库中。其中包含了多个关键表,例如:demo_company: 存储企业的基本信息。demo_checkrecord: 记录了历史检查数据。demo_licence: 管理许可证信息。
(为保护隐私,此处仅列举部分示例表)
3. 应用服务层 (mcp_server.py)
这是整个系统的“大脑”,负责处理客户端请求,并定义可供调用的“工具”(Tools)。
- Model Context Protocol (MCP) 框架: 服务器利用
mcp框架,通过简单的装饰器(如`@mcp.tool()`)就能将一个异步函数发布为一个可通过API调用的工具。这极大地简化了API的开发。 - 工具化接口: 每个查询功能都被封装成一个独立的“工具”,例如
query_company或query_checkrecord。每个工具都有明确的输入参数和输出结构,这为后续与LLM的集成奠定了基础。 - 业务逻辑封装: 复杂的查询逻辑被封装在工具函数内部。例如,当按公司名称查询检查记录时,服务器会先在
demo_company表中查找公司ID,再用ID去demo_checkrecord表中进行精确查询,并将公司名关联到最终结果中。这种封装对客户端是完全透明的。
4. 智能客户端 (mcp_client.py)
客户端是用户与MCP系统交互的门户,也是AI能力的核心体现。
- LLM集成: 客户端的核心是一个工作流:它首先从服务器获取所有可用的工具列表及其定义。
- 动态函数调用: 当用户输入一个问题(例如“查询xx公司2023年以来的检查记录”)时,客户端会将问题和工具列表一起发送给大型语言模型(LLM)。
- 智能决策: LLM会像一个聪明的“调度员”,根据用户的问题意图,从工具列表中选择最合适的一个或多个工具,并生成调用所需的参数(例如,它会将“xx公司”识别为
company_name参数,将“2023年来以来”解析为check_date1参数)。 - 结果润色: 在获取到服务器返回的原始JSON数据后,客户端会再次调用LLM,要求它将结构化的数据“翻译”成一段通顺、易于理解的中文报告,从而完成从自然语言输入到自然语言输出的闭环。
工作流程:一次查询的奇妙 journey
- 用户在
mcp_client.py的命令行界面输入问题:“查询一下ABC制药公司的许可证信息”。 - 客户端将问题和从服务器获取的工具定义(如
query_licence工具)发送给LLM。 - LLM分析后决定调用
query_licence工具,并生成参数{"company_name": "ABC制药公司"}。 - 客户端通过MCP协议调用服务器上的
query_licence工具。 mcp_server.py接收请求,执行该工具函数。函数内部调用database.py中的方法,向demo数据库执行查询。- 服务器将查询结果(一个包含许可证信息的JSON对象)返回给客户端。
- 客户端收到JSON数据后,再次请求LLM,将数据和原始问题一并发送,要求其生成一份总结报告。
- LLM返回一段人性化的文本,例如:“为您找到了ABC制药公司的许可证信息如下:…”,并由客户端最终呈现给用户。
结论
本项目不仅仅是一个数据库查询工具,它更是一个遵循MCP(Model Context Protocol)开放标准,将模块化后端服务、人工智能和用户体验无缝结合的优秀范例。通过采用MCP这样的标准化框架,项目实现了高度的可维护性和互操作性。未来,无论是增加新的数据源,还是集成更强大的AI模型,都可以在现有基础上轻松完成。它向我们展示了如何利用现代技术栈,构建出既强大又易于使用的智能数据应用。