codex mcp-server退场:迁移App Server别只改命令

如果你的工具链里还有这一行:

codex mcp-server

现在最重要的事情不是把命令换掉,而是先确认它背后承载了什么协议责任。

OpenAI 在 8 月 24 日正式把 codex mcp-server 标记为 deprecated,并明确给出两个方向:

需要把 Codex 作为应用后端:
迁移到 Codex App Server

需要在 Claude Code 中调用 Codex:
使用 Codex plugin for Claude Code

这不是一个单纯的 CLI 重命名。

mcp-server 和 App Server 的设计目标不同。前者更像把 Codex 暴露成一个可被 MCP 客户端调用的能力;后者则把 Codex 的完整 Agent Harness 暴露出来,客户端需要理解长期会话、Turn、Item、审批、流式事件和状态恢复。

所以真正的迁移任务是:

Command Migration
→ Protocol Migration
→ State Migration
→ Failure Semantics Migration

如果只改启动命令,很容易得到一个“能连上,但跑不稳”的系统。

第一步先盘点你到底怎么用了mcp-server

我会先全仓库搜索:

rg "codex mcp-server" .
rg "mcpServers" .
rg "codex.*mcp" .

然后把调用方分成三类。

第一类:Claude Code 里把 Codex 当外部能力。这类不一定需要自己迁 App Server,OpenAI 现在明确建议使用 Codex plugin for Claude Code。

第二类:自己写了桌面端或 IDE,而且依赖会话、长任务、流式结果、审批、Artifact。这类应该迁 App Server。

第三类:只把 Codex 当同步函数,输入一次任务、等待最终结果。这里要重新判断是否真的需要 App Server;简单脚本可能继续保持简单接口更合适。

App Server迁移的核心不是HTTP,而是状态模型

我会把客户端状态最少拆成:

Thread
Turn
Item

Thread 代表持续工作上下文;Turn 是一次用户驱动的执行周期;Item 是 Turn 里的可观察工作单元。

例如:

Thread:
修复登录偶发401

Turn 1:
定位原因

Items:
- read AuthService.java
- read JwtFilter.java
- run tests
- summarize findings

Turn 2:
根据批准修改代码

Items:
- edit JwtFilter.java
- run auth tests
- create patch

如果客户端只有 request_id,这次迁移就是一个机会,把 Agent 的运行对象建完整。

先做initialize握手

任何长期运行的双向协议都不应该“连上就发业务消息”。

最少先交换:

Protocol Version
Client Capabilities
Server Capabilities
Feature Flags

例如:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    "client": {
      "name": "internal-ide",
      "version": "2.4.0"
    },
    "capabilities": {
      "approval": true,
      "artifact": true,
      "streaming": true
    }
  }
}

Server 返回:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "2026-08",
    "capabilities": {
      "threadResume": true,
      "toolApproval": true
    }
  }
}

以后 App Server 升级时,客户端可以明确知道当前能力是否兼容,而不是等某个事件字段突然变化以后才发现解析失败。

不要把通知事件当成普通Response

Agent Harness 天然会产生很多异步事件:

Item Started
Item Delta
Item Completed
Approval Requested
Turn Completed
Turn Failed

它们不是普通的 request → response 关系。

客户端最好有统一 Event Envelope:

public record AgentEvent(
        long sequence,
        String threadId,
        String turnId,
        String itemId,
        String type,
        JsonNode payload,
        Instant occurredAt) {
}

这里我特别建议加 sequence

为什么必须有sequence

长连接会遇到断线、重连、网络乱序和客户端卡顿。只靠时间戳不够,两个事件可能拥有相同时间。

更稳的是 Thread 内单调递增 Sequence:

901 ItemStarted
902 ItemDelta
903 ApprovalRequested
904 ApprovalGranted
905 ItemCompleted

重连时客户端告诉服务端:

last_sequence = 903

Server 只补:

904+

这比重新拉整个会话可靠得多。

做一个Catch-up接口

即使底层协议支持长连接,我仍然建议有事件补拉语义。

例如:

GET /threads/{threadId}/events?after=903

或者协议内:

{
  "method": "thread/events",
  "params": {
    "threadId": "th_182",
    "afterSequence": 903
  }
}

断线恢复是生产 Harness 必须解决的问题。

审批必须成为一等事件

不要让 Server 输出一段“我准备运行 rm 命令,可以吗?”,然后客户端再从文本里解析。

真正协议应该是结构化事件:

{
  "method": "approval/requested",
  "params": {
    "approvalId": "ap_91",
    "threadId": "th_182",
    "turnId": "turn_4",
    "itemId": "item_17",
    "action": {
      "type": "shell",
      "command": "git reset --hard HEAD~1"
    },
    "risk": "HIGH"
  }
}

客户端再显式回:

{
  "id": 71,
  "method": "approval/resolve",
  "params": {
    "approvalId": "ap_91",
    "decision": "DENY"
  }
}

这样审批才能被审计、超时、撤销,并且绑定具体 Action。

审批要有TTL

如果 Agent 10:00 发起审批,用户第二天下午才点 Approve,仓库状态可能已经完全变化。

所以:

public record ApprovalRequest(
        String approvalId,
        String actionHash,
        Instant createdAt,
        Instant expiresAt) {
}

过期后必须重新计算 Action、重新审批,不能复用旧批准。

App Server客户端必须处理Backpressure

Agent 可能快速输出 Token Delta、Tool Event、Progress Event、Artifact Event。

如果 UI 处理速度跟不上,不能让内存里的事件队列无限增长。

例如:

BlockingQueue queue =
        new ArrayBlockingQueue(2000);

达到上限时,不同事件要不同处理:

Token Delta:
可合并

Progress Heartbeat:
可丢弃旧值

Approval:
不可丢

Item Completed:
不可丢

Turn Failed:
不可丢

事件需要优先级

public enum EventPriority {
    CRITICAL,
    STATE,
    PROGRESS,
    STREAM
}

内存压力时,STREAM 可以合并,CRITICAL 必须持久化。

迁移时最容易漏掉Thread Resume

旧 MCP 调用很多时候是一次请求一次结束。

App Server 更适合长期 Thread,所以应用数据库不要只存最后一段聊天文本。

至少:

create table agent_thread (
    thread_id varchar(128) primary key,
    user_id varchar(128) not null,
    workspace_id varchar(128) not null,
    status varchar(32) not null,
    last_sequence bigint not null,
    created_at timestamptz not null,
    updated_at timestamptz not null
);

客户端重启后:

重新加载Thread
→从last_sequence继续

Turn必须可以取消

长任务如果用户已经发现方向错了,不要等它跑完。

状态:

public enum TurnStatus {
    CREATED,
    RUNNING,
    WAITING_APPROVAL,
    CANCEL_REQUESTED,
    CANCELED,
    COMPLETED,
    FAILED
}

这里 CANCEL_REQUESTED 很重要,因为 Tool 可能正在执行。

取消请求发出,不代表外部副作用已经撤销。

Tool正在执行时取消怎么办

如果 Tool 是 read_file,通常可以中断。

如果 Tool 是:

send_email
deploy
payment

取消不代表副作用能回滚。

Turn Cancel 结果必须告诉客户端:

{
  "turnId": "turn_4",
  "status": "CANCELED",
  "sideEffects": [
    {
      "tool": "deploy",
      "status": "CONFIRMED"
    }
  ]
}

别把“Agent停止思考”写成“任务已撤销”。

做兼容层,不要一次切所有客户端

如果现在有 VS Code、内部 CLI、Web Console、Claude Code 四个调用方,可以先做 Legacy Adapter:

Old Client
↓
Compatibility Adapter
↓
App Server

先迁服务端,再逐个升级客户端。

兼容层必须有退役时间:

legacy:
  enabled: true
  deprecate_at: 2026-09-15
  disable_at: 2026-10-01

监控:

legacy_request_total

降到 0 再删。

迁移要记录协议版本

每条 Run 都保存:

protocol_version
client_version
server_version

例如:

{
  "protocol": "2026-08",
  "client": "internal-ide/2.4.0",
  "server": "codex-app-server/1.x"
}

事故时才能判断是不是特定版本组合才失败。

最小迁移测试集

我会至少跑:

1. 创建Thread
2. 开始Turn
3. Token Streaming
4. Tool Call
5. Approval Allow
6. Approval Deny
7. Approval Timeout
8. 网络断线
9. Sequence Catch-up
10. Turn Cancel
11. Tool执行中Cancel
12. App Server重启后Resume
13. 客户端旧版本连接
14. 不支持Capability协商

如果只有“hello world 能返回”,不算迁移完成。

迁移前后还要对比成本

协议迁移可能让客户端更容易保留长 Thread、更大 Context。

所以要比较:

tokens_per_turn
context_tokens
tool_calls
duration

不要只看功能是否通。

什么时候我不会迁App Server

如果场景只是:

CI里调用Codex做一次代码分析

输入固定、输出固定,没有多轮、审批、长会话和断线恢复,那 App Server 可能太重。

真正值得迁的是:

IDE
桌面端
协作应用
长期Agent

codex mcp-server 的 deprecated 提示只有一句话,但真正迁移时最容易低估的是:

旧接口连接的是“一个能力”
新App Server承载的是“一个运行时”

所以不要把这次升级做成 command rename。

更合理的是把它当成一次 Harness Protocol Migration:握手、状态、事件、序列、审批、取消、恢复和兼容都要一起补齐。

这些边界补齐以后,App Server 的价值才真正出现。


更多企业级 AI 应用、Agent、RAG 与模型工程化内容,我会继续整理在 智元界

https://www.zyentor.com/