
1. 从“烟囱”到“插座”为什么AI Agent需要一个“USB-C”如果你最近在折腾AI Agent开发或者关注Claude、Cursor这类智能编码工具大概率会频繁听到一个词MCP。它可能出现在某个插件的配置里或者某个开源项目的README中甚至是你想让AI帮你查个天气、读个文件时弹出的一个神秘错误。MCP全称Model Context Protocol中文可以理解为“模型上下文协议”。这个名字听起来有点抽象但它的目标却极其具体和野心勃勃成为所有AI工具与AI模型之间通信的“通用插座”。想象一下没有USB-C接口的电子设备世界。你的手机、电脑、耳机、移动电源每个设备都有一套自己的专属充电线和数据接口。你需要一个抽屉来装各种线缆每次连接新设备都是一场“猜接口”的游戏。这就是当前AI Agent生态的现状。一个想帮你分析GitHub仓库的Agent需要专门写一套与GitHub API交互的代码另一个想帮你管理日历的Agent又得重新实现一遍与Google Calendar的对接。开发者80%的精力可能都花在了为不同的“工具”编写不同的“插头”上而不是思考Agent本身的逻辑。MCP协议的出现就是为了终结这种混乱。它由Anthropic公司Claude的创造者牵头提出并开源其核心理念是标准化。它定义了一套简单的、与具体AI模型无关的通信规范让任何工具我们称之为MCP Server都能以统一的方式将自己的能力“暴露”给任何支持MCP的AI应用我们称之为MCP Client。这就像给所有工具和设备都装上了USB-C接口而AI模型无论是Claude、GPT还是其他大模型则是那个“主机”它只需要知道如何通过MCP这个“标准插座”去“读取”和“调用”工具而无需关心工具内部是安卓系统还是iOS是硬盘还是U盘。对于开发者而言这意味着你可以专注于开发一个功能强大的“工具服务器”MCP Server比如一个能精准搜索学术论文的服务器或者一个能安全执行数据库查询的服务器。一旦完成这个服务器就能被所有支持MCP的AI客户端如Claude Desktop、Cursor、Windsurf等即插即用。对于用户来说你可以在自己喜欢的AI应用里轻松获得成百上千种由社区开发的专业工具能力无需每次切换应用或进行复杂的配置。这个协议正在迅速成为AI Agent工具生态的事实标准。接下来我们就深入它的内部看看这个“USB-C”接口具体长什么样以及我们该如何利用它来构建和连接自己的“设备”。2. MCP协议核心三要素资源、工具与提示词模板要理解MCP如何工作我们必须先拆解它的核心数据模型。协议主要定义了三种类型的实体它们共同构成了AI模型与外部世界交互的上下文。2.1 资源ResourcesAI的“只读存储器”资源是MCP中最基础的概念。你可以把它理解为AI模型可以“查看”但无法直接修改的信息源。它的核心特点是只读和结构化描述。一个资源包含几个关键属性uri资源的唯一标识符类似于一个网址例如file:///path/to/notes.md或github://owner/repo/issues。它告诉客户端这个资源在哪里、是什么。mimeType资源的媒体类型如text/markdown、application/json、image/png。这帮助AI模型和客户端正确解析内容。name和description对人类和AI友好的名称与描述例如name: “项目周报”,description: “包含本周项目进度和下周计划的Markdown文档”。举个例子一个文件系统MCP Server可以向客户端声明一个资源file:///home/user/project/README.md类型是text/markdown名称为“项目说明文档”。当AI模型需要了解这个项目时客户端就会根据这个资源声明向服务器请求该文件的具体内容并将其作为上下文提供给AI模型。AI可以阅读它、总结它但协议本身不提供直接修改文件的方法修改需要通过“工具”实现。资源的价值在于它将杂乱的外部数据文件、数据库记录、API响应封装成了AI模型可以安全、按需消费的“信息块”。AI无需知道文件系统的细节它只需要请求file://开头的资源即可。2.2 工具ToolsAI的“可执行命令”如果说资源是眼睛和耳朵那么工具就是AI的手。工具代表了一个可以被AI模型调用并执行的操作它通常会导致外部世界状态的改变。一个工具的定义更像一个函数声明name: 工具的名称如search_web或create_calendar_event。description: 详细的自然语言描述这是最重要的部分。AI模型完全依赖这个描述来决定在什么情况下使用这个工具。例如“在互联网上搜索给定的查询词并返回最相关的几个摘要结果。”inputSchema: 定义工具所需的参数使用JSON Schema格式。这确保了AI模型能以结构化的方式提供正确的参数。工作流程当AI模型在对话中判断需要执行某个操作比如“帮我查一下今天的天气”它会根据当前可用的工具描述选择最匹配的那个例如get_weather并生成符合inputSchema的参数{“location”: “北京”}。客户端将这个调用请求发送给MCP ServerServer执行实际的操作调用天气API然后将结果{“temp”: “22°C”, “condition”: “晴朗”}返回给AI模型AI再将其组织成自然语言回复给用户。这里有一个关键的心得编写一个好的工具描述description是一门艺术。它需要足够清晰让AI能准确理解其用途又不能过于冗长以免浪费宝贵的上下文令牌。我个人的经验是采用“动词开头目标关键参数说明”的句式并避免使用AI可能误解的同义词。例如“在指定GitHub仓库中创建一个新的Issue”就比“生成一个GitHub问题”要明确得多。2.3 提示词模板Prompts预制的工作流蓝图这是MCP中一个非常强大但常被忽略的特性。提示词模板允许Server预定义一些复杂的、多步骤的提示词框架客户端可以将其作为快捷方式或标准工作流程调用。一个提示词模板包含name和description模板的名称和描述。arguments模板所需的动态参数同样用JSON Schema定义。template提示词的主体内容其中可以嵌入参数。实际应用场景假设你有一个代码审查的MCP Server。你可以定义一个名为code_review的提示词模板它的参数是{“code_snippet”: “string”}而模板内容是一段精心设计的提示词“请以资深工程师的身份审查以下代码{{code_snippet}}。重点检查安全性、性能、可读性和是否符合项目编码规范。请分点列出潜在问题和改进建议。”当用户在客户端选择这个模板并填入一段代码后客户端并不是直接执行它而是将这个填充好的、高质量的提示词“注入”到与AI模型的对话中。这相当于为AI预先装载了一个专业的“审查官”角色和任务清单能极大提升复杂任务结果的一致性和质量。为什么说这是“蓝图”因为它将最佳实践那个精心设计的提示词从具体的对话中抽离出来变成了一个可复用、可分发的资产。团队可以共享一套标准的代码审查、需求分析、文档撰写模板确保所有成员使用的AI助手都遵循同一套高质量的工作流程。3. 协议层剖析SSE与JSON-RPC 2.0如何驱动通信理解了MCP的数据模型我们再来看看这些模型是如何在客户端Client和服务器Server之间“流动”的。MCP的通信层设计遵循了KISS原则Keep It Simple, Stupid采用了两种成熟且非常适合AI交互场景的技术组合。3.1 传输基石Server-Sent Events (SSE)MCP选择SSE作为从Server到Client的单向数据推送通道。你可能对WebSocket更熟悉它是一种全双工通信。但在MCP的场景下通信模式有显著的特点Client如Claude Desktop会发起初始化和工具调用请求而Server则需要主动地、持续地向Client通知资源的变更、新工具的可用性或日志信息。这正是SSE的用武之地。SSE基于HTTP允许Server通过一个长连接向Client持续发送事件流text/event-stream。在MCP中Server通过这个SSE连接主动发送诸如resources/listed资源列表更新、tools/listed工具列表更新这样的事件。Client只需要监听这个流就能实时感知Server端状态的变化而不需要轮询。这样设计的好处简单轻量相比于WebSocketSSE的协议更简单Client端实现容易天然支持HTTP生态如重试、鉴权。符合场景AI Agent与工具的交互中很多事件如文件保存、新消息到达是由工具端触发的需要主动通知AI端。SSE完美契合这种“Server主动推送”的模式。容错性好连接中断后Client可以携带上一个接收到的事件ID重新连接Server可以从该点恢复发送事件。3.2 请求-响应骨架JSON-RPC 2.0SSE解决了Server到Client的推送问题那么Client如何向Server发出指令呢比如“请把file:///a.txt这个资源的内容给我”或者“调用search_web工具参数是{“query”: “MCP”}”。这就是JSON-RPC 2.0的职责。JSON-RPC是一个非常轻量级的远程过程调用协议。Client通过向Server的一个HTTP端点通常是/jsonrpc发送一个JSON格式的请求来调用Server端定义的方法。一个典型的MCP JSON-RPC请求如下所示{ jsonrpc: 2.0, id: 1, method: tools/call, params: { name: search_web, arguments: { query: MCP protocol latest version } } }Server处理后会返回一个响应{ jsonrpc: 2.0, id: 1, result: { content: [ { type: text, text: 找到了关于MCP协议的最新信息... } ] } }关键设计洞察MCP将所有的核心操作——初始化initialize、列出资源resources/list、读取资源resources/read、调用工具tools/call——都定义为了JSON-RPC方法。这使得协议的核心交互变得极其规范和清晰。任何实现了JSON-RPC 2.0 Client的应用程序理论上都能与MCP Server对话。组合起来的工作流Client启动通过JSON-RPC向Server发送initialize请求建立会话。Server通过SSE连接主动推送当前可用的资源列表和工具列表。用户与AI交互AI决定调用某个工具。Client通过JSON-RPC发送tools/call请求。Server执行实际逻辑如调用API、读写数据库并通过同一个JSON-RPC请求返回结果。在此期间如果Server管理的资源发生变化如被监视的文件被修改它会通过SSE通道主动发送更新事件通知Client。这种SSE推送事件 JSON-RPC请求响应的双通道模式分离了“状态通知”和“指令执行”让整个协议既具备了实时性又保持了请求响应的简洁性是MCP设计上的一个亮点。4. 实战从零构建一个天气查询MCP Server理论说得再多不如动手实现一个。我们以构建一个最简单的“天气查询”MCP Server为例使用Python语言这将帮助你透彻理解上述所有概念是如何落地的。我们将使用官方推荐的mcpPython SDK它封装了协议细节让我们能专注于业务逻辑。4.1 环境准备与项目初始化首先确保你的Python版本在3.8以上。创建一个新的项目目录并安装核心依赖。# 创建项目目录并进入 mkdir mcp-weather-server cd mcp-weather-server # 创建虚拟环境推荐 python -m venv venv # 激活虚拟环境 # Windows: venv\Scripts\activate # macOS/Linux: source venv/bin/activate # 安装MCP SDK和HTTP请求库 pip install mcp httpx # 创建一个天气API的免费账户例如用OpenWeatherMap获取API Key我们选择httpx作为HTTP客户端因为它现代且异步友好与MCP SDK的异步特性很配。接下来在项目根目录创建主文件server.py。4.2 定义Server、资源与工具让我们在server.py中开始编码。首先导入必要的模块并定义一个我们自己的Server类。import asyncio from typing import Any import httpx from mcp import ClientSession, StdioServerParameters from mcp.server import Server from mcp.server.models import InitializationOptions import mcp.server.stdio import mcp.types as types # 从环境变量获取天气API密钥更安全 import os WEATHER_API_KEY os.getenv(WEATHER_API_KEY, your_api_key_here) WEATHER_API_URL https://api.openweathermap.org/data/2.5/weather class WeatherServer: def __init__(self): # 创建MCP Server实例 self.server Server(weather-mcp-server) # 注册资源这里我们声明一个“当前天气”资源但它本质上是动态的通过工具调用获取。 # 为了演示资源概念我们可以声明一个“帮助文档”资源。 self.server.list_resources() async def handle_list_resources() - list[types.Resource]: return [ types.Resource( uriweather://help, name天气查询帮助, description本天气MCP服务器的使用说明文档, mimeTypetext/markdown, ) ] # 实现读取上述资源的内容 self.server.read_resource() async def handle_read_resource(uri: str) - str: if uri weather://help: help_text # 天气查询MCP服务器 使用说明 ## 可用工具 - get_current_weather: 查询指定城市的当前天气。 ## 参数说明 调用 get_current_weather 工具时请提供以下参数 - city (字符串): 城市名称例如 北京、New York。 - country_code (可选字符串): 国家代码用于消除城市名歧义例如 CN、US。 return help_text raise ValueError(f未知资源: {uri}) # 注册核心工具获取当前天气 self.server.list_tools() async def handle_list_tools() - list[types.Tool]: return [ types.Tool( nameget_current_weather, description根据城市名称查询当前的天气情况包括温度、湿度、天气状况和风速。温度默认为摄氏度。, inputSchema{ type: object, properties: { city: { type: string, description: 要查询天气的城市名称例如 北京 或 London。 }, country_code: { type: string, description: 可选的国家代码ISO 3166-1 alpha-2用于精确匹配城市例如 CN 或 US。 } }, required: [city] } ) ] # 实现工具调用逻辑 self_server.call_tool() async def handle_call_tool(name: str, arguments: dict[str, Any]) - list[types.TextContent]: if name get_current_weather: city arguments.get(city, ) country_code arguments.get(country_code, ) # 构建查询参数 params { q: f{city},{country_code} if country_code else city, appid: WEATHER_API_KEY, units: metric, # 使用摄氏度 lang: zh_cn # 中文结果 } async with httpx.AsyncClient() as client: try: resp await client.get(WEATHER_API_URL, paramsparams, timeout10.0) resp.raise_for_status() data resp.json() # 解析天气数据 main data[main] weather data[weather][0] wind data[wind] weather_info f **{data[name]} ({data[sys][country]}) 当前天气** - **状况**{weather[description]} - **温度**{main[temp]}°C (体感 {main[feels_like]}°C) - **湿度**{main[humidity]}% - **气压**{main[pressure]} hPa - **风速**{wind[speed]} m/s return [types.TextContent(typetext, textweather_info)] except httpx.HTTPStatusError as e: return [types.TextContent(typetext, textf请求天气API失败HTTP错误: {e.response.status_code})] except Exception as e: return [types.TextContent(typetext, textf查询天气时发生未知错误: {str(e)})] raise ValueError(f未知工具: {name}) async def run(self): 运行服务器使用stdio传输 # 配置服务器通过标准输入输出与客户端通信 server_params StdioServerParameters( commandpython, args[-u, __file__] # -u 参数确保输出无缓冲 ) async with mcp.server.stdio.stdio_server(server_params) as (read_stream, write_stream): async with ClientSession(read_stream, write_stream) as session: await self.server.run( session, InitializationOptions( server_nameweather-mcp-server, server_version0.1.0, capabilitiesself.server.get_capabilities() ) ) if __name__ __main__: server WeatherServer() asyncio.run(server.run())代码逐段解析Server初始化self.server Server(weather-mcp-server)创建了一个MCP Server实例并给它起了一个名字。资源声明self.server.list_resources()装饰器注册了一个处理函数用于在客户端询问时返回服务器提供的资源列表。这里我们声明了一个静态的帮助文档资源weather://help。注意资源是“声明”内容在read_resource中提供。资源读取self.server.read_resource()装饰的函数负责根据传入的uri返回具体内容。当客户端需要查看weather://help时我们就返回预设的Markdown文本。工具声明self.server.list_tools()返回工具列表。我们定义了一个get_current_weather工具并详细描述了它的功能和输入参数模式inputSchema。这里的描述至关重要AI模型就是靠它来理解何时以及如何使用这个工具。工具执行self_server.call_tool()是核心业务逻辑所在。当客户端调用get_current_weather时这个函数被触发。它从arguments中提取参数构造请求调用真实的天气API处理响应并将结果格式化成AI易读的文本返回。返回类型必须是List[types.TextContent]。运行循环run方法配置了服务器使用标准输入输出stdio作为传输层这是MCP Server最常见的运行方式便于被各种客户端如Claude Desktop启动和管理。4.3 配置客户端并测试编写完Server我们需要一个支持MCP的客户端来测试它。最方便的是使用Claude Desktop应用。配置Claude Desktop 在Claude Desktop中MCP Server的配置通常位于一个JSON配置文件中。对于macOS文件路径是~/Library/Application Support/Claude/claude_desktop_config.json。你需要编辑这个文件在mcpServers部分添加我们的天气服务器。{ mcpServers: { weather: { command: python, args: [ -u, /ABSOLUTE/PATH/TO/YOUR/mcp-weather-server/server.py ], env: { WEATHER_API_KEY: your_actual_openweathermap_api_key } } } }重要提示必须使用-u参数无缓冲输出否则通信可能出问题。args中的路径必须是绝对路径。将WEATHER_API_KEY替换为你从OpenWeatherMap获取的真实API密钥。重启与测试 保存配置文件并重启Claude Desktop。如果配置正确Claude会在启动时自动运行我们的Python脚本。现在你可以在Claude的对话窗口中直接说“使用天气工具查一下北京的天气。” Claude应该能识别出可用的get_current_weather工具并向你询问或直接使用参数{“city”: “北京”}进行调用。稍等片刻你就能看到从我们Server返回的结构化天气信息。实操中的坑与心得路径与权限配置文件路径错误或Python脚本没有执行权限是最常见的启动失败原因。务必检查日志Claude Desktop通常有日志输出位置。环境变量敏感信息如API密钥一定要通过env配置或外部文件读取不要硬编码在脚本中。错误处理Server代码中必须有完备的错误处理如try-catch并将错误信息以用户和AI可读的方式返回。一个崩溃的Server会导致客户端连接中断。描述的质量工具description和参数的description直接决定了AI调用的准确性。花时间打磨这些描述就像在编写API文档一样。可以先用自然语言多角度描述工具功能再提炼成简洁准确的句子。通过这个实战你应该能清晰地感受到MCP Server的本质就是一个标准的、带有声明式接口资源/工具的后端服务。AI模型通过MCP协议这个“通用插座”就能安全、可控地使用这个服务的能力。5. 生态现状与未来MCP如何重塑AI应用开发MCP协议虽然年轻但其“连接器”的定位迅速催生了一个活跃的早期生态。理解这个生态的构成能帮助我们看清未来的可能性。5.1 蓬勃发展的Server生态从搜索到数据库目前MCP Server主要围绕几类核心需求展开搜索与信息获取这是最直观的需求。tavily-mcp、brave-search-mcp等Server将独立的搜索API封装成MCP工具让AI模型能实时获取网络信息突破了其训练数据的时间限制。软件开发与运维这是MCP目前最活跃的领域之一。例如文件系统filesystemServer让AI能读写指定目录的文件是实现“AI编程助手”的基础。Git操作gitServer允许AI查看仓库状态、提交历史甚至进行简单的提交操作。命令行command-lineServer需极其谨慎地配置权限允许AI在沙箱中执行Shell命令用于构建、测试等。数据库postgres-mcp、sqlite-mcp等Server让AI能安全地查询数据库通常只读或限制写操作用于数据分析和内容生成。创意与多媒体dalleServer集成图像生成musicServer可能集成音频处理拓展AI的创意边界。系统与硬件bluetooth、serial-port等Server展示了MCP连接物理世界的潜力虽然目前应用较少且需高度关注安全。一个关键趋势是“专业化”早期的Server可能提供大而全的功能但未来的Server会更专注于单一垂直领域并提供更深度的能力。例如一个专为法律文档分析的MCP Server其提供的“资源”和“工具”会远比通用的文件系统Server更加精细和贴合场景。5.2 主流客户端支持协议落地的推手协议的价值在于被广泛采用。MCP在这方面进展迅速Claude DesktopAnthropic自家的产品是MCP的“首发平台”和最佳试验场。其配置相对简单是开发和测试MCP Server的首选。Cursor这款以AI为核心的代码编辑器深度集成了MCP。你可以在Cursor的设置中直接搜索和添加社区发布的MCP Server如GitHub、文件系统体验“开箱即用”的工具增强。Windsurf另一款AI原生代码编辑器也将MCP作为其核心扩展机制。Codex虽然搜索结果中提到了“添加进codex的详细步骤”但通常指的是通过配置将这些MCP Server集成到类似Cursor/Claude这类以AI为核心的开发环境中而不是一个叫Codex的独立产品。这反映了社区用户积极尝试整合各种工具的努力。客户端的竞争本质上是在竞争“最好的AI工具平台”。谁能为AI模型集成更多、更强大的工具谁就能提供更强大的用户体验。MCP协议降低了集成的门槛成为了这场竞争的基础设施。5.3 对开发者意味着什么技能栈与机会如果你想投身于AI Agent开发MCP是你必须了解的技术栈之一。你需要具备的技术能力后端开发基础MCP Server本质是后端服务。你需要熟悉至少一门服务器端语言Python、Node.js、Go等了解HTTP、WebSocket/SSE等网络通信原理。API设计与集成能力大部分MCP Server的工作是“包装”现有的API或系统。你需要懂得如何设计清晰、安全的接口并处理认证、限流、错误等问题。异步编程高效的MCP Server需要处理并发请求异步编程模型如Python的asyncioNode.js的Async/Await几乎是必备技能。安全思维这是重中之重。暴露给AI的工具必须经过严格的安全审查。要遵循最小权限原则对输入进行严格的验证和清理防止提示词注入、任意命令执行等攻击。例如一个“执行SQL”的工具绝不能允许AI拼接原始SQL语句。对AI模型行为的理解你需要学会从AI的视角思考。工具描述怎么写它才能懂它会在什么情况下误用工具如何设计工具的参数和返回值格式能让AI更稳定地解析和使用未来的机会开发垂直领域的专业MCP Server将你在某个行业如金融、法律、医疗、电商的领域知识封装成高质量的MCP工具会有巨大的市场潜力。构建MCP Server开发框架与工具链简化Server的创建、测试、调试和分发流程。比如一个能一键生成MCP Server脚手架的工具。MCP Server的“应用商店”与治理随着Server数量爆炸式增长如何发现、评级、安全审计和管理这些Server会成为一个新的需求。这类似于手机应用商店的早期阶段。MCP协议正在做的是将AI从“无所不知但无能为力”的预言家变成“既懂又能干”的助手。它没有试图创造一个全能型的超级AI而是选择了一条更务实、更开放的路径标准化连接赋能生态。作为开发者我们不再需要等待某个巨头发布一个包含所有功能的“终极AI平台”而是可以像拼乐高一样用MCP这个“通用接口”为自己、为团队、为垂直领域组装出最趁手的AI工具链。这或许才是AI技术民主化和真正普及的开始。