你手上有十几个Python脚本,能查数据库、能发通知、能生成报表。每个都跑得好好的。但AI叫不动它们。
你在Claude里打一句"帮我查一下库存预警",Claude说它没法访问你的数据库。你在GPT里说"把昨天的日志汇总发给我",GPT建议你手动导出。
说白了,你的脚本就像老房子里的家电——能干活,但没接入智能家居系统。灯得手动开,空调得自己调,洗衣机得走过去按启动。而MCP Server,就是那个智能插座。
MCP是什么:一个让AI"插电"的协议
MCP全称Model Context Protocol,2024年底由Anthropic发布,2026年已经成为AI工具调用的事实标准。
它的架构三件套:
- HostAI应用本身,比如Claude Desktop、Cursor、ChatGPT
- ClientHost内部的MCP客户端,负责跟Server通信
- Server
换成智能插座的比喻就清楚了。你的家电(Python脚本)插在智能插座(MCP Server)上,智能插座通过智能家居协议(MCP协议)跟中央控制器(Host里的Client)对话。你对着音箱喊一句"开灯",信号走协议到插座,插座通电,灯亮。
这里有个容易忽略的事:智能插座并不改变家电本身的功能。灯还是那盏灯,空调还是那台空调。插座做的事情是把家电接入一个统一的控制网络。同样的道理,MCP Server不会增强你的脚本功能,查库存的脚本还是查库存,发邮件的脚本还是发邮件。Server做的是把脚本的能力翻译成AI能理解的格式,然后暴露出去。
再推一步:智能插座真正厉害的地方,不是让你能手机远程开灯,而是让中央控制器能编排场景。"回家模式"一句话,灯亮、空调开、窗帘拉上,三个设备联动。MCP Server也一样,它让AI能编排工具链:"查库存、低于阈值就发通知、通知里附上补货链接",三个工具串起来变成一个自动化流程。
但真正的坑不在协议本身。在你根本不知道协议长什么样之前,就已经在重复造轮子了。
之前我们怎么干的
之前团队想让AI调用内部数据库,方案是写REST API。Flask起个服务,/query接参数,返回JSON。看起来没问题?
问题来了。Claude要调,得写一个plugin descriptor。GPT要调,得配一个OpenAPI spec。内网另一个AI要调,又得按它的格式来一遍。三个AI,三套对接文档,每次改接口还得同步三处。
改成MCP Server后,所有支持MCP的AI都能直接调。一次开发,到处运行。那天下午我把REST API改成MCP Server,Claude Desktop配了30秒就能用了。第二天同事在Cursor里也配上了,零额外开发。同一个Server,两个AI客户端,不用改一行代码。这就是标准化协议的力量。
智能插座的价值在哪?让中央控制器能调度所有家电。MCP Server也一样,让AI Agent能编排所有工具。家电本身没变强,灯还是那盏灯;脚本本身没变强,查库存还是查库存。变的是谁能调它们。
动手:写一个完整的MCP Server
用Python MCP SDK写一个Server,分四步:装包、写工具、注册Schema、启动服务。别被这四步吓到,实际代码量加起来不超过50行。
第一步:装SDK
pip install mcp
就一个包。2026年的SDK版本已经稳定到1.x,API基本不会大变了。如果你用uv管理虚拟环境,把pip换成uv pip就行,没啥区别。
第二步:写一个查库存的工具
from mcp.server.fastmcp import FastMCPmcp = FastMCP("inventory-server")@mcp.tool()def check_inventory(sku: str, warehouse: str = "default") -> str: """查询指定SKU在指定仓库的库存数量""" stock = query_db(sku, warehouse) return f"SKU {sku} 在 {warehouse} 仓库库存: {stock}件"
三行有效代码,一个工具就注册完了。FastMCP是SDK提供的高层封装,装饰器@mcp.tool()自动把函数签名转成MCP工具描述。
第三步:参数Schema——这里踩过坑
MCP用JSON Schema描述参数。SDK会从函数签名自动生成,但有个问题:自动生成的Schema精度不够。
看这段代码的warehouse参数,默认值是"default"字符串。自动生成的Schema会把它标记为string类型,但AI不知道"default"是什么意思,也不知道还有哪些仓库可选。
我之前就踩了这个坑。AI调用时传了warehouse="主仓库",结果查不到数据——我们的系统里只有"bj01"、"sh02"这种编码。AI怎么知道?它不知道。
正确做法:用enum约束可选值,用description说明含义。
from pydantic import Field@mcp.tool()def check_inventory( sku: str = Field(description="商品SKU编码,如'SHIRT-001'"), warehouse: str = Field( default="bj01", description="仓库编码", pattern="^(bj01|sh02|gz03)$" )) -> str: """查询指定SKU在指定仓库的库存数量""" stock = query_db(sku, warehouse) return f"SKU {sku} 在 {warehouse} 仓库库存: {stock}件"
Schema越精确,AI调错的可能性越低。这条经验我调了三个晚上才想明白:AI够聪明,但你得告诉它边界在哪。
第四步:启动
if __name__ == "__main__": mcp.run()
mcp.run()默认用stdio模式,Host通过标准输入输出跟你通信。这是最简单的方式,不需要起HTTP服务,不需要配端口。
但如果你想让多个Host同时连,或者想通过网络远程调用,就得换SSE模式:
mcp.run(transport="sse", host="0.0.0.0", port=8080)
两种模式各有适用场景。本地开发用stdio,生产部署用SSE。别在本地调试时用SSE,端口冲突会搞得你怀疑人生。
还有一个细节:stdio模式下,每次Host启动都会spawn一个Server进程。如果你在Server里做了耗时的初始化(比如加载模型、连接数据库),每次启动都会卡一下。解决办法是把初始化放到工具调用时做lazy loading,而不是进程启动时。
对接实测:Claude、GPT、Cursor三连
写完Server只是半程。另一半是让AI真的能调起来。你猜怎么着?对接比写Server还快。
Claude Desktop
编辑claude_desktop_config.json:
{ "mcpServers": { "inventory": { "command": "python", "args": ["path/to/your/server.py"] } }}
重启Claude Desktop,工具自动出现。你会在聊天框下方看到一个小锤子图标,点开能看到你注册的所有工具。输入"帮我查一下SHIRT-001在北京仓库还有多少",Claude会调你的工具,返回结果。整个过程不到两分钟。
Cursor
在项目根目录创建.cursor/mcp.json,格式一样。Cursor 2026年的版本已经原生支持MCP,不需要装任何插件。
ChatGPT / GPT-4o
OpenAI在2026年初接入了MCP协议,走SSE模式。你要把Server部署到公网可访问的地址,然后在ChatGPT的MCP设置里填URL。这意味着你的代码会暴露在公网,记得加认证。MCP协议本身不包含鉴权层,这是你自己的事。
这里有个容易忽略的细节:SSE模式下,工具的响应时间直接影响AI的等待体验。如果你的脚本要跑10秒,AI会等10秒,用户也会等10秒。解决办法:耗时操作做成异步,先返回"任务已提交",再通过另一个工具查结果。
踩坑清单:四个我替你踩过的雷
返回值必须是字符串
MCP工具的返回值类型是list[TextContent],但FastMCP做了封装,你的函数返回str就行。别返回dict或list,会报序列化错误。如果你必须返回结构化数据,用json.dumps()转成字符串。
工具数量别超过50个
我试过一个Server注册了80多个工具,结果Claude调用时经常选错工具。AI在面对太多选项时表现会下降,这跟人一样。拆成多个Server,每个Server负责一个领域,5-15个工具最佳。
错误信息写给谁看?AI,不是开发者
raise ValueError(f"Database query failed: {e}")return f"查询失败:SKU {sku} 不存在或仓库 {warehouse} 未配置。请检查输入参数。"
为什么?因为AI读到错误信息后要决定下一步怎么走。你给它一个Python traceback,它大概率会原样甩给用户。你给它一句"请检查输入参数",它可能会换个参数重试。错误信息就是你跟AI之间的接口协议。
description是AI唯一的说明书
AI调你的工具时,只看两个东西:工具名和description。没有文档页面,没有示例代码,没有同事口头说明。这就好比你家的智能插座上只贴了一个标签,标签上写什么,音箱就只能理解什么。
所以description要写清楚三件事:这个工具做什么、需要什么参数、什么情况下不该用。缺了任何一条,AI都可能误用。
@mcp.tool()def delete_inventory( sku: str = Field(description="要删除的SKU编码"), confirm: bool = Field(default=False, description="必须为True才会执行删除,防止误操作")) -> str: """删除指定SKU的库存记录。⚠️ 此操作不可逆,仅在确认清仓时使用。""" if not confirm: return "未确认,操作已取消。请设置confirm=True来执行删除。" ...
这个confirm参数是我被坑了之后加的。AI第一次调用就传了confirm=True,还好我多加了一层校验。别信任AI不会误操作——它只是概率模型,不是理性人。
2026年的MCP生态
到2026年5月,MCP生态已经和一年前完全不同了。
支持MCP的Host一长串:Claude Desktop、Cursor、ChatGPT、Windsurf、Cline、OpenClaw,国内通义千问和豆包也接入了。主流AI应用基本都支持。半年前还有些Host要装插件才能用MCP,2026年大部分都原生集成了。
SDK方面,Python SDK官方维护,最稳。TypeScript其次。Go和Java有社区版,覆盖约80%的功能。Rust SDK还在早期。如果你在选语言,Python和TypeScript是安全选择,其他语言先观望。
MCP Hub上已有2000+现成的Server。数据库连接、文件操作、API调用这些常见需求大概率能找到现成的。但内部业务逻辑,查库存、算佣金、生成报表,这些还得自己写。别人帮不了你,也不想帮你——这些都是你公司的核心流程。
一个明显趋势:越来越多的团队把MCP Server当"AI时代的API"来用。给前端写API用REST,给移动端用GraphQL,给AI用MCP。协议不同,思路一样:把能力暴露出去,让调用方自己组合。甚至有团队把MCP Server当成了内部服务的统一接入层,前端、移动端、AI三端都走MCP,省得维护三套API。
最后说一个容易被忽略的事
MCP Server让你的脚本对AI可用,但这也意味着你的脚本对任何接了MCP的AI都可用。
我部署的第一个MCP Server上线两周后被三个不同团队的AI调用了,其中一个我根本不认识。他们怎么找到的?因为我们内网有个MCP Registry,所有注册的Server都会被索引。
这挺好,对吧?共享能力,减少重复造轮子。
但代价呢?你的工具一旦通过MCP暴露出去,调用方就不受你控制了。别人可能用你意想不到的方式调用,可能把你的工具嵌进一个十步长的Agent流程里,你的工具变成链路中的一环。任何一环出问题,整条链都断。你的接口改个参数名,下游三个团队的Agent全挂。
所以MCP Server的版本管理、向后兼容、降级策略——这些在REST API时代就存在的问题——在MCP时代只会更尖锐。因为调用方不再是写代码的开发者,而是一个你无法沟通的AI Agent。
智能插座让所有家电都能被调度,但也意味着一个错误的指令能让所有家电同时出问题。MCP解决的是连通性,不是安全性。你在插座上没装保险丝,短路的时候烧的是整条线路。
所以每次写MCP Server,问自己三个问题:谁能调?调了能干什么?干了出事谁负责?前两个靠认证和权限控制,最后一个靠版本管理和降级策略。这些都不是MCP协议会帮你做的事。