Codex 再强,也只是在"读文件、跑命令"这个圈子里打转。但如果它还能查数据库、拉取文档、调用你公司内部的 API 呢?这就是 MCP 的用武之地。本课我们打通这条能力扩展的桥梁。
一、什么是 MCP
MCP = Model Context Protocol(模型上下文协议)。你可以把它理解为**“AI 与外部工具之间的通用接口标准”**。
在没有统一标准之前,让 AI 连接一个新工具,往往要针对每个工具单独开发。MCP 提供了一套通用的"插座":任何遵循 MCP 的工具,都可以被 Codex 这类客户端以统一的方式调用。
下图展示了 MCP 的典型架构:Codex 作为客户端,通过统一的 MCP 协议连接不同的 MCP 服务器,每个服务器负责暴露一类外部能力(如 GitHub、数据库、公司内部 API)。
#mermaid-svg-UxOWRcnCdG3Rr7D8{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-UxOWRcnCdG3Rr7D8 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-UxOWRcnCdG3Rr7D8 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-UxOWRcnCdG3Rr7D8 .error-icon{fill:#552222;}#mermaid-svg-UxOWRcnCdG3Rr7D8 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-UxOWRcnCdG3Rr7D8 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-UxOWRcnCdG3Rr7D8 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-UxOWRcnCdG3Rr7D8 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-UxOWRcnCdG3Rr7D8 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-UxOWRcnCdG3Rr7D8 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-UxOWRcnCdG3Rr7D8 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-UxOWRcnCdG3Rr7D8 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-UxOWRcnCdG3Rr7D8 .marker.cross{stroke:#333333;}#mermaid-svg-UxOWRcnCdG3Rr7D8 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-UxOWRcnCdG3Rr7D8 p{margin:0;}#mermaid-svg-UxOWRcnCdG3Rr7D8 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-UxOWRcnCdG3Rr7D8 .cluster-label text{fill:#333;}#mermaid-svg-UxOWRcnCdG3Rr7D8 .cluster-label span{color:#333;}#mermaid-svg-UxOWRcnCdG3Rr7D8 .cluster-label span p{background-color:transparent;}#mermaid-svg-UxOWRcnCdG3Rr7D8 .label text,#mermaid-svg-UxOWRcnCdG3Rr7D8 span{fill:#333;color:#333;}#mermaid-svg-UxOWRcnCdG3Rr7D8 .node rect,#mermaid-svg-UxOWRcnCdG3Rr7D8 .node circle,#mermaid-svg-UxOWRcnCdG3Rr7D8 .node ellipse,#mermaid-svg-UxOWRcnCdG3Rr7D8 .node polygon,#mermaid-svg-UxOWRcnCdG3Rr7D8 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-UxOWRcnCdG3Rr7D8 .rough-node .label text,#mermaid-svg-UxOWRcnCdG3Rr7D8 .node .label text,#mermaid-svg-UxOWRcnCdG3Rr7D8 .image-shape .label,#mermaid-svg-UxOWRcnCdG3Rr7D8 .icon-shape .label{text-anchor:middle;}#mermaid-svg-UxOWRcnCdG3Rr7D8 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-UxOWRcnCdG3Rr7D8 .rough-node .label,#mermaid-svg-UxOWRcnCdG3Rr7D8 .node .label,#mermaid-svg-UxOWRcnCdG3Rr7D8 .image-shape .label,#mermaid-svg-UxOWRcnCdG3Rr7D8 .icon-shape .label{text-align:center;}#mermaid-svg-UxOWRcnCdG3Rr7D8 .node.clickable{cursor:pointer;}#mermaid-svg-UxOWRcnCdG3Rr7D8 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-UxOWRcnCdG3Rr7D8 .arrowheadPath{fill:#333333;}#mermaid-svg-UxOWRcnCdG3Rr7D8 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-UxOWRcnCdG3Rr7D8 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-UxOWRcnCdG3Rr7D8 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-UxOWRcnCdG3Rr7D8 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-UxOWRcnCdG3Rr7D8 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-UxOWRcnCdG3Rr7D8 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-UxOWRcnCdG3Rr7D8 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-UxOWRcnCdG3Rr7D8 .cluster text{fill:#333;}#mermaid-svg-UxOWRcnCdG3Rr7D8 .cluster span{color:#333;}#mermaid-svg-UxOWRcnCdG3Rr7D8 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-UxOWRcnCdG3Rr7D8 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-UxOWRcnCdG3Rr7D8 rect.text{fill:none;stroke-width:0;}#mermaid-svg-UxOWRcnCdG3Rr7D8 .icon-shape,#mermaid-svg-UxOWRcnCdG3Rr7D8 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-UxOWRcnCdG3Rr7D8 .icon-shape p,#mermaid-svg-UxOWRcnCdG3Rr7D8 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-UxOWRcnCdG3Rr7D8 .icon-shape .label rect,#mermaid-svg-UxOWRcnCdG3Rr7D8 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-UxOWRcnCdG3Rr7D8 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-UxOWRcnCdG3Rr7D8 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-UxOWRcnCdG3Rr7D8 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
MCP 协议
MCP 协议
MCP 协议
Codex 客户端
GitHub MCP 服务器
数据库 MCP 服务器
内部 API MCP 服务器
这张图揭示了 MCP 通信机制的核心:Codex 客户端是唯一的"大脑",负责理解你的自然语言指令并决定调用哪个工具;MCP 协议则是连接客户端与服务器之间的"标准插座",所有请求与响应都通过它进行结构化传输;而 GitHub、数据库、内部 API 等 MCP 服务器则各自封装了一类外部能力,等待被调用。
数据流向通常是这样的:你在会话中提出需求后,Codex 客户端会判断该需求对应哪个 MCP 服务器暴露的工具,然后通过 MCP 协议把"工具名 + 参数"打包成标准请求发给对应服务器;服务器执行完实际操作后,再把结果沿同一条通道返回给 Codex,最终由 Codex 整理成自然语言回显给你。整个过程对用户透明——你只描述"想做什么",而不必关心底层如何连接与调用。
二、MCP 能带来什么
- 连接更多数据源:数据库、文档系统、内部知识库;
- 调用更多工具:搜索、浏览器、办公软件、API;
- 扩展能力边界:让 Codex 从"改代码"升级为"编排整个工作流"。
简单说,MCP 把 Codex 从"编辑器里的助手"变成"可以接入你整个技术栈的代理"。
三、如何配置 MCP 服务器
方式一:通过命令行配置
在 Codex 的交互会话中,使用相关命令添加 MCP 服务器,指定其启动方式与参数。
方式二:通过配置文件
在 ~/.codex/config 中声明 MCP 服务器。配置文件的方式更适合"一次配置、长期复用",也便于团队共享同一套配置。
配置的核心要素通常包括:服务器名称、启动命令、必要的环境变量或参数。
两种配置方式各有适用场景,对比如下:
| 适用场景 | 临时调试、快速验证某个 MCP 服务器是否可用;偶尔使用一次 | 长期使用、需要反复接入;团队需要共享同一套配置 |
| 优点 | 操作直接、即时生效,无需改动文件;适合快速试验 | 一次配置、长期复用;可纳入版本管理,便于备份和团队共享 |
| 缺点 | 重启后可能丢失,不便于记录和分享;多次配置容易变得繁琐 | 需要编辑文件并重启 Codex 后才会生效;配置格式错误可能导致加载失败 |
选择建议:验证或试用阶段,建议先用命令行快速跑通,确认该 MCP 服务器确实解决了你的问题;确认无误后,再把配置写入 ~/.codex/config.toml 沉淀为长期配置。这样既兼顾快速试验,又便于复用和团队共享。
两种配置方式各有适用场景,对比如下:
| 适用场景 | 临时调试、快速验证某个 MCP 服务器是否可用;偶尔使用一次 | 长期使用、需要反复接入;团队需要共享同一套配置 |
| 优点 | 操作直接、即时生效,无需改动文件;适合快速试验 | 一次配置、长期复用;可纳入版本管理,便于备份和团队共享 |
| 缺点 | 重启后可能丢失,不便于记录和分享;多次配置容易变得繁琐 | 需要编辑文件并重启 Codex 后才会生效;配置格式错误可能导致加载失败 |
选择建议:验证或试用阶段,建议先用命令行快速跑通,确认该 MCP 服务器确实解决了你的问题;确认无误后,再把配置写入 ~/.codex/config.toml 沉淀为长期配置。这样既兼顾快速试验,又便于复用和团队共享。
四、一个务实的建议
不要为了"用 MCP"而用。先明确一个真实痛点——“我正缺某个能力,而某个 MCP 服务器刚好补上”——再去接入。否则很容易陷入配置半天、实际用不上的窘境。
五、实战:接入 GitHub MCP 服务器
以接入 GitHub 官方 MCP 服务器为例,演示从安装、配置到调用工具的完整流程。GitHub MCP 服务器由 GitHub 官方维护,把仓库、Issue、Pull Request 等能力以标准工具的形式暴露给 Codex。
第 1 步:安装服务器
推荐使用官方 npm 包,一条命令完成安装:
npm install -g github-mcp-server
如果你更习惯 Docker,也可以直接运行镜像,避免本机 Node.js 环境差异:
docker pull ghcr.io/github/github-mcp-server
第 2 步:准备访问令牌
GitHub MCP 服务器需要一把 Personal Access Token(PAT)来代表你访问 GitHub。在 GitHub 的 Settings → Developer settings → Personal access tokens 中生成 Token,建议遵循最小权限原则,按需勾选 repo、read:org、read:user 等权限。
第 3 步:在 Codex 中配置
打开 Codex 的配置文件 ~/.codex/config.toml,加入以下内容:
[mcp_servers.github]
command = "github-mcp-server"
env = { GITHUB_PERSONAL_ACCESS_TOKEN = "ghp_你的Token" }
如果使用 Docker,可以将配置改为:
[mcp_servers.github]
command = "docker"
args = ["run", "-i", "–rm", "-e", "GITHUB_PERSONAL_ACCESS_TOKEN", "ghcr.io/github/github-mcp-server"]
另外,不建议把真实 Token 直接写进配置后提交到仓库,可以先通过环境变量注入,例如:
export GITHUB_PERSONAL_ACCESS_TOKEN=ghp_你的Token
第 4 步:验证配置成功
重启 Codex 后,在交互会话中输入:
/mcp
如果看到 github 服务器处于已连接状态,说明配置已经生效。接着可以直接用自然语言驱动工具,例如:
帮我查一下我的 GitHub 账号下有哪些公开仓库。
Codex 会自动调用 GitHub MCP 服务器暴露的仓库查询工具,并返回对应结果。
再举一个写操作的例子,验证 Token 是否具备创建 Issue 的权限:
帮我在 octocat/Hello-World 仓库创建一个 Issue,标题是「补充 README 安装说明」,正文先写一句:目前文档缺少本地启动步骤。
Codex 会先确认目标仓库、Issue 标题和正文信息,然后调用 GitHub MCP 服务器提供的 create_issue(或同类创建 Issue 工具),把仓库名、标题、正文作为参数传入。工具执行成功后,Codex 会把创建结果回显到会话中,示意如下:
已创建 Issue #42:https://github.com/octocat/Hello-World/issues/42
如果调用失败,优先检查 Token 是否过期、权限是否足够(创建 Issue 需要仓库的 issues:write 或 repo 写权限),以及 command 对应的命令是否已正确加入 PATH。
第 5 步:用 Python 代码调用 MCP 工具
除了在 Codex 会话中用自然语言驱动,你也可以在 Python 脚本里直接以 MCP 客户端的方式连接 GitHub MCP 服务器并调用其工具。下面是一个完整示例,演示如何列出仓库并创建 Issue:
import asyncio
import os
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
async def main():
# 1. 配置要启动的 MCP 服务器命令与参数
# 这里直接复用 Codex 配置里相同的启动方式
server_params = StdioServerParameters(
command="github-mcp-server",
args=[],
env={
**os.environ,
# 从环境变量读取 Token,避免硬编码到脚本里
"GITHUB_PERSONAL_ACCESS_TOKEN": os.environ["GITHUB_PERSONAL_ACCESS_TOKEN"],
},
)
# 2. 建立与 MCP 服务器的标准输入/输出通道
async with stdio_client(server_params) as (read, write):
# 3. 创建会话并完成初始化握手
async with ClientSession(read, write) as session:
await session.initialize()
# 4. 查看服务器暴露了哪些工具(便于确认工具名)
tools = await session.list_tools()
print("可用工具:")
for tool in tools.tools:
print(f" – {tool.name}: {tool.description}")
# 5. 调用工具:列出当前账号下的公开仓库
# 工具名以第 4 步打印出的实际名称为准,这里以 list_repositories 为例
repos = await session.call_tool(
"list_repositories",
arguments={"visibility": "public"},
)
print("\\n公开仓库列表:")
for repo in repos.content:
print(f" {repo.text}")
# 6. 调用工具:在指定仓库创建 Issue
issue = await session.call_tool(
"create_issue",
arguments={
"owner": "octocat",
"repo": "Hello-World",
"title": "补充 README 安装说明",
"body": "目前文档缺少本地启动步骤。",
},
)
print("\\n创建 Issue 结果:")
for item in issue.content:
print(f" {item.text}")
if __name__ == "__main__":
asyncio.run(main())
运行前先安装官方 Python SDK 并导出 Token:
pip install mcp
export GITHUB_PERSONAL_ACCESS_TOKEN=ghp_你的Token
python github_mcp_demo.py
运行结果示意如下:
可用工具:
– list_repositories: 列出当前账号下的仓库
– create_issue: 在指定仓库创建 Issue
– …
公开仓库列表:
octocat/Hello-World
octocat/Spoon-Knife
…
创建 Issue 结果:
已创建 Issue #42:https://github.com/octocat/Hello-World/issues/42
需要说明的是,不同版本的 GitHub MCP 服务器暴露的工具名可能略有差异,请以 list_tools() 打印出的实际工具名为准。若调用返回 403,多半是 Token 权限不足;返回 401 则说明 Token 已过期或无效,可回到第 2 步重新生成并检查 scope。
常见问题排查
MCP 连接失败时,先执行 /mcp 查看服务器状态,再对照下表逐项排查。
| Token 过期 | gh auth status,或用 curl -H "Authorization: token ghp_xxx" https://api.github.com/user | 在 GitHub 重新生成 PAT,更新配置中的 Token 并重启 Codex |
| 权限不足 | 执行对应 MCP 工具观察是否返回 403;或 curl -I -H "Authorization: token ghp_xxx" https://api.github.com/repos/OWNER/REPO/issues | 检查 PAT 是否勾选 repo、issues:write 等 scope,补全权限后重新生成 |
| 命令未找到 | which github-mcp-server 或 command -v github-mcp-server | 确认已全局安装并检查 PATH;或在配置中使用绝对路径指定 command |
| 网络不通 | curl -I https://api.github.com | 检查代理、防火墙与 DNS;按需设置 HTTPS_PROXY 等环境变量后重启 |
| 配置格式错误 | cat ~/.codex/config.toml,对照 TOML 语法检查 | 修正引号、方括号、缩进等错误,保存后重启 Codex 再执行 /mcp |
调用工具失败
如果 /mcp 显示 github 服务器已连接,但执行 MCP 工具时仍然报错,可以对照下表排查:
| 工具参数错误 | 在会话中让 Codex 先复述即将调用的工具名和参数;或查看工具描述确认必填字段 | 修正自然语言指令,补全仓库名、Issue 标题、正文等必填参数;工具名以 MCP 服务器最终暴露的工具列表为准 |
| 服务器未连接 | 执行 /mcp 查看 github 服务器状态 | 重启 Codex,确认 command 对应的命令存在且环境变量已生效;仍失败则重新安装并重新加载服务器 |
| 权限不足 | 执行写操作工具,观察是否返回 403;或运行 gh auth status 查看当前 Token 权限 | 确认 PAT 已勾选 repo、issues:write 等所需 scope,重新生成 Token 并更新配置后重启 |
常见问题排查
无论 MCP 连接失败还是调用工具失败,都可以先执行 /mcp 查看服务器状态,再对照下表逐项排查。
| Token 过期 | gh auth status,或用 curl -H "Authorization: token ghp_xxx" https://api.github.com/user | 在 GitHub 重新生成 PAT,更新配置中的 Token 并重启 Codex |
| 权限不足 | 执行对应 MCP 工具观察是否返回 403;或 curl -I -H "Authorization: token ghp_xxx" https://api.github.com/repos/OWNER/REPO/issues | 检查 PAT 是否勾选 repo、issues:write 等 scope,补全权限后重新生成 |
| 命令未找到 | which github-mcp-server 或 command -v github-mcp-server | 确认已全局安装并检查 PATH;或在配置中使用绝对路径指定 command |
| 网络不通 | curl -I https://api.github.com | 检查代理、防火墙与 DNS;按需设置 HTTPS_PROXY 等环境变量后重启 |
| 配置格式错误 | cat ~/.codex/config.toml,对照 TOML 语法检查 | 修正引号、方括号、缩进等错误,保存后重启 Codex 再执行 /mcp |
| 工具参数错误 | 在会话中让 Codex 先复述即将调用的工具名和参数;或查看工具描述确认必填字段 | 修正自然语言指令,补全仓库名、Issue 标题、正文等必填参数;工具名以 MCP 服务器最终暴露的工具列表为准 |
| 服务器未连接 | 执行 /mcp 查看 github 服务器状态 | 重启 Codex,确认 command 对应的命令存在且环境变量已生效;仍失败则重新安装并重新加载服务器 |
小结
- MCP 是 AI 与外部工具之间的通用接口标准。
- 它让 Codex 能连接更多数据源、调用更多工具、扩展能力边界。
- 配置两种方式:命令行 或 ~/.codex/config 配置文件。
下一课,我们学习 AGENTS.md——给 Codex 写一份"项目说明书",让它更懂你的项目规范。
本文是《OpenAI Codex 从零基础到精通》第 9 课。


