MCP 通信面试,让 Codex 走 TaoToken 讲清 JSON-RPC/stdio/Streamable HTTP
2026/9/16 19:53:53 网站建设 项目流程

京东二面那道「MCP 协议用什么通信?」的题,翻车点往往不在协议本身,而在候选人一上来就答 WebSocket。面试官接着问本地场景走不走 HTTP、SSE 到底有没有被弃用,两轮下来就露馅了。要避免这种局面,可以把 Codex 当成长期面试陪练:先去 https://taotoken.net/?utm_source=taotoken_aicg_blog_end 创建 Key,把 Codex 的 Base URL 配成 https://taotoken.net/api,然后把原题按消息层 JSON-RPC 2.0、传输层 stdio/Streamable HTTP、演进史三层抛给它。TaoToken 在这里就是 Codex 的模型通道,不改变 Codex 的工作方式,只负责让这条长会话稳定跑下去。

这个翻车现场很典型:候选人觉得“双向通信”就等于 WebSocket,于是答得理直气壮;面试官问“本地工具和远程工具是同一种通信吗”,候选人开始往 localhost HTTP 上猜;再追问“SSE 是不是被弃用了”,很多人直接答“是”,却不知道被弃用的是旧的双端点架构,不是 SSE 这个技术本身。这道题真正考的是分层理解,而不是背几个协议名。下面按原文的节奏,把 Codex 陪练嵌进每一层,让它在长会话里反复追问、反复校正,直到你把这道二面题讲成条件反射。

1. 京东二面原题:MCP 协议用什么通信?先把翻车现场复盘给 Codex

1.1 面试官到底在问哪三层

面试官问“MCP 协议用什么通信”,表面是问传输方式,实际至少有三层。第一层是消息层:每条消息长什么样,用什么格式表达请求、响应、通知和错误。第二层是传输层:消息通过什么通道送到对端,本地场景怎么走,远程场景怎么走。第三层是演进史:MCP 早期用什么方案,后来为什么改,旧方案里哪些东西被保留、哪些东西被替换。

候选人只答 WebSocket,相当于把传输层的一个候选答案当成了全部答案,而且这个候选答案还是错的。本地场景根本不需要网络,stdio 直接通过进程标准输入输出通信;远程场景当前标准是 Streamable HTTP,单个 HTTP 端点根据请求性质返回普通 JSON 或 SSE 流。WebSocket 从来不是 MCP 的标准传输方式。你要让 Codex 陪你练的第一件事,就是逼它按这三层拆开回答,而不是给一个笼统的协议名。

1.2 把原题拆成给 Codex 的提示词

配置好 Codex 通道后,不要只输入“MCP 协议用什么通信”。这种问法很容易得到一段百科式回答,看起来对,但面试时撑不住追问。更有效的提示词要带结构要求和验证点。你可以这样发:

京东二面原题:MCP 协议通常采用什么通信方式? 请按三层回答: 1. 消息层:为什么是 JSON-RPC 2.0,请求/响应/通知分别长什么样; 2. 传输层:本地 stdio 和远程 Streamable HTTP 各自的工作方式与选型理由; 3. 演进史:旧版双端点方案为什么被替换,SSE 本身是否被弃用。 另外请主动指出两个容易答错的细节: - stdio 模式下日志能不能写 stdout; - 为什么 MCP 没有选用 WebSocket。 最后模拟面试官追问一次:“既然要双向通信,为什么不用 WebSocket?”

这段提示词本身就是一份面试复习提纲。Codex 走 TaoToken 的模型通道返回答案后,你不需要全盘背诵,而是拿它当对照表:哪一层讲薄了,就让 Codex 展开;哪个细节它没主动提,就单独追问。长会话的好处是上下文不会断,你可以连续追问十几轮,直到它把 SSE 没被弃用、stdio 日志不能写 stdout 这两个点主动点出来。

2. 分层架构:让 Codex 别急着答 WebSocket,先画 JSON-RPC / stdio / Streamable HTTP 三层

2.1 上层能力、消息层、传输层是解耦的

MCP 的架构可以粗分成三层。最上面是业务能力层,包含 tools、resources、prompts,也就是“能调用哪些工具、能读哪些资源、有哪些提示词模板”。中间是消息层,统一用 JSON-RPC 2.0 表达所有请求、响应、通知和错误。最下面是传输层,负责把消息送到对端,本地可以用 stdio,远程可以用 Streamable HTTP。

这个分层和 HTTP、TLS、TCP 的思路类似:换传输方式不影响上层业务代码。同一个 MCP Server,本地开发时用 stdio 跑在桌面客户端里,部署到云端后换成 Streamable HTTP 给多个客户端共享,工具实现本身几乎不用改。面试官想听到的“分层理解”,核心就是这句话:消息格式和传输方式解耦,所以 MCP 才能同时支持看起来风格完全不同的 stdio 和 Streamable HTTP。

2.2 用 Codex 做分层检查,而不是让它背答案

你可以让 Codex 扮演一个严格的面试官,专门检查你的回答里有没有分层。比如你先把一段答案贴给它,然后要求它只做三件事:标出消息层的内容、标出传输层的内容、标出演进史的内容;如果某层缺失,直接指出缺了什么;最后给一个追问,逼你补全缺失层。

这种练法比让 Codex 直接生成标准答案更有效。因为它会暴露出你的真实短板。有人能说清 stdio 是进程标准输入输出,但说不清 JSON-RPC 2.0 为什么天然支持双向通信;有人能背出 Streamable HTTP 单端点,但不知道旧版双端点方案的 session 绑定有多麻烦。Codex 在长会话里可以反复出题,你每补一层,它就往下一层追问,直到这道题从“背过的答案”变成“能推出来的结构”。

3. 消息层:JSON-RPC 2.0 的请求、响应、通知,Codex 要能举出 tools/call 之外的反向消息

3.1 请求、响应、错误和通知各长什么样

JSON-RPC 2.0 的消息类型不复杂,但面试时最好能脱口而出。请求消息带jsonrpcidmethodparams,比如调用tools/call

{ "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "get_weather", "arguments": { "city": "Beijing" } } }

成功响应带同一个idresult;错误响应带同一个iderror,里面包含错误码和错误信息;通知消息没有id,因为单向推送不需要对方响应。很多人只记得请求和响应,忘了错误响应和通知也是 JSON-RPC 2.0 的一部分。Codex 如果只讲了tools/call,你可以追问它:notifications/progress是什么消息类型,为什么没有id,错误码-32602通常代表什么。

3.2 双向通信不是 WebSocket 的专利

面试里最容易踩的坑,是把“双向通信”直接等同于 WebSocket。JSON-RPC 2.0 在消息层就支持双向:Client 可以调 Server,Server 也可以给 Client 发通知,甚至可以反向请求 Client 执行某些能力。比如工具列表更新时,Server 可以发notifications/tools/list_changed;需要 Client 侧的模型能力帮忙生成内容时,可以发sampling/createMessage

既然消息层已经能表达双向通信,传输层只需要把消息送过去就行,不需要为了“双向”强行选 WebSocket。这句话要练到能自然说出来。你可以让 Codex 连续追问:“那 HTTP 不是单向的吗?”“POST 请求不是只能 Client 发 Server 吗?”“Server 怎么在 HTTP 里主动推消息?”它会把 Streamable HTTP 的 SSE 流式响应、通知消息、session 等细节一步步带出来,比你单独背定义更扎实。

4. 本地传输层:stdio 为什么比 localhost HTTP 快,日志写 stdout 为什么会炸

4.1 stdio 的工作流程和最小配置

stdio 是 MCP 最常用的本地传输方式。Client 启动 Server 子进程,把 JSON-RPC 请求写到 Server 的 stdin,每条消息一行,用换行分隔;Server 处理完,把响应写到自己的 stdout;Client 从 Server 的 stdout 读响应。整个过程不经过网卡,不经过 TCP/IP 协议栈,数据在操作系统内核的管道缓冲区里走一趟就到了。

桌面客户端配置本地 MCP Server 时,常见写法是给一个命令和参数。比如文件系统工具:

{ "mcpServers": { "filesystem": { "command": "npx", "args": [ "-y", "@modelcontextprotocol/server-filesystem", "/Users/yourname/Documents" ] } } }

Client 启动时执行这个命令,拉起一个 MCP Server 子进程,双方通过 stdio 通信。这段配置不需要端口,不需要证书,也不需要防火墙规则。你可以把类似配置贴给 Codex,让它解释commandargs分别对应什么,以及为什么没有url字段。Codex 如果能说清“本地场景不需要网络”,说明它真的理解了 stdio 的定位。

4.2 stdio 的三个优点和三个局限

优点很直接:延迟极低,因为走进程间管道,比 localhost HTTP 少掉 TCP 握手和 HTTP 头解析;配置极简,不用分配端口、不用处理证书;安全性高,因为没有监听端口,外部网络物理上访问不到。生命周期也简单,Client 退出,Server 子进程通常跟着结束,不需要单独守护。

局限也要能说出来:只能本机,跨机器跑不了;每个 Client 启动独立 Server 进程,多个 Client 想共享同一个 Server 实例做不到;某些受限环境可能没有权限 fork 子进程。面试官如果追问“那为什么不用 localhost HTTP”,你可以从这三个局限反推:localhost HTTP 虽然也能本机通信,但多了一层网络栈,还引入了端口和生命周期管理,对本地工具调用来说并不划算。

4.3 stdout 只能走 JSON-RPC,日志必须写 stderr

这是 stdio 模式最经典的工程坑。stdout 是 JSON-RPC 通信通道,Server 随便往 stdout 打印一句调试信息,Client 解析时就会收到非 JSON 内容,轻则报解析错误,重则整个 Server 连接挂掉。正确做法是所有日志写 stderr,stdout 只留给 JSON-RPC 消息。

如果你用 Python 写 MCP Server,日志要显式指定输出流:

import logging import sys logging.basicConfig( level=logging.INFO, stream=sys.stderr, format="%(asctime)s %(levelname)s %(message)s" )

然后让 Codex 检查这段代码:stream=sys.stderr是否写对,有没有别的地方print()到 stdout。这个检查点一定要加进面试陪练,因为很多候选人在讲 stdio 优点时滔滔不绝,一问日志往哪写就卡住了。面试官听到“stderr”和“不能污染 JSON-RPC 通道”,基本就能判断你上手部署过。

5. 远程传输层:Streamable HTTP 单端点、SSE 流式响应,以及面试官追问的 WebSocket

5.1 一个 /mcp 端点如何同时处理普通 JSON 与 SSE 流

远程场景当前标准是 Streamable HTTP。核心设计是单个 HTTP 端点,通常叫/mcp。Client 用 HTTP POST 发 JSON-RPC 请求;Server 根据请求性质决定响应方式:如果是一问一答,直接返回普通 JSON;如果是长任务、进度通知或 Server 主动推送,就返回Content-Type: text/event-stream,用 SSE 流持续推消息。

请求大概长这样:

POST /mcp HTTP/1.1 Host: your-mcp-server.example.com Content-Type: application/json Authorization: Bearer YOUR_MCP_TOKEN {"jsonrpc":"2.0","id":1,"method":"tools/list"}

普通响应:

HTTP/1.1 200 OK Content-Type: application/json {"jsonrpc":"2.0","id":1,"result":{"tools":[]}}

需要流式推送时,响应会变成 SSE:

HTTP/1.1 200 OK Content-Type: text/event-stream data: {"jsonrpc":"2.0","method":"notifications/progress","params":{"progress":30}} data: {"jsonrpc":"2.0","method":"notifications/progress","params":{"progress":60}} data: {"jsonrpc":"2.0","id":1,"result":{}}

同一个端点,Server 自己决定用普通 JSON 还是 SSE 流,这就是“Streamable”的来源。你可以让 Codex 解释:为什么单端点比双端点好管,为什么普通请求可以无状态处理,为什么长任务才需要流式响应。

5.2 为什么不选 WebSocket:三个工程权衡

面试官追问“双向通信用 WebSocket 不是更自然吗”,你可以从工程权衡回答。第一,HTTP 基础设施兼容性。Streamable HTTP 完全走标准 HTTP,CDN、防火墙、反向代理、鉴权中间件都能直接复用;WebSocket 需要 upgrade 握手,很多企业代理对它并不友好。第二,鉴权复杂度。Streamable HTTP 每次请求都能带标准 Authorization Header;WebSocket 第一次连接可以传,重连时往往要重新处理鉴权。第三,Serverless 兼容性。Streamable HTTP 大多数请求是普通 HTTP,Lambda、Cloud Run 这类环境能跑;WebSocket 依赖长连接,很多 Serverless 平台不支持。

MCP 主要传的是文本消息,JSON-RPC 本身已经支持双向通信,所以传输层优先选“跟现有 HTTP 生态兼容”的方案。让 Codex 模拟面试官连续追问这三点,你每答一条,它就问“还有别的理由吗”。练到你能主动把 CDN、代理、鉴权、Serverless 串起来,这道追问基本就稳了。

6. 演进史:SSE 双端点被弃用不等于 SSE 被弃用,Codex 这里最容易答错

6.1 旧的 /sse + /messages 双端点方案

MCP 早期远程传输用的是双端点方案:一个/sse端点负责 Server 到 Client 的单向 SSE 流,另一个/messages端点负责 Client 到 Server 的 HTTP POST。这样设计是因为 SSE 本身只能 Server 到 Client 单向推,要做双向通信就得额外开一条反向通道。

双端点方案在实际部署里问题很多。两条连接要绑定到同一个 session,session 丢了就全乱;SSE 断了要重连,重连后还要重新绑定另一个端点的 session;负载均衡要求两个端点的请求打到同一个实例,粘性会话配置很麻烦;Serverless 环境对长连接 SSE 不友好;两条连接各自维护鉴权头,token 刷新逻辑要写两份。这些问题不是理论上的,而是部署时真会遇到的。

6.2 Streamable HTTP 合并端点,SSE 本身没被弃用

Streamable HTTP 把两个端点合并成一个,通常就是/mcp。Client 总是用 HTTP POST 发请求,Server 在响应里决定要不要切换成 SSE 流式推送。单端点让 session 管理简单很多,绝大多数请求是普通 HTTP,Serverless 也能跑,底层流式推送仍然用 SSE。

这里必须让 Codex 主动说出那句话:被弃用的是“HTTP + SSE 双端点”架构,不是 SSE 这个技术本身。很多人答“SSE 被淘汰了”,面试官会立刻追问“那 Streamable HTTP 的流式怎么实现”,答不上来就很尴尬。你可以让 Codex 反复出这个陷阱题,直到它先区分“架构被弃用”和“技术被弃用”,再讲旧方案的问题和向后兼容期。新项目直接上 Streamable HTTP,旧项目保留/sse/messages的兼容路径,但规范里已经标为 deprecated。

7. Codex 走 TaoToken:config.toml 里改 base_url,把二面陪练长期挂起来

7.1 创建 Key 与确认模型 ID

前面所有陪练都依赖一个稳定的模型通道。打开 TaoToken 注册并创建 API Key,Key 用占位符YOUR_API_KEY表示。模型 ID 不要自己编,以 https://taotoken.net/?utm_source=taotoken_aicg_blog_end 模型广场当时列表为准。Codex 配置文件里填的 Base URL 是https://taotoken.net/api,末尾不要加/v1,也不要在这个地址后面挂任何 UTM 参数。

如果你习惯先用命令行验证通道,可以安装 CLI:

npm install -g @taotoken/taotoken

然后起一个 Codex 会话:

taotoken cc -k YOUR_API_KEY -u https://taotoken.net/api -m YOUR_MODEL_ID

这里的-u是接口 Base URL,不是官网落地页,所以不要带 UTM。Key 从 https://taotoken.net/?utm_source=taotoken_aicg_blog_end 创建,模型 ID 同样以模型广场为准。

7.2 ~/.codex/config.toml 的可复制配置

Codex 的配置文件通常在~/.codex/config.toml。把模型提供商指向 TaoToken 兼容通道,配置大致如下:

model = "YOUR_MODEL_ID" model_provider = "taotoken" [model_providers.taotoken] name = "TaoToken" base_url = "https://taotoken.net/api" env_key = "TAOTOKEN_API_KEY"

然后在 shell 里导出环境变量:

export TAOTOKEN_API_KEY=YOUR_API_KEY

保存后重新打开 Codex 会话,确认它读取的是新的model_provider。这里不要把 Anthropic 那套环境变量套到 Codex 上,Codex 走的是自己的config.toml和 provider 配置。配好之后,再把京东二面原题和三层提示词丢进去,就可以开始长会话面试陪练了。

8. 验证与排障:Codex 回答缺层、模型 ID 不匹配、base_url 多了 /v1

8.1 验证 Codex 是否主动点出两个细节

第一轮回答拿到后,不要只看它有没有提到 stdio 和 Streamable HTTP。重点检查两个验证点:它有没有主动说“SSE 本身没有被弃用,被弃用的是双端点架构”;它有没有主动说“stdio 模式下日志不能写 stdout,必须写 stderr”。如果这两个点缺了,直接追问:“你刚才漏了 SSE 的弃用范围,请重新解释哪部分被弃用、哪部分仍在 Streamable HTTP 里使用。”再追问:“stdio 模式日志应该走哪个流,为什么?”

第二轮让 Codex 模拟面试官,专门追问 WebSocket。检查它的回答有没有从 HTTP 基础设施兼容、鉴权、Serverless、状态管理这几个角度展开。如果它只说“WebSocket 更复杂”这种空话,就要求它给具体对比。长会话里可以不断加码,直到它能把工程权衡讲成一张对照表。

8.2 常见报错对照

  • 401 Unauthorized:Key 没填对,或者环境变量没有 export 成功。检查TAOTOKEN_API_KEY是否等于你从控制台复制的值。
  • 模型 ID 不匹配:Codex 报模型不存在,通常是把占位符YOUR_MODEL_ID原样填进去了,或者抄了不存在的 ID。回到 https://taotoken.net/?utm_source=taotoken_aicg_blog_end 模型广场看当时可用列表。
  • base_url多了/v1:Codex 请求路径可能变成/api/v1/...,导致 404。配置里统一写https://taotoken.net/api,末尾不要加/v1
  • 配置不生效:确认改的是~/.codex/config.toml,保存后重开会话;如果用了 shell 环境变量,确认当前终端能echo $TAOTOKEN_API_KEY
  • MCP stdio 解析失败:这是 MCP Server 侧的坑,不是 Codex 配置问题。检查 Server 有没有把调试日志打到 stdout,正确做法是日志走 stderr,stdout 只输出 JSON-RPC 消息。

排障时不要同时改多个地方。先确认 Key 和 Base URL,再确认模型 ID,最后才查 MCP Server 自身的日志通道。让 Codex 帮你逐条核对配置,但实际改动和运行要在本地终端完成,不要让它去连你的生产环境或执行任何业务操作。

9. 跑通之后:拿同一把 Key 去模型对话,再看 Coding Plan 和用量

Codex 能按三层讲清 MCP 通信之后,可以回到 TaoToken 模型对话 用同一把 Key 发一条测试消息,确认模型 ID 和 Base URL 没填错。如果打算把这道二面题的陪练长期挂着,或者每天都要用 Codex 过面试题,可以打开 Coding Plan 看套餐是否够用;新的 Key 在 控制台 API Keys 创建。跑完一轮长会话后,回 https://taotoken.net/?utm_source=taotoken_aicg_blog_end 看一眼这次调用有没有记上账,顺便确认模型广场里当前可用的模型列表。

最后留一个自检清单:消息层能不能说清 JSON-RPC 2.0 的四类消息;传输层能不能分开讲 stdio 和 Streamable HTTP;演进史能不能主动纠正“SSE 被弃用”的误答;工程细节能不能带出 stdout 日志陷阱和 session 路由。把这四条对着 Codex 的回答过一遍,缺哪条就让它补哪条,京东二面这道题基本就钉死了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询