ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

MCP 的 Tools、Resources、Prompts 讲解:这次用 TaoToken 走通 Codex 调用

MCP 的 Tools、Resources、Prompts 讲解:这次用 TaoToken 走通 Codex 调用 《MCP 详细讲解》把 Tools、Resources、Prompts 三类能力拆得很清楚但很多人看完后卡在同一个地方概念都懂了下一步该让哪个客户端去调。这次我直接选 Codex 当客户端用 TaoToken 做统一模型通道先打开 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 创建 Key再把三类能力一个个跑通。注意这里不是把 MCP 的理论再讲一遍而是要把上一篇留下的实际操作缺口补上Tools 到底是被谁调用的Resources 怎么进到模型上下文Prompts 又如何变成一个能选中的模板。文章里的 MCP Server 是完整单文件代码存到本地就可以让 Codex 真正调起来。1. MCP 是什么这次选 Codex 当客户端1.1 MCP 的三方角色怎么落到 Codex 上MCP 把「模型连接外部系统」这件事拆成 Host、Client、Server 三个角色。之前只读概念时容易晕落到 Codex 上就具体了用户操作的是 HostCodex 会拉起一条与 MCP Server 的连接这条连接的维护者就是 Client真正暴露能力的是 Server 进程。这个 Server 可以是本地 Node 进程也可以是远程服务我们这次用本地进程来演示。模型本身不会主动去执行任何外部函数。它只是根据对话内容「建议」使用某个工具真正发起调用的是客户端。换句话说MCP 的能力要有人去拉而 Codex 就是我们选的这个人。用户对 Codex 说「查一下东京天气」Codex 判断需要调用 get_weather接着把参数和调用意图发给 MCP ServerServer 执行完把结果返回Codex 再让模型把结果整理成自然语言。这一整条链路里模型从未直接接触天气 API。1.2 准备材料一张表看清 Key、Base URL、模型 ID动手之前先对照这张表三样东西分别填到不同的位置Key 用来鉴权Base URL 是 Codex 请求模型的接口地址模型 ID 决定具体用哪个模型。项目取值用在哪里API KeyYOUR_API_KEY从 TaoToken 创建环境变量 TAOTOKEN_API_KEYBase URLhttps://taotoken.net/api~/.codex/config.toml模型 IDYOUR_MODEL_ID以模型广场为准~/.codex/config.tomlKey 从 TaoToken 注册后创建占位符统一写成 YOUR_API_KEY。Base URL 填给 Codex 时不要带 UTM 参数也不要在末尾追加 /v1直接写 https://taotoken.net/api。模型 ID 先不猜文章里用 YOUR_MODEL_ID 占位实际填写时去 TaoToken 模型广场复制真实 ID。这张表的分工清楚了后面配置就不会把官网和接口混在一起。2. Tools先让 Codex 通过 TaoToken 调一次 get_weather2.1 Tools 的实质是函数调用Tools 是 MCP 里最像「函数调用」的能力。一个 Tool 通常包含名称、描述、输入参数结构和返回结果。模型根据上下文判断是否需要调用它而不是由人手动触发。比如用户说「帮我查一下今天东京的天气」模型可能会选择调用 get_weather传入 cityTokyo工具执行后返回结构化结果模型再把结果整理成人类可读的回答。设计 Tools 时要注意它和普通函数的差异调用可能产生外部动作。查询天气是只读的相对安全但如果一个 Tool 做的是发送邮件、删除文件、创建订单就必须考虑权限、确认机制和审计日志。第一次跑通 MCP 链路时建议先用只读工具练手get_weather 就是很好的起点。2.2 把 Codex 的模型通道指到 TaoTokenCodex 默认有自己的模型供应商配置但我们用 TaoToken 把模型通道统一起来。编辑~/.codex/config.toml加入下面这段内容# ~/.codex/config.toml model YOUR_MODEL_ID # 从 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 模型广场复制不要猜 model_provider taotoken [model_providers.taotoken] name TaoToken base_url https://taotoken.net/api # 注意末尾不要加 /v1 env_key TAOTOKEN_API_KEY然后在当前 shell 里导出环境变量export TAOTOKEN_API_KEYYOUR_API_KEY这里有个容易搞混的点官网地址是给人点的上面已经加了 UTM而base_url是给 Codex 用的接口地址直接写 https://taotoken.net/api。两者不要互相替换。不同版本的 Codex 对env_key字段名可能有细微差异以你本机安装版本的config.example.toml注释为准。2.3 写一个同时暴露三类能力的 MCP Server为了让 Tools、Resources、Prompts 都真实跑起来我们在本地新建~/mcp-demo/server.js用 MCP TypeScript SDK 写一个最小 Server。它同时暴露 get_weather 工具、users-schema 资源和 code_review_summary 模板后面两章继续复用。import { McpServer } from modelcontextprotocol/sdk/server/mcp.js; import { StdioServerTransport } from modelcontextprotocol/sdk/server/stdio.js; import { z } from zod; const server new McpServer({ name: demo-server, version: 0.1.0 }); server.tool( get_weather, { city: z.string().describe(城市名例如 Tokyo) }, async ({ city }) ({ content: [{ type: text, text: ${city}多云18°C湿度 65% }] }) ); server.resource( users-schema, db://schema/users, async (uri) ({ contents: [{ uri: uri.href, text: CREATE TABLE users (id INTEGER PRIMARY KEY, email TEXT UNIQUE, created_at TEXT); }] }) ); server.prompt( code_review_summary, { diff: z.string().describe(待评审的代码 diff) }, ({ diff }) ({ messages: [{ role: user, content: { type: text, text: 请按以下结构做代码评审\n\n1. 变更概览\n2. 潜在问题\n3. 测试建议\n4. 优化建议\n\n代码 diff\n${diff} } }] }) ); await server.connect(new StdioServerTransport());初始化并安装依赖mkdir -p ~/mcp-demo cd ~/mcp-demo npm init -y npm install modelcontextprotocol/sdk zod接着把 MCP Server 注册进 Codex。在~/.codex/config.toml末尾追加[mcp_servers.demo] command node args [/Users/you/mcp-demo/server.js]如果你用 nvm 管理 Nodecommand最好写成node的绝对路径否则 Codex 可能找不到 PATH 里的命令。改完配置后重启 Codex 会话。2.4 验证 Tools 是否真的被 Codex 调起来在 Codex 会话里输入「今天东京天气怎么样」观察它的回应。正常情况下 Codex 会调用 get_weather传入 cityTokyo拿到 Server 返回的天气文本后组织回答。如果看不到调用动作可以追问一句「你刚才调用了哪个工具」让 Codex 把决策过程暴露出来。这一步验证的不只是 MCP Server 本身而是整条链路的连通性Codex 通过 TaoToken 拿到模型响应模型决定调用工具Codex 执行 MCP 调用结果再回到模型进行表达。任何一环断了都会在这里暴露。3. Resources把 db://schema/users 读进 Codex 的上下文3.1 Resources 为什么不是另一种 ToolsResources 可以理解为 MCP Server 提供给客户端读取的上下文数据。它不像 Tools 那样强调执行动作更像是「可读取的文件、记录或数据源」。项目 README、数据库 schema、日志文件、用户日程都可以用 Resource 暴露。通常用 URI 标识比如 file:///project/README.md、db://schema/users。Resources 的核心价值是让模型获得更准确的背景信息。比如你在 IDE 里问「这个函数为什么报错」MCP Server 可以把相关源代码、测试结果、依赖信息作为 Resources 提供给模型。模型不需要猜测而是基于真实上下文分析问题。和 Tools 相比Resources 更适合只读数据它的设计重点不是「执行」而是「提供背景」。3.2 server.js 里的 Resource 长什么样前面 server.js 里已经注册了一个名为users-schema的 ResourceURI 是db://schema/users。它返回的 text 是一段建表语句。当 Codex 需要了解 users 表结构时可以通过这个 URI 把文本放入模型上下文。db://schema/users CREATE TABLE users (id INTEGER PRIMARY KEY, email TEXT UNIQUE, created_at TEXT);这里有个实际建议刚开始接 MCP 的 Resources 时不必一上来就让 Server 直连生产数据库。先用静态文本模拟 schema验证 Codex 能读到、能理解、能基于它回答再逐步把 text 替换成真实查询结果。这样出问题时至少能确定是读取问题还是查询问题。3.3 在 Codex 里触发一次 Resources 读取在 Codex 会话里输入「users 表结构是什么帮我分析 email 为什么可能重复」观察它是否会读取db://schema/users。如果 Codex 没有自动读取直接在对话里要求「先读取 db://schema/users再回答」。一旦 schema 文本进入上下文Codex 就能发现 email 字段带 UNIQUE 约束并指出重复可能来自大小写、NULL 或历史数据导入等方向。提示这段 schema 只是文本Codex 不会自己连数据库。要核对生产库里真实存在的重复 email请在 SQL*Plus 或数据库客户端里执行查询再把结果贴回对话让 Codex 帮你对照分析。4. Prompts把代码评审模板做成可复用入口4.1 Prompts 与 Tools、Resources 的触发差异Prompts 是 MCP Server 暴露的可复用提示模板可以把某类固定工作流封装起来。Tools 通常由模型根据上下文决定是否调用Resources 通常由客户端决定如何附加上下文Prompts 则更像菜单、快捷命令或工作流入口帮助用户以标准方式完成高频任务。比如团队经常需要生成代码评审总结就可以提供一个 code_review_summary Prompt。它要求输入代码 diff、项目背景和关注点然后生成结构化的评审意见。和写死一段提示词相比Prompts 胜在结构稳定所有使用者拿到的都是同一套框架输出粒度相对可控。4.2 在同一个 MCP Server 里注册 Prompt继续用前面的 server.js里面的server.prompt方法注册了 code_review_summary 模板。它接收diff参数把用户消息整理成带四个固定小节的评审请求server.prompt( code_review_summary, { diff: z.string().describe(待评审的代码 diff) }, ({ diff }) ({ messages: [{ role: user, content: { type: text, text: 请按以下结构做代码评审\n\n1. 变更概览\n2. 潜在问题\n3. 测试建议\n4. 优化建议\n\n代码 diff\n${diff} } }] }) );注意这个模板不会自动改变模型行为它只负责把用户消息整理成固定格式。实际生成评审意见的还是模型。也就是说Prompts 直接把「原材料」喂给模型减少它自由发挥的余地但最终回答质量仍取决于模型本身。4.3 在 Codex 里实际调用模板在 Codex 会话里粘一段代码 diff然后说「用 code_review_summary 模板评审这个 diff」。Codex 会读取模板内容按四个小节输出评审意见。如果输出没有出现「变更概览」「潜在问题」等结构多半是模板没被加载。检查~/.codex/config.toml里的mcp_servers路径是否正确然后重启 Codex 会话。这一步跑通后Prompts 的价值就很直观了它把「每次都要重复交代评审格式」变成「只要说出模板名格式自动固定」。团队里其他人用 Codex 时也可以共用同一个 MCP Server 里的模板评审口径不会各写各的。5. 三者怎么区分一场「出差规划」看三种能力的分工5.1 一次出差里的三类能力用一个生活场景把三者串起来用户说「帮我规划一次出差」。Resources 提供日程、预算规则、历史出差偏好模型不需要凭记忆猜用户的住宿习惯Prompts 提供「出差规划」模板规定模型先收集哪些信息、按什么结构输出Tools 则负责查航班、订酒店、建日程。三者配合才能形成完整的智能工作流。如果只把「查航班」做成 Tool模型能飞航班但没有预算规则和日程偏好规划结果就是空泛的。如果只把预算规则做成 Resource模型了解背景却没有执行能力规划只能停在纸面。如果只把出差流程做成 Prompt模型知道步骤却不知道当前时间和目的地模板也无法落地。三类能力本身是互补的。5.2 TaoToken 在这条链路里的真实位置TaoToken 并不替代 MCP Server也不替代 Codex。它负责的是「模型通道」这一层Codex 需要向某个 OpenAI 兼容接口发送请求TaoToken 把接口统一Codex 通过它发起的模型请求会在 TaoToken 账号下产生 Token 消耗。MCP Server 完全不需要知道模型是从哪来的它只负责把工具、资源和模板暴露出来。完整链路是这样的用户在 Codex 提问Codex 把请求发到 https://taotoken.net/api模型返回回答或工具调用意图Codex 接着调 MCP Server 执行 get_weather把结果拿回来交给模型整理最终输出给用户。这条链路里有三层东西各司其职TaoToken 负责通道Codex 负责编排和消耗 TokenMCP Server 负责暴露能力与上下文。以后排障时也按这个分层去看问题不会一头扎进代码里找不到方向。6. 排障与设计建议别把数据库 schema 硬塞给 Tools6.1 Codex 配置常见问题按上面的配置走完最可能遇到三个问题。第一401 Unauthorized。检查环境变量是否真的导出了echo $TAOTOKEN_API_KEY看看是不是 YOUR_API_KEY。如果 Key 复制不完整去官网重新创建。第二model not found。YOUR_MODEL_ID 只是占位符不代表真实模型 IDCodex 会直接报错。去 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 的模型广场复制一个实际存在的 ID 填回来。第三MCP Server 没被加载。改完~/.codex/config.toml之后没重启会话或者args里的路径写错都会造成 Codex 看不到工具。用绝对路径最稳妥。6.2 按边界拆能力而不是把所有东西都塞进 Tools开发 MCP Server 时不要把所有能力都塞进 Tools。很多数据其实只需要被读取做成 Resources 会更清晰、更安全很多固定任务也不一定需要写代码逻辑做成 Prompts 反而更容易维护。Tools 要强调权限和副作用控制Resources 要保证数据新鲜度和访问范围Prompts 要保持结构稳定避免依赖模糊的大段提示词。放到这次 Codex 场景里设计建议可以具体化成四条第一次跑通链路时只用只读工具权限问题先不碰Resources 先给静态文本验证读取正常后再接真实数据源Prompts 的输出结构写成固定小节方便后续对照模板排障涉及生产库的操作由人在本地执行Codex 只负责生成 SQL 和解释结果不代跑线上命令。等你在 Codex 里依次处理过天气、schema 和代码评审三个请求再回头看 MCP 官方文档三类能力就不再是三个名词而是三条可以分开验证的链路。如果还没建 Key先去 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 创建一个再回来把 server.js 跑起来跑通后回到同一页面看看这次 Codex 调用产生的 Token 记录你会对每一层做了什么有更直观的感受。
返回列表