关于 Rail
Rail 是供代表人类购物的 Agent 使用的预算、审批与收据 MCP 服务,默认采用不产生真实交易的 dry-run 模式。它通过本地账本和人工确认控制支出,并以 Stripe Link 作为结算接口,而非发行银行卡。
主要功能
- 01设置并读取本地预算
- 02记录待审批购买提案
- 03人工批准或拒绝提案
- 04读取收据并撤销 dry-run 结算
- 05通过环境门控启用 Link 结算
适用场景
- 01为 Agent 设定购买额度
- 02在购买结算前要求人工批准
- 03查看支出收据并恢复预算
MCP 相关
Rail 向 MCP 客户端提供预算、提案决策和收据管理工具。默认 dry-run 不连接网络或扣款;真实 Link 请求需显式设置多项环境门控。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
7收录的工具列表 · 更新于 3 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| note | string | 否 | 此预算的可选备注 |
| currency | string | 否 | 货币代码;默认值为 USD |
| amount_usd | number | 是 | 以 USD 计的预算金额 |
详细介绍
Rail MCP
Rail 是一个预算、审批和收据层,Agent 代表人类购买商品时会调用它。默认以 dry-run 模式运行,并封装 Stripe Link 进行结算,而非发放卡片。
它不是市场、店面或外联工具。Rail 管理预算、审批关卡和收据账本。
快速入门
需要 Node.js 20+。运行已发布的软件包:npx -y rail-mcp。默认模式为 dry-run:不联网,也不收费。
Claude Desktop 和任何接受 mcpServers 块的其他宿主:
{
"mcpServers": {
"rail": {
"command": "npx",
"args": ["-y", "rail-mcp"]
}
}
}
Cursor: 一键安装(安装链接)。config 值是 {"command":"npx","args":["-y","rail-mcp"]} 的 base64 编码。
cursor://anysphere.cursor-deeplink/mcp/install?name=rail&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsInJhaWwtbWNwIl19
Grok Bot: 使用 npx -y rail-mcp 添加自定义 MCP。
不要将 Stripe 或 Link 密钥(STRIPE_SECRET_KEY、LINK_ACCESS_TOKEN 或实时支出标记)放入此共享代码片段。除非在共享配置之外有意设置这些关卡,否则不会产生真实扣款。请参阅 Stripe Link 接口。
账本文件(budget.json、proposals.json、receipts.json)会写入用户主目录中的 ~/.rail;如果设置了 RAIL_DATA_DIR,则写入该目录。这些是本地状态,不属于 npm 软件包。默认情况下,文件位置不受进程工作目录影响,因此即使宿主从 / 启动服务,文件仍会写入主目录。
示例
设置预算、提出购买申请、由人类审批,然后读取收据。dry-run 不会将资金转出本机。
set_budget→{ "amount_usd": 50, "note": "week1" }propose_purchase→{ "merchant": "Acme", "amount_usd": 12, "rationale": "need widgets" }get_budget仍显示剩余预算50.00和open_proposals: 1。申请会保持待处理状态,直到人类作出决定。decide_proposal→{ "proposal_id": "prop_…", "decision": "approve" }get_receipts返回一条settled_dry_run收据,其中包含settlement_ref。剩余预算为38.00。
拒绝申请不会产生支出。refund_receipt 会撤销 dry-run 结算并恢复预算。
工具
| 工具 | 用途 |
|---|---|
set_budget | 覆盖本地预算限额。不转移资金 |
get_budget | 读取预算、已支出金额、剩余金额和未处理申请数量 |
propose_purchase | 仅记录待处理的购买意向。不转移资金。之后需要人类审批 |
list_proposals | 按 pending(默认)/ approved / rejected / all 读取申请 |
decide_proposal | 人类确认步骤。approve 会完成结算(生成 dry-run 收据和 settlement_ref,并扣减剩余预算)。reject 不产生支出。不能重复决定 |
get_receipts | 按时间倒序读取收据 |
refund_receipt | 人类确认步骤。撤销 dry-run 结算并恢复预算 |
权限模型
提出购买的成本很低,结算购买则不然。Agent 可以记录购买意向,而不转移资金。人类应确认结算购买或撤销收据的调用。
主机应从 tools/list 读取 title、description 和 annotations。每个提示都经过显式设置。否则,规范默认值(readOnlyHint 为 false、destructiveHint 为 true、openWorldHint 为 true)会将每个工具都视为具有破坏性的开放世界写入操作。Rail 的账本位于本地。默认模式为 dry-run:不联网,也不扣款。
| 工具 | readOnlyHint | destructiveHint | idempotentHint | openWorldHint | 主机应如何处理 |
|---|---|---|---|---|---|
set_budget | false | false | true | false | 允许。仅覆盖本地限额。相同参数不会累加或花费 |
get_budget | true | false | true | false | 允许。只读 |
propose_purchase | false | false | false | false | 允许。新增一条待处理意向,不花费任何资金。每次调用都会创建一条新提案 |
list_proposals | true | false | true | false | 允许。只读 |
decide_proposal | false | true | true | false | 需向人类确认。approve 会结算并扣减剩余预算。重复调用不会再次结算 |
get_receipts | true | false | true | false | 允许。只读 |
refund_receipt | false | true | true | false | 需向人类确认。撤销 dry-run 结算并恢复预算。重复调用不会再次退款 |
destructiveHint 是确认信号,且只有 decide_proposal 和 refund_receipt 的值为 true。每个工具的 openWorldHint 都是 false:dry-run 不会离开账本,而实时 Link 仍受独立的环境门控保护。注解只是提供给主机的提示,本身不会转移资金。
模式默认为 RAIL_MODE=dry_run。金额以整数美分存储;工具以保留 2 位小数的 USD 显示金额。ID:prop_…、rcpt_…,dry-run Link 引用位于 settlement_ref 上,格式为 lsrq_dry_…。
本地检出
tsx 是此仓库用于内部自用测试的开发依赖。npm run smoke 会直接运行 TypeScript 源码,无需构建。npm start 会先编译,再运行 dist/index.js(rail-mcp 二进制文件指向的同一个文件)。
npm install
npm start # tsc → dist/, then stdio MCP server
npm run dev # tsx watch src/index.ts
npm run smoke # dry-run ledger smoke test; throwaway dirs only (never ./data, ~/.rail, or RAIL_DATA_DIR)
npm run smoke 会强制使用 RAIL_MODE=dry_run,绝不会启用实时扣款门控,并且只会将账本写入其创建并删除的临时目录。即使环境中设置了 RAIL_DATA_DIR,./data、~/.rail 和 RAIL_DATA_DIR 也不会受到影响。其中一项检查会将服务的工作目录设为 /,并将 HOME 指向一个临时目录,然后调用一个工具。该调用会成功,并且该项检查的账本会创建在临时主目录下,而不是 /data 或真实的 ~/.rail 下。在该启动过程中,显式设置的 RAIL_DATA_DIR 仍会覆盖默认值。
Stripe Link 接口
Rail 向 Link 请求一次性凭证。Rail 仍负责决定预算和策略,并写入收据。此接口不会发卡,也不会渲染 UI。
RAIL_MODE=dry_run(默认值,包括未设置时):createSpendRequest会返回一个虚构的 Link 支出请求 ID,状态为dry_run_pending_human。不会发送 Stripe 或 Link HTTP 请求。批准后,会将该 ID 作为settlement_ref存入settled_dry_run收据,并扣减剩余预算。RAIL_MODE=live但未通过门控: 除非同时设置STRIPE_SECRET_KEY和RAIL_LIVE=1,否则会抛出live mode not enabled — set keys and get explicit human approval。提案会保持待处理状态,且不会写入收据。- Live 模式且通过这两项门控:
POST https://api.link.com/spend_requests的请求正文仅作脚手架(参见src/stripeLink.ts)。除非设置RAIL_ALLOW_LIVE_CHARGE=1,否则不会发送任何内容。 RAIL_ALLOW_LIVE_CHARGE=1: 唯一允许调用 Link 的分支,且还必须设置LINK_ACCESS_TOKEN。STRIPE_SECRET_KEY仅作为是否存在的门控条件,绝不会发送。不会创建 Stripe Issuing 卡片。文档:Link CLI、link-cli、面向 Agent 的 Issuing。- 只有在刻意设置这些环境变量后,才会启用 Live 支出。已提交的 Link 请求会保存为
link_pending_human,不会扣减 dry-run 预算。CI 和npm run smoke均使用 dry-run,不会扣款。
| 环境变量 | 作用 |
|---|---|
RAIL_MODE | dry_run(默认值)或 live |
RAIL_DATA_DIR | 账本目录。默认为用户主目录下的 ~/.rail。显式设置的值会覆盖默认值 |
STRIPE_SECRET_KEY | Live 模式必需。不用于发卡,也不用作 Link 持有者令牌 |
RAIL_LIVE=1 | 与密钥同时使用的显式 Live 模式批准 |
RAIL_ALLOW_LIVE_CHARGE=1 | 发送任何 Link HTTP 请求前的额外门控 |
LINK_ACCESS_TOKEN | Link OAuth 令牌。实际运行脚手架 POST 前必须设置 |
明确不包含的目标
- 不提供市场 UI
- 不进行推广联系或消息发送
- 不发卡
- dry-run、CI 或 smoke 中不进行真实扣款
许可证
MIT。版权所有 2026 Thomas Stockham。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。