想象你走进一家热闹的中餐厅。大厅里,经理微笑着迎上来,记下你要的菜、询问口味偏好、安排上菜节奏;后厨里,厨师们各守灶台,切配、颠勺、装盘;而穿梭其间的传菜员,则负责把点菜单从大厅送进后厨,再把热气腾腾的菜端回餐桌。顾客不会直接冲进厨房喊“加辣”,厨师也不会跑到大堂推销菜品——三个角色各司其职,饭局才能既高效又安全。 大模型应用中的 MCP(Model Context Protocol,模型上下文协议)分层架构,正是这样一家“数字餐厅”:Server 是后厨,提供真实能力(查数据库、调 API、操作文件);Host 是餐厅经理,管理 Agent 会话、与用户交互、决定何时调用哪个能力;Client 是传菜员,负责建立连接并把标准化的 JSON-RPC 消息在两端间传送。三层各管一摊,才能保证工具调用安全、高效、可扩展。理解了这三个角色的分工与协作,你就拿到了读懂 MCP 架构的钥匙。

岗位关联

一句话价值:架构师掌握 MCP 三层职责划分、通信流程与安全边界,才能做出安全、可扩展的 Agent 平台选型决策。

目录
  1. 可视化演示
  2. 角色总览:三个岗位,一条动线
  3. Host 职责:运筹帷幄的餐厅经理
  4. Server 职责:深藏功名的后厨
  5. Client 职责:勤勉的传菜员
  6. 通信流程:一张订单的旅程
  7. 安全边界:传菜窗口的规矩
  8. 部署拓扑:小店与中央厨房
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

本节配有交互动效(进入视口后自动加载,约 3KB)。

stdio通信 HTTP/SSE通信MCP三层架构可视化:展示Server/Host/Client的职责划分与协作流程HTTP/SSE通信MCP三层架构可视化:展示Server/Host/Client的职责划分与协作流程 HTTP/SSE通信MCP三层架构可视化:展示Server/Host/Client的职责划分与协作流程HTTP/SSE通信MCP三层架构可视化:展示Server/Host/Client的职责划分与协作流程

角色总览:三个岗位,一条动线

假设你开了一家“MCP 餐厅”。大厅里,经理负责接待你、记录需求、安排上菜顺序;后厨里,厨师掌握着真正的烹调手艺;而传菜员,则在大厅与后厨之间来回奔波。你不会直接冲进厨房喊“要加辣”,厨师也不会跑到桌前推销招牌菜。三个岗位各管一摊,餐厅才能既高效又安全地运转。理解 MCP 架构的第一步,就是把这三个岗位认清楚。

在 AI 应用里,MCP 正是这样一套“餐厅分工制度”。它把工具调用拆成三个角色:Server 像后厨,负责把数据库、文件系统、第三方 API 包装成标准能力;Host 像经理,是用户和 Agent 所在的应用程序,负责理解用户意图、安排调用;Client 像传菜员,负责把 Host 的请求翻译成标准小票(JSON-RPC 消息)送到 Server,再把结果端回来。三者缺一不可,少一个环节,整个调用链条就断了。

三层之间通过 JSON-RPC 2.0 格式通信,整条链路可以写成一条流水线:

所以当你听到“MCP 架构”时,脑海里应该是这家餐厅的画面:经理不下厨、厨师不待客、传菜员不做菜。三者职责越清晰,系统就越容易扩展——想加一道新菜,只需在后厨新增一个 Server;想开分店,只需让经理多带几个传菜员。

用户→指令Host→委托Client→JSON-RPCServer→执行工具\displaystyle \text{用户} \xrightarrow{\text{指令}} \text{Host} \xrightarrow{\text{委托}} \text{Client} \xrightarrow{\text{JSON-RPC}} \text{Server} \xrightarrow{\text{执行}} \text{工具}
这行流水线表达了一次完整请求从用户到工具的传递路径:每一环都只做自己的事,消息单向流入,结果再原路返回。
  1. 用户指令用户在 Host 界面输入自然语言请求,经理开始接单。
    用户→指令Host\text{用户} \xrightarrow{\text{指令}} \text{Host}
  2. 宿主委托Host 根据意图挑出合适的 Client,就像经理指定负责某条路线的传菜员。
    Host→委托Client\text{Host} \xrightarrow{\text{委托}} \text{Client}
  3. 连接通信Client 用 JSON-RPC 封装请求穿越传输层,小票被写成标准格式。
    Client→JSON-RPCServer\text{Client} \xrightarrow{\text{JSON-RPC}} \text{Server}
  4. 能力执行Server 调用真实工具并把结果原路返回,后厨把菜做好端出。
    Server→执行工具\text{Server} \xrightarrow{\text{执行}} \text{工具}

Host 职责:运筹帷幄的餐厅经理

餐厅经理每天的工作是什么?记住熟客口味、安排座位、决定先上哪道菜、征询顾客对菜品的意见。经理从不亲自掌勺,但所有与“人”有关的决策都归他管——这正是 Host 的定位。它是三层架构里离用户最近、也最“重”的角色。

Host 在 MCP 中就是“Agent 的家”。它承载着大模型、会话上下文和用户界面;用户输入、模型推理、工具返回结果都在这里汇聚。Claude Desktop、支持 MCP 的 IDE、自研 Agent 平台,本质上都是 Host。它们决定 Agent 何时调用哪个工具、调用的结果如何呈现给用户——决策权牢牢握在 Host 手里。

Host 的关键职责可归纳为三点:一是管理 Agent 会话——像经理记住你的口味一样维护多轮上下文;二是用户交互——把模型输出呈现给用户,把用户指令送给模型;三是权限拦截——在调用任何工具前先征求用户同意,相当于经理上菜前问一句“您确定要这道菜吗?”此外,Host 还要协调多个 Client:一个 Host 可以同时连接多个 Server,就像一位经理管着多名传菜员,各跑各的路线。

回到餐厅,如果把“经理”这个角色抽掉,顾客就只能自己跑进厨房点菜,AI 应用也会失去决策与安全审查的关卡。Host 存在的意义,就是让“人”始终留在决策回路里——任何工具调用,都应该先过经理这一关。

Host=Agent会话管理+UI交互+授权拦截\displaystyle \text{Host} = \text{Agent}_{\text{会话管理}} + \text{UI}_{\text{交互}} + \text{授权}_{\text{拦截}}
Host 是三层里唯一直接面对用户的组件,它把会话、界面、决策和授权打包在一起,是“人的意志”进入系统的入口。
  1. 会话管理Agent 的多轮对话与上下文状态由 Host 维护,类比经理记住每桌的点单记录。
    Agent会话管理\text{Agent}_{\text{会话管理}}
  2. 交互界面用户输入与模型输出的可视化由 Host 承担,类比大厅的迎宾与服务台。
    UI交互\text{UI}_{\text{交互}}
  3. 授权拦截工具调用前必须经用户确认,类比上重口菜前先问一句忌口。
    授权拦截\text{授权}_{\text{拦截}}

Server 职责:深藏功名的后厨

后厨的价值在于“会做菜”。鱼香肉丝、宫保鸡丁、红烧狮子头——每道菜就是一项能力。MCP Server 就是这些能力的提供方,它不关心坐在大厅里的顾客是谁,只负责按标准流程把一道道菜做出来。真正动手干活的永远是后厨,这是 Server 最朴素也最重要的定位。

一个 Server 可以暴露三类能力:Tools(工具)是可执行动作,比如查询订单、写文件、调用支付 API;Resources(资源)是只读数据,比如数据库表格、配置文件内容;Prompts(提示词模板)相当于后厨的“预制菜单”,比如一个格式化周报的标准模板。三类能力统一通过 JSON-RPC 暴露,Host 不需要知道后厨内部怎么烧菜,只需知道“能点什么菜”。

Server 的核心行为是“能力广播”:连接建立后,通过 tools/list 把自己能提供的工具清单上报给 Host,Host 据此规划调用策略。同时 Server 必须守好自身边界——它在自己的进程内执行,独立于 Host,权限受限;每次调用都要校验参数格式与调用方身份,就像后厨有食品卫生规范,不接触顾客隐私。

设计 Server 时,思路应该像开菜谱:一道菜一个规矩,食材清单写清楚,做法别越界。Server 暴露能力的同时必须自带边界——菜可以辣,但锅不能把火苗带进餐厅。能力越聚焦,权限面越小,系统就越安全。

Server={Tools∪Resources∪Prompts}\displaystyle \text{Server} = \{ \text{Tools} \cup \text{Resources} \cup \text{Prompts} \}
Server 的能力集合由三类元素构成:Tools 是有副作用的动作,Resources 是只读数据,Prompts 是按需取用的模板。
  1. 可执行工具Tools 是有副作用的函数,调用后改变外部状态,类比热炒出锅的菜。
    Tools\text{Tools}
  2. 只读资源Resources 是无副作用的取数操作,类比查看冰箱库存。
    Resources\text{Resources}
  3. 模板化提示Prompts 是带占位符的指令模板,类比后厨的预制菜单。
    Prompts\text{Prompts}

Client 职责:勤勉的传菜员

传菜员是餐厅里最不起眼却最关键的岗位。菜做得再好、经理安排得再周密,如果没人把订单送进厨房、把菜端出来,一切都是空谈。MCP 里的 Client 就是这条“生命线”——它不决策、不做菜,只保证消息准确送达。

Client 是 Host 内部与某个 Server 之间的一对一连接通道。Host 可能同时挂着多个 Client:一个连文件系统 Server,一个连数据库 Server,一个连 GitHub Server。每个 Client 只服务一个 Server,就像每位传菜员只负责一条固定送餐路线。这个“一对一”约束是理解 Client 的关键:它不是一个抽象层,而是一条具体的、有状态的连接。

Client 的职责有三:一是建立与维持连接,选择传输层(本地用 stdio 管道,远程用 HTTP/SSE)并管理会话生命周期;二是消息封装,把请求、响应包装成 JSON-RPC 2.0 格式,包含 jsonrpc 版本、method、params、id 等字段;三是协议协商,在初始化阶段与 Server 对齐协议版本与能力。它像传菜员一样,只保证小票格式正确、路线无误,从不擅自改菜。

传菜员不需要懂菜谱,但必须跑得快、传得准。当你的 Agent 平台出现“连不上工具”的故障时,八成问题出在 Client 这层:传输断了、协议版本没对齐、消息格式错误。排查时盯着传菜员手里的“小票”看,往往很快就能定位。

Client=Transport(stdio/HTTP/SSE)+JSON-RPC封装\displaystyle \text{Client} = \text{Transport}(\text{stdio} / \text{HTTP} / \text{SSE}) + \text{JSON-RPC}_{\text{封装}}
Client 的本质是“传输层 + 协议封装层”,它把业务意图变成协议消息,是 Host 通往 Server 的物理通道。
  1. 传输层选择Transport 决定消息走本地管道还是网络,类比传菜员选择走大厅还是后门。
    Transport(stdio/HTTP/SSE)\text{Transport}(\text{stdio} / \text{HTTP} / \text{SSE})
  2. 协议封装JSON-RPC 负责把调用序列化为标准帧,类比把口头嘱咐写成统一格式的订单小票。
    JSON-RPC封装\text{JSON-RPC}_{\text{封装}}

通信流程:一张订单的旅程

一次完整的点餐体验是什么样?你告诉经理想吃什么,经理确认菜单上有这道菜,传菜员把订单送进后厨,厨师做完让传菜员端回,经理检查后上桌。MCP 的工具调用生命周期,就是这张订单的旅程,四步走完,一次会话才算圆满。

整个过程分四个阶段。首先是初始化握手(initialize):Client 向 Server 声明协议版本与能力,Server 回应自己的版本与能力,双方“对上方言”;接着是能力发现(tools/list):Client 拉取 Server 的工具清单,相当于看菜单;然后是工具调用(tools/call):Client 携带参数发起调用,Server 执行后返回结果;最后是会话收尾:发送关闭通知,释放连接资源,相当于结账离店。

所有消息都用 JSON-RPC 2.0 封装:请求带 method 和 params,响应带 result 或 error,id 用来配对请求与响应。一个典型的调用消息形如 {"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"query_order","arguments":{"order_id":42}}}——这串标准格式,就是传菜员手里那张所有人都能读懂的订单小票。

这张“订单旅程”提醒我们:任何 MCP 调试都可以按阶段切分——握手失败先查协议版本,清单为空查 Server 注册,调用失败查参数与权限。把旅程拆开看,问题就各归各家,不会再混成一锅粥。

会话=initialize→tools/list→tools/call→shutdown\displaystyle \text{会话} = \text{initialize} \rightarrow \text{tools/list} \rightarrow \text{tools/call} \rightarrow \text{shutdown}
一次 MCP 会话的生命周期是严格单向的,像订单只能从下单走到结账,不能跳步,也不能倒流。
  1. 初始化握手Client 先发 initialize,双方交换协议版本,对上“暗号”。
    initialize→initialized\text{initialize} \rightarrow \text{initialized}
  2. 能力发现tools/list 拉取工具清单,Host 据此规划下一步调用。
    tools/list→tool 列表\text{tools/list} \rightarrow \text{tool 列表}
  3. 工具调用tools/call 携带参数往返一次,得到执行结果,订单完成。
    tools/call→result\text{tools/call} \rightarrow \text{result}
  4. 会话收尾发送 shutdown 通知并回收连接资源,桌面恢复整洁。
    shutdown\text{shutdown}

安全边界:传菜窗口的规矩

餐厅为什么要设传菜窗口?因为顾客与后厨必须隔离:顾客不能进厨房碰刀具,厨师也不该知道顾客的银行卡密码。MCP 的安全边界设计,就是这扇“传菜窗口”——每一层都管好自己的权限,谁也不越界。

MCP 安全不是某一层的单点防护,而是层层设防:第一道防线在 Host——所有工具调用必须先经用户授权,经理替你确认;第二道防线在 Server——Server 只暴露最小必要能力,并在自己的沙箱里执行,权限受限;第三道防线在传输层——本地用 stdio 隔离进程,远程用 HTTPS/SSE 加密,敏感数据尽量留在本地,不经过不必要的网络传输。

实践要点包括:能力最小化(比如数据库 Server 只暴露只读查询,不暴露删表接口)、参数校验(Server 对每个参数做类型与范围检查,拒绝畸形输入)、审计日志(Host 记录每次调用的时间、工具、参数摘要,像餐厅留下订单存根以备查账)。权限判定遵循“取交集”原则:一次调用能拿到的权限,必须同时落在用户、Host、Server 三方允许的范围内。

安全的本质是“默认不信,逐级求证”。传菜窗口既挡了顾客进厨房,也挡了厨师打探顾客隐私——两边各守其位,餐厅才能放心营业。设计 MCP 系统时,宁可多问一次用户,也不要默认放行。

P执行⊆P用户∩PHost∩PServer\displaystyle P_{\text{执行}} \subseteq P_{\text{用户}} \cap P_{\text{Host}} \cap P_{\text{Server}}
一次工具调用最终能拿到的权限,是用户授权、Host 策略、Server 沙箱三方权限集合的交集——任何一方说不,调用就做不成。
  1. 用户意向用户授权范围构成最外层的权限集合,类比顾客同意你吃辣。
    P用户P_{\text{用户}}
  2. 宿主策略Host 策略进一步过滤,禁止越权操作,类比经理不点菜单外的菜。
    PHostP_{\text{Host}}
  3. 服务端沙箱Server 自己的权限边界收最后一道口子,类比后厨不碰顾客私人物品。
    PServerP_{\text{Server}}

部署拓扑:小店与中央厨房

一家餐厅可以是一间街边小店,也可以是一套连锁中央厨房体系。MCP 的部署方式同样取决于你是“小店”还是“连锁”:本地单进程就像小店——后厨就在店里,传菜员走几步就到;远程多服务就像中央厨房——后厨集中建在别处,各门店通过网络从同一厨房调菜。

本地单进程部署:Host 与 Server 跑在同一台机器,通过 stdio(标准输入输出管道)通信,Client 拉起一个子进程并与它直接对话。优点是低延迟、高隐私——数据不出本机,适合桌面应用(Claude Desktop、IDE 插件)和本地文件、命令行工具。缺点是无法共享:每个用户都要各自拉起一份服务。

远程多服务部署:Server 独立部署在远端,通过 HTTP/SSE 通信,多个 Host(不同用户、不同团队)共享一套工具服务。优点是松耦合、可复用、便于集中运维,适合企业级的数据库查询、工单系统、内部 API 网关。缺点是网络延迟更高,且数据要过网络,安全要求更严。实践中也有混合部署:本地 Server 处理敏感文件,远程 Server 处理需要共享的数据。选型权衡看三件事:数据敏感性、延迟要求、运维成本。

选部署方案就像选餐厅经营模式:街边小店适合私密小范围,中央厨房适合规模化共享。架构师先问自己三个问题——数据能不能出本地、延迟有多敏感、谁负责运维——答案自然浮现,不必盲目追捧某一种形态。

部署形态={本地单进程:stdio远程多服务:HTTP/SSE混合模式:两者兼有\displaystyle \text{部署形态} = \begin{cases} \text{本地单进程} & : \text{stdio} \\ \text{远程多服务} & : \text{HTTP/SSE} \\ \text{混合模式} & : \text{两者兼有} \end{cases}
三种形态对应三种传输与运维策略:没有绝对的好坏,只有合不合适。数据越敏感,越倾向本地;服务越需要共享,越倾向远程。
  1. 本地形态stdio 管道,子进程隔离,数据不出本机,私密性最好。
    本地单进程:stdio\text{本地单进程} : \text{stdio}
  2. 远程形态HTTP/SSE 网络传输,服务可被多 Host 共享,扩展性最好。
    远程多服务:HTTP/SSE\text{远程多服务} : \text{HTTP/SSE}
  3. 混合形态按数据敏感度分配本地或远程通道,兼顾隐私与共享。
    混合模式:stdio+HTTP/SSE\text{混合模式} : \text{stdio} + \text{HTTP/SSE}

AI 应用场景

桌面智能助手的本地文件操作

阶段:工具调用链路设计

解决的问题:传统桌面助手无法安全读取本地项目文件,靠手写插件逐个集成既繁琐又难维护。MCP 让 IDE 作为 Host,通过 stdio 类型的 Client 连接文件系统 Server,用户授权后 Agent 才能读取目录、搜索代码、修改文件,所有操作都被审计记录。

具体案例:程序员对支持 MCP 的 IDE 说“帮我重构 payment 模块的重复代码”。Host 管理会话,先把意图交给大模型;模型决定调用 read_file 与 search_files 工具,Host 弹出授权框征求用户同意;同意后,Client 通过 stdio 把 JSON-RPC 请求送到本地文件系统 Server,结果返回模型,最终生成重构建议。全程数据不出本机,权限由用户把关。

企业统一工具网关

阶段:安全边界与集中管理

解决的问题:不同团队各自造轮子对接数据库、工单系统,权限失控、重复建设。用 MCP 把内部能力封装成统一的远程 Server,所有 Agent 应用作为 Host 接入,授权与审计集中在一处,权限边界可管可控。

具体案例:某金融机构搭建数据查询平台,将“客户信息查询”“交易流水统计”封装为只读 Server,通过 HTTP/SSE 部署在内网。业务 Agent(Host)调用这些工具前,必须经过用户授权和参数白名单校验;Server 只暴露最小必要字段,删表、导入等危险操作根本不在工具清单里。每次调用自动写入审计日志,合规检查一键导出。

多 Agent 协作编排

阶段:系统集成与协议对接

解决的问题:多个 Agent 之间互相调用时协议不一、耦合严重。把下游 Agent 的能力包装成 MCP Server,上游 Agent 作为 Host 通过 Client 调用,协作关系标准化,新增协作方只需新增一个 Server。

具体案例:一家 SaaS 公司让“数据分析 Agent”调用“报表生成 Agent”。报表 Agent 把自己封装成 Server,暴露 create_report 工具;数据分析 Agent 所在平台作为 Host,挂着对应的 Client。主 Agent 分析完数据后,通过 Client 发起工具调用生成报表,整个过程遵循统一的 JSON-RPC 流程,双方团队互不侵入对方代码。

Python 演示

python83 行
import json  class MCPServer:    """MCP Server:模拟后厨,提供真实的工具能力"""     def __init__(self, name, tools):        self.name = name        self.tools = tools     def handle(self, req):        method = req["method"]        if method == "initialize":            return {"jsonrpc": "2.0", "id": req["id"],                    "result": {"serverName": self.name,                               "protocolVersion": "2024-11-05",                               "tools": list(self.tools)}}        if method == "tools/call":            name = req["params"]["name"]            args = req["params"].get("args", {})            if name in self.tools:                return {"jsonrpc": "2.0", "id": req["id"],                        "result": {"output": self.tools[name](args)}}        return {"jsonrpc": "2.0", "id": req["id"],                "error": {"code": -32601, "message": "方法不存在"}}  class MCPClient:    """MCP Client:模拟传菜员,负责消息在 Host 与 Server 间往返"""     def __init__(self, server):        self.server = server        self.req_id = 0        self.connected = False     def send(self, method, params=None):        self.req_id += 1        req = {"jsonrpc": "2.0", "id": self.req_id,               "method": method, "params": params or {}}        print(f"  [Client -> {self.server.name}] {method}")        return self.server.handle(req)  class MCPHost:    """MCP Host:模拟餐厅经理,管理会话、授权并调度工具"""     def __init__(self):        self.clients = {}        self.logs = []     def attach(self, name, client):        self.clients[name] = client     def approve(self, tool, args):        print(f"[Host] 请求用户授权调用 {tool},参数 {args}")        return True     def call_tool(self, name, tool, args):        if not self.approve(tool, args):            return None        reply = self.clients[name].send("tools/call",                                        {"name": tool, "args": args})        result = reply["result"]["output"]        self.logs.append((name, tool, result))        return result  def main():    calc = MCPServer(        "计算器",        {"add": lambda a: a["x"] + a["y"],         "mul": lambda a: a["x"] * a["y"]})    client = MCPClient(calc)    host = MCPHost()    host.attach("计算器", client)    client.send("initialize")    print("[Host] 计算 3 × 4:", host.call_tool("计算器", "mul",                                                {"x": 3, "y": 4}))    print("[Host] 审计日志:", host.logs)  if __name__ == "__main__":    main()
目的:用三个类模拟 MCP 三层架构,演示初始化握手、用户授权、工具调用往返和审计日志的完整链路。
  1. class MCPServer后厨:持有真实工具函数,按 JSON-RPC 协议处理初始化与调用请求。
  2. class MCPClient传菜员:维护请求 id,把方法名和参数封装成标准消息发给 Server。
  3. class MCPHost经理:管理多个 Client,调用前先征求用户授权,并把调用记录写入审计日志。
  4. def handle(self, req)Server 根据 method 字段分发请求,相当于后厨按小票类别接单。
  5. client.send("initialize")建立会话时先握手,双方对齐协议版本,对上“暗号”。
  6. host.attach("计算器", client)Host 把传菜员挂到自己的管理名单里,一条路线一个 Client。
  7. def approve(self, tool, args)安全边界的核心:任何工具调用都要先过用户授权这一关。
  8. self.logs.append(...)每次调用留痕,方便事后审计,像餐厅保留订单存根。

常见误区

误区网上看到 MCP 能调工具,觉得它就是 OpenAI function calling 的改版,封装一下 HTTP 请求就行,不需要理解三层架构。

正解function calling 解决的只是“模型输出结构化调用意图”这一步;而 MCP 定义了 Server/Host/Client 三层职责、完整的会话生命周期(初始化、能力发现、调用往返、关闭)、传输层抽象和权限边界。它更像一套“餐厅分工制度”,而 function calling 只是菜单上的一道菜。两者解决的问题层次完全不同。

为何常见:初学者第一次接触 MCP 时往往从“调工具”这个表象入手,忽略了协议层面“谁连接谁、谁授权谁”的结构性设计,自然容易把两层框架混为一谈。

误区以为一个应用要么是 Host,要么是 Client,就像两台服务器各自扮演一个角色,部署时左右各放一个进程。

正解Host 是应用外壳(会话、UI、决策),Client 是 Host 内部的连接组件。一个 Host 内部可以挂多个 Client,每个 Client 对应一个 Server。类比餐厅:经理(Host)手下有多名传菜员(Client),每名传菜员只跑一条固定路线。二者不是并列关系,而是“包含”关系。

为何常见:架构图画常把三个角色画成三个并排的方块,让人误以为它们是对等组件,忽略了 Client 存在于 Host 进程内部的层级事实。

误区为了让 Agent 什么都能干,把数据库、文件、支付、搜索全部打包到一个巨型 Server 里,觉得这样调用方便、不用维护多个连接。

正解单一 Server 权限面过大,一旦被攻破,所有能力同时沦陷;故障爆炸半径也大,一个工具出问题拖垮全部。正确做法是按域拆分 Server,每个 Server 只暴露最小必要能力,遵循“最小权限原则”——就像后厨按冷菜、热菜、面点分灶,各守一摊,而不是一个大锅全炒。

为何常见:人总有“省事”的直觉,认为集中管理更简单,却忽略了安全与故障隔离在分布式架构里的长期价值。

误区觉得 MCP 是给云端服务设计的,本地文件、命令行工具直接代码调用就行,没必要走协议。

正解stdio 本地传输是 MCP 的一等公民,桌面应用(Claude Desktop、IDE)恰恰是 MCP 最常见的落地场景。本地 Server 通过子进程隔离运行,数据不出本机,延迟极低,还能享受统一的三层协作与审计能力。传菜员既能跑大厅,也能在后厨门口递菜——本地远程都是同一条送餐路线,只是距离不同。

为何常见:日常接触的 MCP 教程多拿“连接远程数据库、第三方 API”举例,让学习者误以为协议只为网络而生,忽略了传输层可插拔的设计初衷。

面试题

Q1. 在 MCP 三层架构中,哪个组件负责管理 Agent 会话并与用户直接交互?

单选题 · easy

  • A.提供工具能力的服务端
  • B.管理会话与用户交互← 正确答案
  • C.只负责传输协议消息
  • D.直接处理用户的需求

答案:B。Host 像餐厅经理,负责会话管理、用户交互和授权决策;Server 像后厨只提供能力,Client 像传菜员只负责传输。选项 B 准确命中 Host 的职责核心,其余选项分别描述了 Server、Client 和用户侧的行为。

Q2. MCP Client 最核心的职责是什么?

单选题 · easy

  • A.编写工具内部业务逻辑
  • B.建立连接并封装协议消息← 正确答案
  • C.决定模型生成什么回复
  • D.维护用户账户的账单

答案:B。Client 是“传输层 + JSON-RPC 封装层”,负责建立连接、封装消息、协商协议版本,对应选项 B。工具逻辑由 Server 编写(A),回复内容由 Host 里的模型决定(C),账户账单与 Client 无关(D)。

Q3. 一次 MCP 会话开始后,Client 首先发送哪个请求?

单选题 · mid

  • A.立即发送工具调用请求
  • B.先发送初始化握手请求← 正确答案
  • C.直接发送关闭连接通知
  • D.发送用户授权身份凭据

答案:B。会话生命周期严格有序:先 initialize 握手对齐协议版本,再 tools/list 发现能力,之后才能 tools/call 调用工具,最后 shutdown 收尾。选项 B 是第一步;A 跳过了握手,C 是最后一步,D 不属于标准流程。

Q4. MCP Server 通过什么方式让 Host 知道它提供哪些能力?

单选题 · mid

  • A.通过能力广播上报清单← 正确答案
  • B.直接修改宿主的源代码
  • C.通过手工配置文件指定
  • D.由平台后台猜测能力

答案:A。Server 通过 tools/list 能力发现机制把工具清单广播给 Host,相当于后厨递出菜单。B 破坏边界,C 太脆弱且非协议标准,D 靠猜不可靠。能力广播是协议定义的标准行为。

Q5. 在 MCP 安全边界设计中,谁负责最终的用户授权放行?

单选题 · mid

  • A.Server 自行决定是否放行
  • B.Host 征求用户授权后放行← 正确答案
  • C.Client 绕过权限直接调用
  • D.操作系统默认自动放行

答案:B。Host 是决策与授权关卡,调用工具前必须征求用户同意,类比经理上菜前问顾客。Server 只执行不决策(A),Client 只传输不判断(C),操作系统不参与授权逻辑(D)。

Q6. 关于“最小权限原则”,以下哪种做法正确?

单选题 · mid

  • A.每个 Server 授予全部权限
  • B.只授予完成任务的最小权限← 正确答案
  • C.权限不做限制来加快开发
  • D.授权完全交给工具判断

答案:B。执行权限等于用户、Host、Server 三方权限的交集,且应尽量收窄。B 正是“最小权限”的定义;A 扩大攻击面,C 牺牲安全,D 把安全责任推给工具层,都违背了层层设防的设计初衷。

Q7. 本地单进程与远程多服务部署的核心区别是什么?

单选题 · hard

  • A.本地用 stdio 远程走 HTTP← 正确答案
  • B.远程部署响应必然更快
  • C.本地部署无法调用工具
  • D.两者传输协议完全不同

答案:A。本地单进程通过 stdio 管道在子进程间通信,远程多服务通过 HTTP/SSE 跨网络通信,对应 A。远程因网络开销通常更慢(B 错),本地完全可以调用工具(C 错),两者 JSON-RPC 消息协议一致、仅传输层不同(D 错)。

Q8. 以下哪些职责属于 MCP Host?(多选)

多选题 · mid

  • A.管理多个 Client 的实例← 正确答案
  • B.请求用户授权并展示结果← 正确答案
  • C.编写服务端的工具代码
  • D.维护整场会话的上下文← 正确答案

答案:ABD。Host 像餐厅经理:协调多个 Client(A)、征求用户授权并展示结果(B)、维护会话上下文(D)都是它的活儿。C 是 Server 的职责——经理不掌勺,工具逻辑属于后厨。

Q9. 一次完整 MCP 工具调用往返包含哪些阶段?(多选)

多选题 · hard

  • A.初始化握手请求与响应← 正确答案
  • B.能力发现获取工具清单← 正确答案
  • C.工具调用携带参数往返← 正确答案
  • D.直接修改本地数据文件

答案:ABC。会话之旅按顺序包含 initialize 握手(A)、tools/list 能力发现(B)、tools/call 调用往返(C),最后才是 shutdown 收尾。D 是工具执行的具体效果,属于调用阶段的内部动作,不是独立的协议阶段。

Q10. 关于 MCP 安全边界设计,以下哪些做法正确?(多选)

多选题 · hard

  • A.Server 校验调用方身份← 正确答案
  • B.Host 记录会话审计日志← 正确答案
  • C.敏感数据尽量留在本地← 正确答案
  • D.用户绕过 Host 直连 Server

答案:ABC。安全是层层设防的传菜窗口:Server 校验调用方(A)、Host 留审计日志(B)、敏感数据本地隔离(C)都是正确实践。D 破坏三层隔离——顾客直接闯进厨房,正是架构要避免的。