尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

MCP 核心概念讲解

MCP 核心概念讲解 MCPModel Context Protocol模型上下文协议是一套开放协议用于让 AI 应用Host以标准化的方式接入外部工具、数据源和交互界面。本文是 MCP 的概念篇讲是什么角色、原语、传输方式、真实报文、设计思想。想看完整生命周期怎么串起来见 mcp端到端流程.md。1. 一句话理解 MCPMCP 解决的痛点是大模型LLM本身只会说话不会执行动作。它无法读你的文件、查数据库、发请求。MCP 给 LLM 提供了手和眼睛——通过一组标准化的接口让 LLM 能调用外部能力并把结果拿回来继续推理。类比对 LLM 而言MCP 相当于USB-C 接口任何支持这个标准的外设工具、数据源都能即插即用。对开发者而言MCP 是“AI 的 USB 标准”写一次 Server就能被所有支持 MCP 的 AI 助手复用。一句话总结LLM 负责想MCP 负责做。LLM 通过 MCP 把意图翻译成对工具的调用拿到结果后继续推理最终把答案讲给你听。架构 流程一张图看懂角色分层 数据往返┌─────────────────────┐ │ 你用户 │ └──────────┬──────────┘ │ ① 提问「帮我查一下上个月的销售数据」 ▼ ╔═════════════════════════════════════════════════════╗ ║ HOST (AI 应用如 CodeBuddy) ║ ║ ║ ║ ┌─────────────────────┐ ║ ║ │ 大模型 LLM │ ② 理解意图需要查数据库 ║ ║ └──────────┬──────────┘ ║ ║ │ ③ 决定调用工具按 MCP 协议发起请求 ║ ║ ▼ ║ ║ ┌─────────────────────┐ ║ ║ │ MCP Client │ ← 协议连接器替 LLM ║ ║ └──────────┬──────────┘ 跟某个 Server 一对一通信║ ║ │ ④ JSON-RPC (stdio/HTTP) ║ ╚══════════════╪══════════════════════════════════════╝ ▼ ┌─────────────────────┐ │ MCP Server │ ⑤ 执行真实逻辑 └──────────┬──────────┘ │ ⑥ 调用/查询 ▼ ┌─────────────────────┐ │ 外部系统 │ ← 数据库、GitHub、文件、企业 API └──────────┬──────────┘ │ ⑦ 数据沿 MCP 原路返回 ▼ ┌─────────────────────┐ │ 大模型 LLM │ ⑧ 拿到结果继续推理 └──────────┬──────────┘ 回到 Host 内的 LLM │ ⑨ 整理成你想要的格式 ▼ ┌─────────────────────┐ │ 你用户 │ ← 获得答案 └─────────────────────┘2. 三个角色别搞混2.1 角色表职责对照官方规范角色官方定义在本案例中职责HostLLM 应用程序发起连接的一方CodeBuddy整个程序初始化连接、启动/关闭 server 子进程stdio 模式、管理会话、管理用户授权与数据访问、整合结果Client宿主应用内的连接器与某个 Server一一对应CodeBuddy 内部针对local-time的 Client与 server.js 一对一通信发请求、收响应、翻译协议tools/list、tools/call 都是它发的Server提供上下文和能力的服务server.js本项目暴露 Resources/Prompts/Tools监听 stdin、执行工具、经 stdout 返回┌───────────────────────────────────────────────┐ │ HOST │ │ (CodeBuddy, AI 应用) │ │ │ │ ┌─────────────┐ ┌──────────────────┐ │ │ │ LLM │ 决策 │ MCP Client │ │ │ │ (大模型) │──────▶│ (协议连接器) │ │ │ └─────────────┘ └────────┬─────────┘ │ └───────────────────────────────────┼──────────┘ │ JSON-RPC 2.0 │ (stdio / Streamable HTTP) ▼ ┌─────────────────────┐ │ MCP Server │ │ (server.js) │ │ Tools/Resources/ │ │ Prompts │ └──────────┬──────────┘ │ 调用 ▼ ┌─────────────────────┐ │ 外部系统 │ │ (文件/DB/GitHub/API)│ └─────────────────────┘2.2 关键澄清CodeBuddy 不是 Client它是 Host。Client 是 Host 内部的组件。一个 HostCodeBuddy可以同时管理多个 Client每个 Client 连一个 Server比如local-time、TDesign各一个。stdio 模式下Server 是 Host 启动的子进程运行在 Host 所在的机器上而 Streamable HTTP 模式下Server 是独立常驻的服务进程不隶属于 Host详见 4.1 传输方式。官方规范强调Host 负责用户授权与数据访问控制——比如工具调用代表任意代码执行需先获得用户同意这也是 CodeBuddy 里需要Trust信任连接器的原因。3. 核心原语Primitives先澄清一个易混淆点modelcontextprotocol/sdk同时提供Server 端McpServer和Client 端Client的 API。本仓库server.js只用到 Server 端用来暴露工具给 Host 调用Client 端则是 Host如 CodeBuddy内部用来连 Server 的。所以当你写一个 MCP Server时只需要接触 Server 端 API——协议里那句一个 Client 对一个 ServerServer 端只需要做好自己的本分。MCP 围绕三类能力展开称为Primitives——Server 暴露给 LLM 的能力入口。原语作用类比本项目是否有Tools工具LLM 主动调用执行操作有副作用函数调用 / Function Calling✅get_current_time等 4 个Resources资源暴露只读数据供 LLM 读取上下文文件、数据库查询结果❌暂无Prompts提示词预定义的交互模板复用常见任务流程代码片段 / 模板❌暂无3.1 Tools —— 最常用特点由LLM 决定是否调用Model-controlled。使用模式tools/list发现→tools/call调用→ 返回结果。本项目 4 个工具的定义方式get_current_time、format_time、time_diff、list_timezones结构一致以get_current_time为例server.tool(get_current_time,// 工具名获取当前时间。传 local 获取本地时间...,// 描述LLM 靠它判断何时调用{tz:z.string().optional()...},// 参数 schemaZod 校验async({tz}){...}// 实际执行逻辑);3.2 Resources —— 只读数据特点由Host 决定加载Host-controlled为 LLM 补充上下文。标识用URI如file:///...、time://now唯一标识。使用模式resources/list→resources/read。server.resource(time-now,time://now,async(uri)({contents:[{uri,text:newDate().toISOString()}],}));3.3 Prompts —— 模板特点由用户或 Host 主动触发User-controlled复用复杂任务流程。使用模式prompts/list→prompts/get。3.4 三个原语的谁控制对比原语谁决定触发数据方向有无副作用ToolsLLM双向可写有ResourcesHostServer → LLM只读无Prompts用户/HostHost → Server读模板无4. 通信协议JSON-RPC 2.0 TransportMCP 的语言是JSON-RPC 2.0。所有请求/响应都是 JSON 消息通过Transport传输层交换。4.1 传输方式传输方式说明适用场景stdio通过标准输入输出通信Server 作为子进程启动本地、单机本项目Streamable HTTP通过 HTTP/SSE 通信远程、跨机、Webstdio 的三件套在 Node SDK 中import{McpServer}frommodelcontextprotocol/sdk/server/mcp.js;import{StdioServerTransport}frommodelcontextprotocol/sdk/server/stdio.js;constservernewMcpServer({name:local-time-server,version:1.0.4});consttransportnewStdioServerTransport();awaitserver.connect(transport);4.2 stdin / stdout 具体是什么stdio标准输入输出是操作系统给每个进程默认配备的三个数据管道管道简称作用在 MCP 中标准输入stdin程序读入数据读 Client 发来的 JSON-RPC 请求标准输出stdout程序输出数据写出 JSON-RPC 响应标准错误stderr程序输出错误信息打印日志不参与协议在stdio传输下Server 是被 Host 作为子进程启动的。Host 的 Client 和 Server 子进程之间就通过这一根 stdin 和一根 stdout 连线┌──────────────┐ ┌──────────────┐ │ client 进程 │ │ server.js 子进程│ └──────┬───────┘ └──────┬───────┘ │ │ │ ① 往 Server 的 stdin 写入请求 │ │───────────────────────────────────────────▶│ │ {id:2,method:tools/list,params:{}}│ │ │ │ │ ② 处理工具逻辑 │ │ 发现有哪些工具 │ ③ 从 Server 的 stdout 读取响应 │ │◀───────────────────────────────────────────│ │ {id:2,result:{tools:[...]}} │ │ │ ▼ ▼写请求 往 Server 的stdin里write一个 JSON 消息。读响应 监听 Server 的stdout按换行切分出一条条 JSON 消息。每条消息以jsonrpc、id请求与响应用id对应、method、result/error这些字段组成 —— 这就是JSON-RPC 2.0。注JSON 本身允许跨行但 MCP 的 stdio 实现StdioServerTransport约定按换行符分隔消息即一行一条消息readline逐行读取因此发送方需把每条消息序列化后放在同一行。StdioServerTransport这个类做的正是往 stdin 读、往 stdout 写、按行切分 JSON、用 id 匹配请求响应这些琐事。5. 真实报文长什么样tools/list 与 tools/call以上是抽象描述下面给出一份本项目的真实报文实际运行时抓取。MCP stdio 下每行 JSON 一条消息。① 握手 initialize initialized官方完整握手是三步① Client → Server写往 Server 的 stdin{jsonrpc:2.0,id:1,method:initialize,params:{protocolVersion:2024-11-05,capabilities:{},clientInfo:{name:my-app,version:1.0.4}}}② Server → Client写往 stdout{result:{protocolVersion:2024-11-05,capabilities:{tools:{listChanged:true}},serverInfo:{name:local-time-server,version:1.0.4}},jsonrpc:2.0,id:1}③ Client → Server写往 stdin通知初始化完成无响应{jsonrpc:2.0,method:notifications/initialized}完整握手 三步initialize 请求 → initialize 响应 → initialized 通知。三步都完成才允许后续请求如 tools/list。② tools/list —— 列出有哪些工具请求stdin{jsonrpc:2.0,id:2,method:tools/list,params:{}}响应stdout——截取一个工具为例{result:{tools:[{name:get_current_time,description:获取当前时间。传 local 获取本地时间或传 IANA 时区名...,inputSchema:{$schema:http://json-schema.org/draft-07/schema#,type:object,properties:{tz:{type:string,description:时区名称默认 local}}}}]},jsonrpc:2.0,id:2}inputSchema里的内容其实就是你在server.tool(get_current_time, 描述, { tz: z.string()... })中写的描述 Zod schema。SDK 会自动把它转成标准 JSON Schema 返回给 LLM。③ tools/call —— 真正调用工具请求stdin{jsonrpc:2.0,id:3,method:tools/call,params:{name:get_current_time,arguments:{tz:Asia/Shanghai}}}响应stdout{result:{content:[{type:text,text:{\datetime\:\2026-08-06T02:21:49Z\,\timezone\:\Asia/Shanghai\,\utc_offset\:\0800\,\readable\:\2026年08月06日 10:21:49\,\unix_timestamp\:1785982909}}]},jsonrpc:2.0,id:3}content正是你在回调里return { content: [{ type: text, text: ... }] }写的东西。字段对照代码 ↔ 报文你在server.tool()里写的变成报文里的工具名get_current_timetools.list[].name描述字符串tools.list[].descriptionZod schematz 等参数tools.list[].inputSchemaJSON Schema回调return { content:[...] }tools/call响应的result.content6. 关键设计思想6.1 分层解耦协议层JSON-RPC Transport负责怎么传。能力层Tools/Resources/Prompts负责传什么。业务层你的函数逻辑负责做什么。写 MCP Server核心就是用协议层包裹你的业务函数让 LLM 能通过标准接口调用它。6.2 Schema 驱动工具的参数 schema本项目用 Zod不只是校验输入更重要的是告诉 LLM 每个参数的含义和格式LLM 才能生成正确的调用参数。描述写得好不好直接决定 LLM 会不会用对。6.3 一个 Client 对一个 Server每个 Server 进程只服务一个 Client 连接。要服务多个应用/连接就启动多个 Server 进程或改用支持多会话的 HTTP Transport。6.4 错误处理要结构化LLM 需要能程序化判断调用是否成功。返回结构化 JSON而非散落的中文错误串能让 LLM 更好地决定下一步。本项目的工具统一返回{error: ...}或正常的 JSON 结果。7. 官方参考MCP 规范主页含最新版本https://modelcontextprotocol.io/specification/2024-11-05架构与角色https://modelcontextprotocol.io/docs/architecture基础协议握手/生命周期/传输https://modelcontextprotocol.io/specification/2024-11-05/basic/lifecycle服务器原语Resources/Prompts/Toolshttps://modelcontextprotocol.io/specification/2024-11-05/server/工具规范tools/list、tools/callhttps://modelcontextprotocol.io/specification/2024-11-05/server/tools客户端功能Samplinghttps://modelcontextprotocol.io/specification/2024-11-05/client/注MCP 仍在演进各版本规范有差异。本文锚定2024-11-05撰写链接也指向该版本本项目使用的 Node SDKmodelcontextprotocol/sdk1.30在握手时会协商并实际采用更新的协议版本2025-06-18。两者在本文涉及的握手流程、tools/list、tools/call上行为一致故不影响理解。若需对照最新规范可将上方链接中的2024-11-05替换为2025-06-18。 感谢阅读想了解更多 我的博客网站 | 记录思考分享干货 我的个人主页 | 关于我、开源项目
返回列表