MCP从入门到实战:手把手给AI Agent插上通用工具接口
2026/9/8 20:01:52 网站建设 项目流程

先抛个引子:你是不是也见过这种场景?同一个AI编程助手,有的人拿它只能聊天翻译,有的人却能指挥它直接查数据库、改Figma设计稿、调浏览器自动化跑E2E测试。差距不在模型智商,而在“连接”这件事上做没做对。2024年底Anthropic把MCP协议推向开源社区之后,AI Agent的玩法一下子变了——从“单聊”进化成“即插即用地接入各种系统”。这篇文章我就以自己的实战过程为例,把MCP是什么、Server和Client之间怎么对话、怎么从零手写一个MCP服务、以及怎么接到AI Agent里跑起来,完整过一遍,重点讲那些文档里不写、但你实际动手一定会踩的坑。

1. 内容整体设计与思路拆解

1.1 MCP到底是什么:给AI插上“通用U盘接口”

MCP全称Model Context Protocol,中文常叫模型上下文协议。我更喜欢叫它“AI外设的USB接口”。你想想,电脑要接键盘、鼠标、打印机,靠的是USB口加驱动;AI Agent要接数据库、设计工具、浏览器、监控系统,以前靠每家各写各的插件,现在MCP把这个过程统一成了标准协议。

标准协议解决什么?解决重复造轮子。在MCP出现之前,AI Agent接入一个工具基本是这么干的:写一段Python脚本调API、把返回结果拼进Prompt、再告诉模型“这个JSON是这个意思”。每接一个新系统,这套逻辑就得重写一遍。而且工具之间还不能共享,A项目写的MySQL查询函数,B项目没法直接用。

MCP把这个问题拆成三层:协议层规定消息格式和传输方式,Server层负责暴露工具和数据源,Client层负责跟AI模型对接。做出一个MCP Server之后,只要客户端支持MCP,不管是Claude Desktop还是Cursor还是自研Agent,都能直接“插上就用”,这才是“即插即用”的真实含义。

1.2 为什么2025年这一年MCP突然火起来

你看现在的热搜词里,从“cursor连接蓝湖mcp”到“wazuh mcp服务器”,再到“burpsuite mcp”,覆盖了设计、安全、游戏引擎、数据可视化这么多领域,说明MCP不是小众技术,而是正在变成AI Agent的标配接口。

原因其实不复杂。第一,AI编程工具打得火热,Cursor、Codex、Trae都需要连用户的私有数据,MCP提供了一套统一的方式,开发者写一次就能到处用。第二,MCP是Anthropic开源并推动的,Claude生态带动了热度,其他厂商跟得也快。第三,MCP把“Agent能干什么”的边界问题交给工具去定义,模型只负责决策和调用,这个分工让复杂任务变得可拆解、可调试。

这里要强调一个容易混淆的点:MCP和Function Calling不是一回事,也不是替代关系。Function Calling是模型API层的能力,让模型输出一个结构化调用指令;MCP是应用层协议,解决的是工具“怎么注册、怎么被发现、怎么被调用”的统一标准。两者可以配合使用,也可以单独存在。

1.3 我的MCP实战目标:做一个能查GitHub星标的Server

纸上谈兵没用,我这次实战选了一个最典型、最能说明问题的场景:做一个MCP Server,功能只有一个——输入仓库名,返回它的Star数和最近更新时间。

为什么选这个?第一,GitHub API免费、无需鉴权也能用,降低了门槛;第二,它调用的是外部HTTP接口,能完整展示MCP里“Agent发出请求→Server解析参数→Server调外部API→返回结构化结果→Agent理解结果”这条完整链路;第三,这个Server做完之后,不管是Claude Desktop还是Cursor都能接,能直观体会“即插即用”。

为了让过程更有参考性,我还会配一个MySQL查询的Server做对比,说明MCP在私有数据场景下的价值。咱们不搞花活,就一步步把Server写出来、跑起来、接进去。

2. 核心细节解析与实操要点

2.1 MCP协议里的三个核心角色:Server、Client、Agent

先理清概念,后面写代码才不迷糊。MCP架构里一共有三个角色。

MCP Server:暴露能力的一方。它声明“我能做什么”,提供三种能力——工具(Tools)、资源(Resources)、提示词(Prompts)。工具是最常用的,就是可调用的函数;资源是暴露给模型读取的上下文数据;提示词是预定义好的对话模板。

MCP Client:连接Server和Agent的中间层。它负责跟Server建立连接、拉取工具清单、发起调用请求。Claude Desktop、Cursor内置的MCP支持,本质就是内置了一个MCP Client。

AI Agent:决策大脑。它从Client拿到工具清单后,根据用户的任务决定“该调哪个工具、传什么参数”,然后把调用结果拼回上下文继续推理。

我用一个生活化类比来帮你记:Agent是老板,Server是供应商,Client是秘书。老板不知道供应商的联系方式,秘书负责维护通讯录(工具清单),老板说要查数据,秘书打电话给供应商(发起调用),拿到结果再转述给老板(返回上下文)。

2.2 MCP的传输与消息格式:JSON-RPC 2.0

MCP目前主流的传输方式是Streamable HTTP(早期是stdio),消息格式走JSON-RPC 2.0。这意味着什么?意味着所有交互都是“发一个JSON请求、收一个JSON响应”,跟你调普通HTTP接口没有本质区别。

具体来说,Client和Server建立连接之后,会先发一个tools/list请求,Server返回工具名、描述、参数结构;Agent根据这个清单生成调用意图;Client再发tools/call请求,带上工具名和参数;Server执行完返回结果,结果里可以带结构化内容(JSON)、文本内容,甚至是图片资源。

这个设计的好处是:传输层只负责搬JSON,业务逻辑全在Server端,所以传输层以后就算从HTTP换成WebSocket,Server端的核心代码也不用大变。我后面写Server时你会看到,真正要写的核心逻辑,其实是“处理tools/call”那部分。

2.3 工具选型:Python + FastMCP,还是TypeScript + SDK?

MCP官方SDK有Python和TypeScript两套,社区还有各种封装。我个人建议:想做原型验证、快速跑通的选Python的FastMCP库;想深度集成前端生态、做生产级服务选TypeScript官方SDK

我这次用Python + FastMCP,理由是:FastMCP把SDK的样板代码简化得很干净,一个装饰器就能定义一个工具,十行左右就能跑起一个Server。对新手来说,这个上手体验非常重要,不至于被协议细节劝退。

如果你要在Cursor或VS Code Copilot里用MCP,客户端侧的配置方式略有不同,但Server侧完全通用。记住这句话:MCP Server不挑客户端,只要客户端支持MCP协议,接谁都能用

3. 实操过程与核心环节实现

3.1 从零搭建FastMCP开发环境

先准备环境,我假设你已经装好了Python 3.10以上版本。在终端里建一个项目目录和一个虚拟环境:

mkdir mcp-demo cd mcp-demo python -m venv .venv # Windows .venv\Scripts\activate # macOS / Linux source .venv/bin/activate pip install fastmcp httpx

这里装了两个依赖:fastmcp是核心库,httpx用来调GitHub API。有人会问为什么用httpx而不是requests,因为httpx支持异步,FastMCP原生支持异步工具,后面写并发请求时不用改架构。

装完之后可以验证一下:

python -c "import fastmcp; print(fastmcp.__version__)"

看到版本号输出就说明环境OK。这一步我建议不要跳过,很多人后面报错发现是环境没装对,白白浪费半小时。

3.2 手写一个GitHub星标查询Server

在项目目录下新建github_star_server.py,这是整个Server的核心文件。我先把完整代码贴出来,再逐段拆解:

import httpx from fastmcp import FastMCP mcp = FastMCP("GitHub Star Server") @mcp.tool() def get_github_stars(repo: str) -> dict: """获取指定GitHub仓库的星标数和最近更新时间。 Args: repo: GitHub仓库名,格式为 owner/repo,例如 anthropics/anthropic-sdk-python """ url = f"https://api.github.com/repos/{repo}" response = httpx.get(url, timeout=10) if response.status_code == 404: return {"error": "仓库不存在,请检查名称是否正确"} if response.status_code != 200: return {"error": f"GitHub API返回异常状态码: {response.status_code}"} data = response.json() return { "repo": repo, "stars": data["stargazers_count"], "description": data.get("description", ""), "last_updated": data["updated_at"], "html_url": data["html_url"], } if __name__ == "__main__": mcp.run(transport="sse")

不要小看这几十行,它包含了几个很关键的实践细节。

细节一:docstring不是注释,是给模型看的“工具说明书”。FastMCP会把函数名和docstring发给LLM,模型通过这些描述判断“这个工具是干嘛的、什么情况下该调用”。我在docstring里明确写了格式是owner/repo,还给了示例,这样模型就知道怎么从用户的话里提取参数。很多人写的工具明明能用,但模型就是不调用,十有八九是描述不清晰。

细节二:错误处理要返回给人看的消息,而不是抛异常。如果GitHub API返回404,我直接返回一个带error字段的字典,这样Agent拿到结果后能自行推理出“仓库不存在”,然后转告用户。如果这里直接抛异常,很多客户端会显示一长串堆栈,体验很差,而且模型无法理解到底发生了什么。

细节三:transport="sse"表示用SSE(Server-Sent Events)传输方式。这是目前MCP客户端兼容性最好的一种方式。早期推荐的streamable-http在某些老版本客户端上有兼容问题,所以我建议新手先用SSE,跑通之后再考虑换其他传输。

3.3 把Server接到Claude Desktop里

Server写好了先本地跑一下,确认没有语法错误:

python github_star_server.py

看到类似“Started SSE server on /mcp”的日志就说明Server在跑了。接下来把它接到客户端里。我用Claude Desktop举例,因为它的配置最直观。

打开Claude Desktop的配置文件(路径通常是~/Library/Application Support/Claude/claude_desktop_config.json),加一段:

{ "mcpServers": { "github-stars": { "command": "python", "args": ["/绝对路径/你项目目录/github_star_server.py"], "env": {} } } }

注意,这里不是填http://localhost:8000这种地址,而是填启动命令。Claude Desktop会自己拉起子进程运行这个Python脚本。这也是MCP的灵活之处——Server既可以是远程HTTP服务,也可以是本地子进程。

保存配置文件,重启Claude Desktop,然后在对话框里输入:“查一下anthropics/anthropic-sdk-python这个仓库有多少star”。正常情况下,模型会调用get_github_stars工具,然后告诉你结果。

第一次跑通这个流程时,我确实感觉“通了、真的通了”——不是聊聊天,是它在按我的要求主动查外部数据,还自己决定用什么参数。这个体验跟以前纯靠Prompt工程是完全不一样的。

3.4 扩展实战:做一个MySQL查询Server

光查GitHub星标还不够过瘾,我再加一个能体现“连接私有系统”的Server。假设你本地有个MySQL数据库,里面有张订单表,你想让Agent帮你查订单数量。

先装依赖:

pip install pymysql

然后写mysql_server.py

import pymysql from fastmcp import FastMCP mcp = FastMCP("MySQL Query Server") DB_CONFIG = { "host": "127.0.0.1", "user": "root", "password": "your_password", "database": "shop", } @mcp.tool() def query_orders(status: str = None) -> dict: """查询订单表数据。 Args: status: 订单状态,可选值为 pending、paid、shipped、completed。不传则查询全部。 """ sql = "SELECT id, customer, amount, status FROM orders" params = [] if status: sql += " WHERE status = %s" params.append(status) sql += " LIMIT 50" conn = pymysql.connect(**DB_CONFIG) try: with conn.cursor() as cursor: cursor.execute(sql, params) rows = cursor.fetchall() columns = [desc[0] for desc in cursor.description] result = [dict(zip(columns, row)) for row in rows] return {"total": len(result), "rows": result} except Exception as e: return {"error": str(e)} finally: conn.close() if __name__ == "__main__": mcp.run(transport="sse")

这个例子想说明一个事:MCP Server最大的价值不是接公开API,而是把私有数据安全地暴露给AI Agent。你的数据库密码、连接串都写在Server端,模型只看到工具名和返回结果,接触不到底层细节。这就比“把SQL拼接进Prompt”安全得多。

接MySQL这个Server时,配置文件和前面GitHub那个完全一样,只是换个名字和路径。你可以在同一份配置里同时挂两个Server,Claude Desktop会自动合并所有工具给模型用。多个Server之间互不干扰,这就是“即插即用”最直观的体现。

3.5 在Cursor里玩MCP:几种常见连接的配置方式

Cursor是我日常用得最多的AI编程工具,它支持MCP的方式跟Claude Desktop略有不同。在Cursor里,点开Settings → Tools → MCP,可以看到所有已连接的Server。

添加一个远程MCP Server(比如有人部署好的公开Server),直接在URL框里填SSE地址,比如https://example.com/mcp,Cursor会自动探测并连接。

添加一个本地脚本Server,选择“Add local MCP Server”,填启动命令和参数,跟Claude Desktop里的配置逻辑一样。

用VS Code Copilot连接Figma MCP这种操作,本质也是给编辑器配置一个MCP服务器。你需要在Copilot的配置目录下指定MCP服务器的地址或命令,然后它就会自动把Figma设计文件的信息作为上下文喂给AI。从热搜来看这个问题问的人很多,注意一点:Figma MCP通常需要你提供Figma的Access Token,这个Token要放在Server端的环境变量里,不要写死在对话里发给模型。

我实测下来一个感受:Cursor对MCP工具的支持已经相当成熟,模型自动决定调用工具的成功率比Claude Desktop还要高一点,因为它把工具描述和当前代码上下文融合得更好。

4. 常见问题与排查技巧实录

4.1 Server连接上了,但模型就是不调用工具

这是我被问得最多的问题,也是我被坑得最惨的问题。现象很统一:配置没报错,工具清单也拉到了,但模型就是“视而不见”,该自己瞎编还自己瞎编。

排查思路按顺序来:

第一步,检查工具描述是否够具体。模型的调用决策完全依赖工具名和docstring。如果你的工具描述写的是“查询数据”这种模糊描述,模型根本不敢用。我自己的经验是:docstring要写清楚“什么时候用、参数格式是什么、返回什么”。你可以故意把描述写得长一点,把边界情况也写进去。

第二步,检查是否同时挂了太多Server。工具清单越长,模型的选择成本越高。你挂了20个Server,每个3个工具,模型要在一堆工具里挑,容易挑错或挑不出来。建议只保留当前任务需要的Server。

第三步,给模型一个明确的触发场景。有些客户端默认不太喜欢主动调工具,你得在对话里带上明确的意图词。比如直接说“用工具查一下”,比说“帮我看看”更容易触发。

4.2 调用工具后报超时或“Connection reset”

这个大概率是网络问题,但要注意区分两种情况。

本地Server(stdio方式)报连接重置,先看子进程有没有崩溃。直接在终端手动运行那个Python文件,看看能不能正常启动、有没有报错。很多本地Server配置看着没问题,一跑就发现端口被占、依赖缺失、路径写错,这些错误在客户端里都被统一显示成“connection reset”,很误导人。

远程Server(HTTP/SSE方式)报超时,先确认Server确实在跑、端口没被防火墙挡着。可以用curl测一下MCP的SSE端点,看能不能拿到预期响应。如果你部署在云服务器上,记得检查安全组有没有放行对应端口。

4.3 工具返回了结果,但模型理解错了

这个问题比较隐蔽。比如我的get_github_stars返回的last_updated字段是字符串2025-06-01T12:00:00Z,模型读出来之后,如果用户问“最后更新是什么时候”,它能正常回答;但如果用户问“最后更新是几号”,有些模型会把整个字符串念出来,不会主动换算时区。

解决思路是:在Server端就把数据清洗到“人类可直接读”的程度。我在实际版本里会把updated_at先格式化一遍,再返回给模型,不给它自由发挥的空间。另外,返回的字段名也很重要,尽量用语义化名称,比如display_last_updated,比updated_at更不容易让模型产生误解。

4.4 MCP配置改了但没生效

改了claude_desktop_config.json,重启客户端之后发现还是老样子——这个通常不是配置问题,而是JSON格式错了。MCP配置如果解析失败,客户端默认会静默忽略,而不是弹窗报错。

你可以在终端里跑一下:

python -m json.tool claude_desktop_config.json

有输出说明JSON合法。如果没有输出且报错,那就是多了逗号、少了括号这类低Level错误,改对了再重启客户端。

4.5 常见问题速查表

现象可能原因快速排查方案
配置了但工具列表为空JSON格式错误或Server启动失败手动运行脚本,检查输出日志
模型不调用工具工具描述不够清晰重写docstring,加入触发场景和参数示例
调用返回超时网络不通或子进程崩溃curl测试SSE端点,检查安全组
返回数据能被看到但回答错误返回字段语义不明确在Server端格式化数据,精简字段
多个Server工具互相干扰工具名冲突或清单过长给每个工具加统一前缀,减少Server数量

4.6 还有几个容易踩的暗坑

暗坑一:Python版本太老。FastMCP要求Python 3.10以上,用3.8、3.9跑会直接报语法错误。装之前先确认python --version

暗坑二:端口冲突。你本地跑了多个MCP Server,如果都用了默认端口,第二个就会起不来。建议在mcp.run()里显式指定端口,比如port=8001,避免冲突。

暗坑三:工具名称冲突。如果两个Server都定义了query这个工具,客户端合并工具清单时可能互相覆盖。我的习惯是给工具名加前缀,比如github_get_starsmysql_query_orders,名字长一点没关系,但一定要唯一。

暗坑四:别在生产环境犯的错——把数据库密码硬编码在Server脚本里。用环境变量传连接串,或者用本地密钥管理服务,否则一个不小心把配置文件提交到Git仓库,密码就暴露了。MCP Server虽然是本地跑的,但它也是程序,同样要按生产标准来。

5. 更多场景与扩展玩法

5.1 不只是编程工具:安全测试、游戏引擎、设计工具里的MCP

MCP的火爆远远超出编程辅助工具的范围。从热搜词里你就能看到它在往各种垂直领域渗透。

安全测试领域的Burp Suite MCP:渗透测试人员把Burp抓到的包通过MCP暴露给AI Agent,AI就能直接分析请求、对比响应、甚至尝试生成测试Payload。这极大减少了人在测试工具和AI助手之间来回Copy-Paste的工作量。

游戏引擎里的Unity MCP和Cocos Creator MCP:游戏开发者在编辑器里通过MCP让AI直接操作场景对象、查询组件状态、生成C#或TypeScript脚本。设计资源和AI编程之间第一次有了这么顺畅的通道。

设计工具里的Figma MCP、蓝湖MCP:前端开发最大的痛点是“设计稿和代码对不上”。有了Figma MCP,AI能直接读Figm文件的图层结构、尺寸、颜色变量,然后生成更精准的还原代码。蓝湖MCP的逻辑类似,但对国内团队更友好,很多人从热词里找它也是因为这个。

运维安全领域的Wazuh MCP:把Wazuh的安全告警通过MCP暴露给AI,让AI做初步的告警研判。这是安全运营自动化一个很好的方向。

这些场景共同说明一件事:MCP是AI Agent的“通用接口层”,谁支持谁就进Agent的“工具库”。学会做一个MCP Server,等于你掌握了一种不管接什么系统都能用同一套思路搞定问题的能力。

5.2 Skills和MCP怎么配合

还有一个高频问题:Skills和MCP是什么关系?我的理解是:Skills偏“流程编排”,MCP偏“工具接入”。Skill定义的是“遇到这类任务要按什么步骤做”,MCP定义的是“有哪些原子能力可用”。

比如你在Cursor里配了一个“从Figma设计稿还原登录页”的Skill,里面可能规定:第一步读取Figma图层,第二步提取颜色变量,第三步生成React组件,第四步做响应式适配。而每一步真正去执行的时候,调的还是Figma MCP暴露出来的那些工具。所以,Skill带着模型做规划,MCP给模型提供弹药,两者是配合关系,不是替代关系。

5.3 未来的Agent开发,MCP会变成标配吗

从整个行业的热度和工具链的成熟度来看,MCP正在走向“AI Agent的水电煤”。2026年之后,Agent开发可能不再需要关心“怎么去接某个具体服务”,直接找现成的MCP Server就行。就像现在写Web应用不需要自己实现HTTP协议一样。

但这并不意味着深入理解底层机制没意义。恰恰相反,真正能做出差异化价值的,是那些把私有工具封装成高质量MCP Server的人。协议本身很快会变成基础设施,但怎么把自己团队的数据库、API、内部系统安全高效地封装给AI用,这个能力会越来越值钱。

我在实际运用中还有一个小技巧:做MCP Server时,不要一上来就追求把所有功能都暴露出去,先只暴露两三个高频工具,跑通再迭代。模型在工具数量少的时候调用准确率会高很多,这对新项目调优特别有帮助。另外,每次修改Server代码之后,记得在客户端里重连一次,有时候工具列表缓存不会自动刷新,会让人误以为改动没生效。最后想提醒一点:MCP目前的版本协议还在快速演进中,你写Server时尽量用官方维护的SDK,跟着大版本走,不要自己去实现底层协议细节,否则升级时很容易踩兼容性的坑。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询