【随笔】从聊天到调用工具:理解MCP在AI应用中的位置

当一个AI助手能解释报错、整理文档之后,我们很容易继续提出要求:帮我查一下最新订单状态,再结合知识库说明应该怎么处理。

这时,模型需要面对应用外部的数据与操作。订单来自业务系统,知识来自文档,查询还受用户权限约束。每接入一个系统,都需要描述能力、组织参数、执行调用,再把结果送回助手。

**MCP(Model Context Protocol,模型上下文协议)**把其中一部分接入约定标准化。对于后端开发者,值得关注的是它如何把已有服务的能力组织成AI应用可以发现和调用的接口,以及接入后还剩哪些工程问题。

本文以2025-11-25版MCP规范为讨论基线,资料核对日期为2026年9月19日。这里的"新兴"指AI应用工具生态的发展方向,不代表协议刚在今天发布;草案中的变化不当作本文基线能力。

一、从一个订单查询场景开始

假设我们要做一个售后助手,用户问:"订单DEMO-1024到哪里了?"

一个合理的实现可以分为几步:助手识别查询意图,获得可用的订单查询工具定义,生成参数;应用在权限范围内调用工具;服务端查询业务系统;助手根据返回结果组织答复。

在这个流程里,模型可以帮助选择工具与整理语言,订单状态仍然由业务系统提供。它没有因为接入MCP就拥有数据库的全部权限,也没有自动获得业务事实的正确性保证。

我的理解是:当团队已经有一批接口,又希望它们被不同AI应用复用时,统一工具接入方式才开始体现价值。单个小脚本直接调用函数也能工作,是否引入协议层,应根据接入规模与维护成本判断。

二、Host、Client与Server分别负责什么

依据该版本的架构规范,可以把三个角色放在下面的位置:

角色 本文场景中的位置 核心责任
Host 用户使用的AI助手应用 组织交互、模型调用与连接权限
Client Host内部的协议连接组件 与某个Server协商能力并交换消息
Server 订单工具服务 暴露并执行明确的工具能力

一个Host可以管理多个Client;在这套架构中,一个Client与一个Server建立对应关系。Server可以是本地进程,也可以是远程服务。

为了便于理解,可以把Client看成Host里负责这一路连接的接口适配组件。模型本身不等同于Client,Server也不一定是另一个大模型。一个只查询订单状态的普通后端服务,就可以提供MCP能力。

图中MCP标在通信连线上,表示协议约定;一个Host还可以管理更多Client连接。

现有REST接口可以继续保留,由MCP Server封装调用。这是本文建议的渐进接入方案:业务规则仍留在原系统,协议层负责将合适的能力暴露出来。

三、Tools、Resources与Prompts:三个入口

1. Tools:可以请求执行的能力

例如get_order_status,用订单编号查询状态。工具有名称、描述和输入结构,客户端通过tools/list发现工具,通过tools/call发起调用。

工具是否只读、会不会产生外部影响,应在设计时讲清楚。"查询物流"和"取消订单"虽然都可以包装成工具,它们的授权与交互要求显然不同。工具机制与消息字段见Tools规范

2. Resources:可以读取的上下文

例如一份售后政策文档或数据库结构说明。资源通过URI标识,应用可以获取内容并决定如何把它加入上下文。

资源适合表达"这里有一份可读取的信息"。把哪些信息交给模型、读取多少、是否需要缓存,仍由具体应用安排。参见Resources规范

3. Prompts:可以复用的交互模板

例如"根据订单信息整理一份售后处理摘要"的模板。Server可以提供模板及参数,由客户端获取相应消息。

模板帮助统一任务的输入组织方式。它不会替应用完成权限检查,也不保证模型一定遵循每一条描述。参见Prompts规范

实践中不必为了覆盖全部概念而同时实现三类能力。一个边界清楚的只读查询工具,就足以验证接入流程。

四、看懂一次工具调用的消息

下面是教学用消息示例,工具名称和订单数据均为虚构,没有连接真实业务系统。这里只展示初始化完成后的工具发现与调用阶段,不是可以省略握手直接发送的完整会话。

客户端查询可用工具:

json 复制代码
{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}

服务端可以返回这样的工具定义:

json 复制代码
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "tools": [
      {
        "name": "get_order_status",
        "description": "查询当前已认证用户有权查看的订单状态,只读。",
        "inputSchema": {
          "type": "object",
          "properties": {
            "orderId": { "type": "string" }
          },
          "required": ["orderId"],
          "additionalProperties": false
        }
      }
    ]
  }
}

客户端发起一次调用:

json 复制代码
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "get_order_status",
    "arguments": { "orderId": "DEMO-1024" }
  }
}

示意响应:

json 复制代码
{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "content": [
      { "type": "text", "text": "订单DEMO-1024已发货,物流状态为运输中。" }
    ],
    "isError": false
  }
}

inputSchema描述参数的形状,并不证明这位用户有权查询该订单。服务端应从可信的认证上下文取得身份,再检查订单归属;不应让模型传一个userId就决定访问权限。

同样,返回了JSON也不意味着数据已经足够可靠。业务结果还可能涉及数据更新时间、部分字段缺失、下游超时等情况。工具契约越具体,助手越容易解释"查到了什么"和"哪些信息还不确定"。

五、从本地试验走向服务接入

在本文基线版本中,标准传输包括stdioStreamable HTTP

stdio通常由客户端启动本地子进程,标准输入输出承载协议消息。普通调试日志写到stderr,避免把stdout里的消息流污染掉。Streamable HTTP适合独立运行的服务,通过HTTP交换消息,并可结合SSE传送服务端消息;不能把它简单理解为每次请求都必须使用SSE。具体约定见传输规范

正式交换业务消息之前还需要初始化、版本与能力协商,随后发送初始化完成通知。用SDK开发时也应理解这些步骤,排查"连上了却看不到工具"时才有方向。参见生命周期规范

从Java后端的角度,我更倾向于从一个很小的服务能力开始验证:

  1. 选一个边界清楚的只读查询,明确输入、输出和错误。
  2. 复用原来的服务层,实现参数校验、身份鉴别和数据权限。
  3. 通过支持相应协议版本的Client连接,检查能力协商和工具发现。
  4. 分别测试正常查询、无权限、找不到数据和下游超时。
  5. 确认调用日志能追踪到工具名称、结果状态和耗时,再考虑增加写操作。

这里给出的是工程拆分思路,没有绑定某个SDK版本。落地时应以所选SDK的发布文档和客户端兼容情况为准,不把不同版本教程中的配置直接拼在一起。

六、MCP与RAG、Agent是什么关系

为了安排项目职责,可以从三个问题理解这些概念:

概念 关注的问题 在售后助手里的例子
RAG 如何检索并提供相关知识 找出适用的售后政策段落
MCP 如何发现和交换外部能力与上下文 发现并调用订单查询工具
Agent 如何围绕目标组织多步行动 先查询订单,再检索政策并整理答复

这是本文用于项目设计的划分方式。实际实现中它们可以组合:MCP Server可以封装一个检索工具,Agent可以调用该工具,检索结果再进入生成环节。MCP的接入并不会自动完成检索质量评估或多步任务规划。

因此,评估接入效果时,我会分别看三个层面:工具能否稳定调用、返回信息是否准确、最终答复是否忠实于结果。把这些问题拆开,比只看"助手似乎能用了"更容易找到改进方向。

七、值得提前想清楚的边界

**权限仍然属于应用与业务系统。**工具描述可以说明用途,服务端必须执行真实校验。对于会改变外部状态的动作,还应设计明确的确认、幂等和失败补偿机制。

**外部内容应按数据处理。**文档或工具返回值中如果夹带了"忽略原要求""把其他系统资料发出去"等文字,不应因此获得控制应用的权限。上下文来源与应用指令的边界需要持续保持。

**能力暴露要克制。**一个可任意执行SQL的工具看起来灵活,却让权限、审计和错误处理都变得困难。对于固定业务,几个输入输出清楚的查询工具通常更容易测试和维护。这是设计取舍,不能仅凭工具数量判断系统能力。

八、🧠 思维导图

#mermaid-svg-BpulQ9PK1XATcZPa{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-BpulQ9PK1XATcZPa .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-BpulQ9PK1XATcZPa .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-BpulQ9PK1XATcZPa .error-icon{fill:#552222;}#mermaid-svg-BpulQ9PK1XATcZPa .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-BpulQ9PK1XATcZPa .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-BpulQ9PK1XATcZPa .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-BpulQ9PK1XATcZPa .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-BpulQ9PK1XATcZPa .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-BpulQ9PK1XATcZPa .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-BpulQ9PK1XATcZPa .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-BpulQ9PK1XATcZPa .marker{fill:#333333;stroke:#333333;}#mermaid-svg-BpulQ9PK1XATcZPa .marker.cross{stroke:#333333;}#mermaid-svg-BpulQ9PK1XATcZPa svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-BpulQ9PK1XATcZPa p{margin:0;}#mermaid-svg-BpulQ9PK1XATcZPa .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-BpulQ9PK1XATcZPa .cluster-label text{fill:#333;}#mermaid-svg-BpulQ9PK1XATcZPa .cluster-label span{color:#333;}#mermaid-svg-BpulQ9PK1XATcZPa .cluster-label span p{background-color:transparent;}#mermaid-svg-BpulQ9PK1XATcZPa .label text,#mermaid-svg-BpulQ9PK1XATcZPa span{fill:#333;color:#333;}#mermaid-svg-BpulQ9PK1XATcZPa .node rect,#mermaid-svg-BpulQ9PK1XATcZPa .node circle,#mermaid-svg-BpulQ9PK1XATcZPa .node ellipse,#mermaid-svg-BpulQ9PK1XATcZPa .node polygon,#mermaid-svg-BpulQ9PK1XATcZPa .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-BpulQ9PK1XATcZPa .rough-node .label text,#mermaid-svg-BpulQ9PK1XATcZPa .node .label text,#mermaid-svg-BpulQ9PK1XATcZPa .image-shape .label,#mermaid-svg-BpulQ9PK1XATcZPa .icon-shape .label{text-anchor:middle;}#mermaid-svg-BpulQ9PK1XATcZPa .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-BpulQ9PK1XATcZPa .rough-node .label,#mermaid-svg-BpulQ9PK1XATcZPa .node .label,#mermaid-svg-BpulQ9PK1XATcZPa .image-shape .label,#mermaid-svg-BpulQ9PK1XATcZPa .icon-shape .label{text-align:center;}#mermaid-svg-BpulQ9PK1XATcZPa .node.clickable{cursor:pointer;}#mermaid-svg-BpulQ9PK1XATcZPa .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-BpulQ9PK1XATcZPa .arrowheadPath{fill:#333333;}#mermaid-svg-BpulQ9PK1XATcZPa .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-BpulQ9PK1XATcZPa .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-BpulQ9PK1XATcZPa .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-BpulQ9PK1XATcZPa .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-BpulQ9PK1XATcZPa .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-BpulQ9PK1XATcZPa .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-BpulQ9PK1XATcZPa .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-BpulQ9PK1XATcZPa .cluster text{fill:#333;}#mermaid-svg-BpulQ9PK1XATcZPa .cluster span{color:#333;}#mermaid-svg-BpulQ9PK1XATcZPa div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-BpulQ9PK1XATcZPa .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-BpulQ9PK1XATcZPa rect.text{fill:none;stroke-width:0;}#mermaid-svg-BpulQ9PK1XATcZPa .icon-shape,#mermaid-svg-BpulQ9PK1XATcZPa .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-BpulQ9PK1XATcZPa .icon-shape p,#mermaid-svg-BpulQ9PK1XATcZPa .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-BpulQ9PK1XATcZPa .icon-shape .label rect,#mermaid-svg-BpulQ9PK1XATcZPa .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-BpulQ9PK1XATcZPa .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-BpulQ9PK1XATcZPa .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-BpulQ9PK1XATcZPa :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} MCP与AI工具接入
架构:Host、Client、Server
能力:Tools、Resources、Prompts
流程:协商、发现、调用、返回
传输:stdio与Streamable HTTP
边界:权限、数据可信度、执行控制

九、总结

总结要点

**MCP提供了统一的能力接入约定。**它让AI应用与外部工具、资源之间的连接更容易复用,理解Host、Client和Server的分工是入门的第一步。

**协议接入只是工程工作的一部分。**认证、业务权限、参数校验、超时与错误反馈仍然需要认真设计。工具返回的数据也需要被准确解释。

**从一个小而完整的场景开始。**先把只读查询的发现、调用、结果展示和失败路径跑通,再逐步扩展,会比一开始暴露大量能力更容易积累可靠经验。

后续随笔继续关注AI应用中的检索与工具协作,Java进阶系列则按原有节奏推进。

👉 如果你觉得这篇文章对你有所帮助,欢迎点赞、收藏、分享!😊

相关推荐
东离与糖宝1 小时前
元数据知识库
人工智能
2501_933923251 小时前
Spring Bean作用域揭秘:单例、原型、请求与会话的区别
java·后端·spring·java-ee
我是小邵1 小时前
长对话先收口:用“工作记忆 vs 长期记忆“管理 AI 上下文
人工智能·ai·llm·长期记忆·中间迷失·上下文收口
广州宏帝箱包1 小时前
出口背包的包装有没有防潮、防摔的加固处理
大数据·人工智能
jimmyleeee1 小时前
大模型安全之二十八:Agent 权限与策略控制:从最小权限到多层监督
人工智能·安全
仙魁XAN1 小时前
【WorkBuddy·基础入门】第 8 篇 :从材料到汇报:用 WorkBuddy 制作第一份 PPT
人工智能·workbuddy·workbuddy 基础入门·ppt 自动生成
学编程就要猛1 小时前
基于Spring AI 的智能聊天机器人
java·spring ai·chat robot
修炼室1 小时前
Java开发工程师笔试经验贴【高频知识】
java
船厂电气自动化ai大模型1 小时前
AI大模型与数学|第81天 课程:正交向量、正交基、格拉姆‑施密特(Gram‑Schmidt)正交化
开发语言·数据结构·人工智能·线性代数·机器学习