news 2026/9/26 12:41:51

MCP--自我学习用

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MCP--自我学习用

MCP 全称Model Context Protocol(模型上下文协议),是由 Anthropic 发起、现由 Linux 基金会托管的开放行业标准,专门解决AI Agent 与外部工具、数据源之间的标准化接入问题。它定义了一套统一的通信规则、能力发现机制和交互格式,让任意符合规范的 AI 应用都能无缝调用任意符合规范的外部能力,被称为「AI 时代的通用工具接口标准」。

Host-Client-Server 的三级架构

角色定位核心职责典型实例
Host(宿主)AI 应用本体管理大模型、执行业务逻辑、统筹所有工具会话Claude Desktop、VS Code、Cursor、自研 Agent 平台
Client(客户端)连接器 / 协议适配器每个服务端对应一个独立 Client;负责协议握手、消息路由、会话管理、安全隔离Host 内置的 MCP 客户端模块
Server(服务端)能力提供方把底层的 API、数据库、文件系统等包装成标准 MCP 能力对外暴露文件系统服务、数据库服务、第三方业务工具

一个Host可以同时管理多个 Client,每个 Client 对应一个独立的 Server 连接,不同的工具之间天然隔离,互不影响

两层协议分层

MCP 把协议拆分为独立的两层,底层通信变化不影响上层业务逻辑

数据层(内层):基于 JSON-RPC 2.0 标准,定义所有业务消息的格式,语义和交互流程,包括生命周期管理,核心原语,通知机制。这一层和传输方式无关,是协议的核心

传输层(外层):定义客户端和服务端之间的通信通道,主流支持两种传输方式,1.stdio(标准输入输出),用于本地进程间通信,延迟极低,适合本地工具服务,2.HTTP:用于远程服务通信,支持跨网络,跨部署,适合第三方云服务

核心原语

原语(Primitives)是 MCP 协议的核心,规定了服务端可以对外暴露的能力类型,以及客户端可以提供的回调能力,所有交互都基于这些标准原语展开。

服务端原语:

服务端通过这三类原语对外暴露能力,也是 Agent 开发最常用的部分:

1.Tools(工具):可执行的函数,是最核心的原语。Agent 可以调用工具执行操作,比如查询数据库、调用业务 API、操作文件、执行命令。对应标准方法tools/list(发现工具)、tools/call(调用工具)。

2.Resource(资源):给模型提供上下文的数据,比如文件内容、表结构、文档片段。模型只能读取,不能修改,适合给模型注入静态背景信息。

3.Prompts(提示模板):可复用的提示词模板,比如少样本示例、工具使用引导、系统提示,用来统一模型和工具的交互方式。

客户端原语:
服务端也可以反向向客户端请求能力,这是 MCP 和普通 API 最大的区别之一:

1.Sampling(采样):服务端可以请求客户端的大模型生成文本,比如工具执行到一半需要模型做决策,不用自己集成大模型 SDK。

2.ELicitation(引导):服务端可以请求用户补充信息或确认操作,比如高危操作前向用户二次确认。

3.Logging(日志):服务端可以向客户端发送日志,用于统一调试和监控

标准扩展位 _meta字段:

协议专门在消息结构中预留了_meta字段,用于传输带外元数据,比如用户身份、会话 ID、链路追踪信息等。这类数据不属于业务参数,不应该塞进工具的 arguments 里,_meta就是标准的存放位置 —— 这也是你之前笔记里「身份走 _meta」的规范依据。

完整的工具链与工具调用生命周期

一次标准的 MCP 工具调用,从连接建立到结果返回,遵循严格的标准化流程:

1.初始化与能力协商:

Host 创建 Client,向目标 Server 发起 initialize 请求,携带客户端支持的能力、协议版本

Server 返回自身支持的能力,协议版本,可用的原语范围

Client 发送 notifications/initialized 通知,确认握手完成,会话进入就绪状态

2.工具发现

Client 调用 tools/list 方法,向 Server 查询当前可用的所有工具

Server 返回工具列表,包含每个工具的名称、描述、参数 Schema(JSON Schema 格式)

Client 把工具列表同步给 Host,Host 将其注入大模型的上下文,供模型决策调用

3.工具调用与结果返回

模型决定调用某个工具,输出工具调用意图

Client 封装成标准的 tools/call 请求,发送给 Server

Server 执行工具,返回结构化结果(成功/错误都遵循统一格式)

Client 把结果回传给 Host,注入对话历史,模型基于结果继续生成回答

MCP vs Function Calling

维度Function CallingMCP
层级模型能力层通信协议层
核心作用让模型输出结构化的工具调用意图让工具以标准方式接入、被发现、被调用
工具发现静态,工具 Schema 写死在 prompt 或代码里动态,运行时通过tools/list实时获取
跨厂商兼容不兼容,每个厂商格式有差异统一标准,任意模型、任意工具都能对接
部署形态和应用同进程工具服务独立部署,天然隔离

Function Calling 是「模型怎么说要调工具」,MCP 是「工具怎么接进来、怎么执行」。生产环境中通常两者配合使用:模型用 Function Calling 生成调用意图,通过 MCP 协议真正执行调用。

MCP vs 自定义 REST API

维度自定义 REST APIMCP
面向对象面向人类开发者、服务间调用面向 AI 模型、Agent 自动调用
发现方式静态文档(Swagger/OpenAPI),设计时确定运行时动态发现,工具可实时增减
集成成本M×N 复杂度:每接一个新工具,每个 Agent 都要写适配M+N 复杂度:工具和 Agent 各接一次标准协议,即可互通
状态管理默认无状态有状态会话,上下文跨调用保留
安全边界接口级鉴权,逻辑分散在每个接口协议层统一鉴权、隔离、审计

REST 是通用的服务间通信协议,MCP 是专门为 AI Agent 优化的工具接入协议

用官方 Python SDK 写的最小化服务端+客户端,完整走通「初始化→列工具→调工具」全流程

1.服务端

import asyncio from mcp.server.fastmcp import FastMCP #创建 MCP 服务实例 mcp=FastMCP("DemoCalculator") #注册一个工具 - 自动生成 inputSchema,自动暴露给 tools/list @mcp.tool() def add(a: int, b: int) -> int: """Add two integers together""" return a + b if __name__=="__main__": #stdio 传输模式(本地进程通信) mcp.run(transport="stdio")

2.客户端

通过 stdio 连接服务端,完成完整调用流程

import asyncio from mcp.client.stdio import stdio_client from mcp.client.session import ClientSession async def main(): #建立 stdio 传输通道,启动子进程运行服务端 async with stdio_client(["python", "server.py"]) as (read, write): #创建会话,执行 initialize 握手 async with ClientSession(read, write) as session: await session.initialize() # 调用 tools/list 获取工具列表 tools=await session.list_tools() print("可用工具: ") for tool in tools.tools: print(f" - {tool.name}: {tool.description}") #调用 tools/call 执行 add 工具 result=await session.call_tool("add", {"a":5, "b":3}) print(f"\n调用结果:{result.content[0].text}") if __name__=="__main__": asyncio.run(main())

核心方法的源码级实现

tool/list 的底层实现

tools/list 请求的处理逻辑本质就是遍历注册的工具,返回标准化结构

async def handle_list_tools(self, request:ListToolRequest) -> ListToolsResult: tools=[] for name, tool in self._tool_registry.items(): tools.append({ "name": name, "description": tool.description, "inputSchema": tool.input_schema # JSON Schema 格式 }) return ListToolsResult(tools=tools)

客户端收到后,会把这个列表转换成模型能理解的 Function Calling 格式,注入 prompt(这一步又是怎么实现的)

tools/call 的底层实现

async def handle_call_tool(self, request:CallToolRequest) -> CallToolresult: tool_name=request.params.name arguments=request.params.arguments #从注册表查找工具 if tool_name not in self._tool_registry: return CallToolResult( content=[{"type": "text", "text": f"Unknown tool: {tool_name}"}], isError=True ) try: #执行工具函数 result=await self._tool_registry[tool_name].handler(**arguments) #包装成标准返回格式 return CallToolResult( content=[{"type":"text", "text":str(result)}] ) except Exception as e: #结构化错误返回 return CallToolResult( content=[{"type": "text", "text": str(e)}], isError=True )
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/26 12:41:42

WorkBuddy 深度使用指南:从安装到进阶的 AI 办公助手实战

1. 为什么值得花时间把 WorkBuddy 用明白第一次接触 WorkBuddy 是在一个赶交付的深夜,当时手头压着三份文档要整理、两段代码要补注释、还有一堆会议纪要等着归档。同事甩过来一句"你试试 WorkBuddy,能省不少事",我半信半疑装上了。…

作者头像 李华
网站建设 2026/9/26 12:40:39

Java语法进阶:从字节码看穿语法糖与泛型擦除的底层原理

从"会写Java"到"真正懂Java语法",中间其实隔着一整层编译器和字节码。这阵子帮团队做代码评审,经常看到有同事语法用得飞起,但问到底层原理就含糊了——比如for-each和普通for循环到底差在哪,switch为什么能判…

作者头像 李华
网站建设 2026/9/26 12:40:35

参与感与硬件即渠道:拆解小米模式背后的杠杆效应

我研究过小米这套商业打法很久,有一个很深的感受:很多企业把“参与感”做成了客服,把“硬件低价”做成了自残,把“互联网思维”做成了口号。但真正的秘密不在这几个词各自代表什么,而在它们连成一条线之后产生的杠杆效…

作者头像 李华
网站建设 2026/9/26 12:39:45

工业物联网纯上报设备数采:单向链路架构设计与实战

干这行久了你会发现,"数采"这词儿听着基础,跟吃饭喝水一样日常,但碰上工业物联网里那批纯上报设备,难度立马不一样。所谓纯上报设备,就是只管往外吐数据、压根儿不听你指挥的那类老古董或者功能受限的终端—…

作者头像 李华
网站建设 2026/9/26 12:39:36

LLM流式对话架构设计与实战:SSE、WebSocket选型及前后端实现

1. 通用 LLM 流式对话的架构选型与设计思路 1.1 为什么流式输出是对话类产品的分水岭 做过对话机器人的朋友大概都有这个体会:非流式接口跑通之后,本地测试一切正常,一上线就被用户吐槽“卡”。原因很简单,大模型生成一段三百字的…

作者头像 李华