news 2026/6/10 6:49:46

深入理解 MCP 协议:从底层通信到 MySQL 实战接入

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
深入理解 MCP 协议:从底层通信到 MySQL 实战接入

深入理解 MCP 协议:从底层通信到 MySQL 实战接入

最近在做一个课设,想让 AI 能直接查询我本地的 MySQL 数据库。网上翻了一圈,全是"MCP 是 AI 的 USB-C 接口"这类比喻,看完还是不知道怎么用。花了三天踩坑,把底层逻辑搞清楚了,写下来给自己留个记录。


先说结论:MCP 解决的是一个被忽视已久的根本问题

为什么需要 MCP?

在 MCP 出现之前,如果你想让 ChatGPT 或者任何 LLM 能查你的数据库,你得这么做:

  1. 自己写一套 Function Calling 的接口定义
  2. 把数据库操作封装成函数
  3. 把函数 schema 塞进 prompt
  4. 解析模型返回的 JSON,手动执行

每接入一个新工具,就要重新写一套。换个模型(比如从 GPT 换成 DeepSeek),又要重新适配。

这就好比家里每个电器都有一个独立遥控器,需要逐个编写接口;而 MCP 则像全屋智能中枢,通过统一协议接入所有设备。

听起来是个比喻,但工程上的含义很实在:写一次 MCP Server,任何支持 MCP 的 AI 客户端都能直接用。


MCP 的三层架构,用人话说清楚

MCP 的核心思想是将 LLM 的核心推理能力与外部功能的实现细节解耦,通过定义清晰的主机(Host)、客户端(Client)和服务器(Server)架构实现灵活、可扩展且安全的 LLM 应用生态。

Host / Client / Server,三个词一出来,大多数人就晕了。我当时也是。后来我用一个具体场景理解了:

你(用户) ↓ 提问 Claude Desktop(Host,宿主应用) ↓ 转发请求 MCP Client(内嵌在 Host 里,负责通信) ↓ 标准化协议 MCP Server(你自己写的,封装了数据库/文件/API) ↓ 执行 MySQL / 本地文件 / 第三方 API

关键点:MCP Server 是你来写的,是把你的工具"翻译"成 AI 能懂的标准接口。

Host 是 Claude Desktop、Cursor 这类应用,它们已经帮你实现了 MCP Client,你不需要管。你只需要写 Server,告诉 AI “我有哪些工具、每个工具怎么用”。


底层通信:JSON-RPC 2.0,没有那么神秘

我踩的第一个坑就是以为 MCP 是某种复杂的私有协议。

其实不是。MCP 协议使用 JSON-RPC 2.0 作为消息传输格式。

JSON-RPC 2.0 是一个极简的远程调用协议,一条请求长这样:

{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"query_database","arguments":{"sql":"SELECT * FROM users WHERE id = 1"}}}

Server 返回:

{"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"[{\"id\": 1, \"name\": \"张三\", \"email\": \"zhangsan@example.com\"}]"}]}}

就这么简单。AI 说"我要调用 query_database,参数是这条 SQL",Server 执行完把结果返回去,AI 再把结果转成自然语言告诉你。

理解了这一层,后面的东西就都清晰了。


我踩的坑:传输方式的选择

MCP 支持两种传输方式,这里是我卡了最久的地方。

1. stdio(标准输入输出)

Server 作为一个本地子进程运行,Host 通过标准输入输出和它通信。

# Server 启动方式if__name__=="__main__":importasynciofrommcp.server.stdioimportstdio_server asyncio.run(stdio_server(server))

优点:配置简单,本地开发首选。
缺点:只能本地用,无法远程访问。

2. HTTP + SSE(Streamable HTTP)

新的传输规范中,服务端作为独立进程运行,支持多客户端连接,基于 HTTP POST/GET 请求实现,可选用服务器推送事件(SSE)实现多消息流式传输。

# Server 以 HTTP 方式启动if__name__=="__main__":importuvicornfrommcp.server.fastmcpimportFastMCP app=FastMCP("my-server")uvicorn.run(app.get_asgi_app(),host="0.0.0.0",port=8000)

我踩的坑:我一开始用的是老版本的 SSE 实现,结果发现协议已经改了,连接一直断。后来看了官方 changelog 才知道,2025年初协议把传输层做了破坏性更新,旧的 SSE 方案已经废弃,要用新的 Streamable HTTP。

教训:用 MCP 之前先确认 SDK 版本,pip show mcp看一眼,0.9.0 以上才支持新传输协议。


写一个真实可用的 MCP Server(查 MySQL)

说了这么多,来看实际代码。这是我课设里用的版本,精简过,核心逻辑都在。

环境准备

pipinstallmcp pymysql

完整代码

importpymysqlimportjsonfrommcp.server.fastmcpimportFastMCP# 初始化 MCP Servermcp=FastMCP("mysql-assistant")# 数据库配置DB_CONFIG={"host":"localhost","port":3306,"user":"root","password":"your_password","database":"your_db","charset":"utf8mb4"}defget_connection():returnpymysql.connect(**DB_CONFIG)# ========== 定义工具 ==========@mcp.tool()defquery_data(sql:str)->str:""" 执行 SELECT 查询语句,返回查询结果。 只允许 SELECT,不允许增删改操作。 Args: sql: 要执行的 SELECT SQL 语句 Returns: JSON 格式的查询结果 """# 安全校验:只允许 SELECTsql_upper=sql.strip().upper()ifnotsql_upper.startswith("SELECT"):return"错误:只允许执行 SELECT 查询语句"try:conn=get_connection()cursor=conn.cursor(pymysql.cursors.DictCursor)cursor.execute(sql)results=cursor.fetchall()cursor.close()conn.close()ifnotresults:return"查询结果为空"returnjson.dumps(results,ensure_ascii=False,default=str)exceptpymysql.Errorase:returnf"数据库错误:{str(e)}"@mcp.tool()defget_table_schema(table_name:str)->str:""" 获取指定数据表的字段结构信息。 在写 SQL 之前先调用这个工具了解表结构。 Args: table_name: 表名 Returns: 表的字段名、类型、是否为空等信息 """try:conn=get_connection()cursor=conn.cursor()cursor.execute(f"DESCRIBE `{table_name}`")columns=cursor.fetchall()cursor.close()conn.close()result=f"表{table_name}的结构:\n"result+="字段名 | 类型 | 允许空 | 键 | 默认值\n"result+="-"*60+"\n"forcolincolumns:result+=" | ".join(str(c)forcincol)+"\n"returnresultexceptpymysql.Errorase:returnf"获取表结构失败:{str(e)}"@mcp.tool()deflist_tables()->str:""" 列出当前数据库中所有的表名。 不知道有哪些表时,先调用这个。 """try:conn=get_connection()cursor=conn.cursor()cursor.execute("SHOW TABLES")tables=[row[0]forrowincursor.fetchall()]cursor.close()conn.close()return"数据库中的表:\n"+"\n".join(f"-{t}"fortintables)exceptpymysql.Errorase:returnf"获取表列表失败:{str(e)}"# ========== 启动 ==========if__name__=="__main__":mcp.run()# 默认 stdio 模式,用于本地 Claude Desktop

配置到 Claude Desktop

claude_desktop_config.json里加上:

{"mcpServers":{"mysql-assistant":{"command":"python","args":["/绝对路径/mysql_mcp_server.py"]}}}

重启 Claude Desktop,然后直接问它:

“帮我看看 users 表里注册时间最早的 10 个用户”

它会自动调用list_tablesget_table_schemaquery_data,最后给你一个完整答案。不需要你写任何 SQL。


一个容易忽视的设计细节:工具描述比代码更重要

我刚开始写的时候,工具描述就一句话,结果 AI 经常调错工具或者传错参数。

后来我意识到:AI 是通过读你写的 docstring 来决定"该不该调用这个工具、怎么调用"的。描述越精确,AI 的行为越准确。

# ❌ 模糊的描述@mcp.tool()defquery(sql:str)->str:"""执行SQL"""...# ✅ 清晰的描述@mcp.tool()defquery_data(sql:str)->str:""" 执行 SELECT 查询语句,返回查询结果。 只允许 SELECT,不允许增删改操作。 在查询前请先用 get_table_schema 了解表结构,避免写出错误的字段名。 Args: sql: 完整的 SELECT SQL 语句,例如:SELECT * FROM users LIMIT 10 """...

这个细节在所有 MCP 教程里几乎没人提,但它直接决定了 Agent 的实际可用性。


MCP 和 Function Calling 的本质区别

有人会问:这和 OpenAI 的 Function Calling 有什么区别?

本质区别只有一个:Function Calling 是模型私有的,MCP 是跨模型的标准。

维度Function CallingMCP
标准化程度各家模型实现不同统一开放协议
复用性换模型要重写一次编写,到处使用
工具发现需要手动在 prompt 中声明Server 自动暴露工具列表
部署方式嵌入应用代码独立进程,可远程部署

OpenAI 于 2025 年 3 月 27 日宣布其 Agents SDK 已正式支持 MCP,这标志着该协议正式成为大模型与外部数据交互的行业标准。

连 OpenAI 都跟进了,这件事基本盖棺定论:MCP 会成为 AI 工具调用的基础设施标准,就像 HTTP 之于 Web。


最后说几句

MCP 本身不复杂,复杂的是周边生态还在快速变化——协议在更新、SDK 在迭代、各家客户端的支持程度也不一样。

我觉得现在学 MCP 最值的投资是:把"写 MCP Server"这个技能练熟。不管 AI 工具链怎么变,能给 LLM 快速接入各种数据源的人,在接下来几年会非常抢手。


有问题欢迎评论区讨论,如果帮到你了点个赞,我会继续更新这个系列。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 6:48:16

关于借用GitHub来实现自动更新的方法

最近在研究怎么让一个程序能自动检测更新,我有一个比较有意思的想法想分享一下,常规的自动更新方式,无非主要思路在于,程序持有者需要和远端服务器通信,判断当前应用版本号是否为最新,如若远端服务器返回否…

作者头像 李华
网站建设 2026/6/10 6:45:52

Codex 使用指南:从入门到高效协作,让 AI 真正参与开发流程

摘要Codex 不只是一个“帮你写代码”的工具,更像是一个可以理解项目、修改文件、运行命令、定位问题、补充测试和做代码审查的 AI 编程协作者。本文将从实际开发场景出发,介绍 Codex 的常见用法、提示词写法、协作流程以及避坑建议,帮助你更稳…

作者头像 李华
网站建设 2026/6/10 6:39:49

地图数据工程师的日常:如何为你的中国分省图数据选择并配置兰勃特投影(标准纬线25°/45°详解)

地图数据工程师的实战指南:中国分省图兰勃特投影配置详解当你第一次在GIS软件中看到"兰勃特等角圆锥投影"这个选项时,可能会被它复杂的参数设置界面吓到。作为处理中国省级行政区划地图数据的专业人士,选择正确的投影方式不仅关乎数…

作者头像 李华
网站建设 2026/6/10 6:38:50

Qt6实战:用QChart打造一个可交互的实时数据可视化工具(附完整源码)

Qt6实战:构建高性能实时数据可视化系统的工程化实践在工业控制、金融交易和物联网监测等领域,实时数据可视化一直是刚需场景。传统方案往往面临性能瓶颈和交互体验不佳的问题,而Qt6的QChart模块配合现代C特性,为开发者提供了构建高…

作者头像 李华