关于 rails-mcp
rails-mcp 是面向 Agent 治理与安全的可自托管 MCP 服务,提供动作登记、支出意图记录和人工签署审计。动作分类始终为 GATED;签署只能通过命令行完成,MCP 工具无法自行签署。
主要功能
- 01动作分类始终为 GATED
- 02登记动作执行信息
- 03追加式支出意图账本
- 04滚动窗口预算评估
- 05查询注册表哈希与签署状态
- 06命令行人工签署
适用场景
- 01在外部拦截器中检查动作分类
- 02记录并评估支出意图
- 03查看注册表对应的签署状态
MCP 相关
向 MCP 客户端提供六个只读为主的工具,用于动作分类、登记信息查询、预算评估及账本记录。人工签署仅通过命令行执行,不作为 MCP 工具提供。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
6收录的工具列表 · 更新于 2 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| action_type | string | 是 |
详细介绍
rails-mcp
一个可自托管、由调用方配置的默认拒绝操作注册表 + 仅追加的支出账本 + 仅限 CLI 的签核审计轨迹,以 MCP 工具的形式提供。与作者的另外六个 MCP 服务(mcp-factory、rag-mcp、bus-mcp、desktop-mcp、github-mcp、discord-mcp)属于不同类别——那些是开发工具(“将 Agent 连接到 X”);这个项目则关注治理与安全:“阻止 Agent 在无人察觉的情况下执行不可逆操作。”
它从一个正在运行的内部注册表(shared/rails/,31 个测试,自 2026-07-06 起在真实的多机器人群组中运行)移植并泛化而来——这种模式先在内部落地,然后才公开发布。
这是什么/不是什么
是:
- 用于将
action_type字符串分类为无条件受限(默认拒绝)的模式与纯逻辑,无论是否已注册。 - 用于注册你所了解的操作类型当前执行机制(
enforcement_layer、enforcement_pointer、ceremony)的信息库——仅供参考,绝不放行。 - 仅追加的支出意向账本 + 滚动窗口预算检查。
- 仅追加的人工签核账本,记录谁批准了注册表的当前哈希值以及时间。
不是:
- 不是执行器。
classify_action返回GATED本身并不会阻止任何操作。你仍需将其接入自己的 PreToolUse 钩子、权限拒绝列表或 CI 门禁——rails-mcp 提供模式和审计轨迹,而不是拦截器。record_spend_intent记录支出意向;它绝不会调用供应商、付费 API 或经纪服务,这里也没有任何机制能阻止超预算支出。 - 不预置任何操作类型数据。 每个采用者都需要提供自己的注册表(YAML/JSON 配置文件或普通 dict)。此软件包不包含任何群组的特定操作类型。
- 不是多租户。 签核账本假定每个注册表只有一个人工操作者字符串;对 v1 来说足够,但已知后续版本仍需解决此限制。
永远不能配置的唯一不变量
classify_action(action_type) 始终返回 "GATED"——无论是否已注册、加载了什么配置,都没有任何参数或配置字段能够改变这一点。这就是整个产品。由配置驱动的故障时放行开关会使整个产品主张失去意义,因此 classify()(rails_mcp/registry.py)只接受 action_type 参数:没有任何参数可让调用方使其返回任何放行结果。is_action_registered 回答的是另一个纯粹提供信息的问题——“我是否了解此操作类型的执行机制?”——绝不会影响 GATED 判定。
快速入门(60 秒)
pip install rails-mcp
将以下内容添加到你的 Claude Desktop/Code MCP 配置中:
{
"mcpServers": {
"rails-mcp": {
"command": "rails-mcp"
}
}
}
PATH 中没有控制台脚本?可以改用 "command": "python", "args": ["-m", "rails_mcp"]。
默认情况下,注册表加载时为空(如实为空,而非故障时放行——classify_action 对所有操作仍无条件返回 GATED)。将其指向你自己的操作类型配置:
{
"mcpServers": {
"rails-mcp": {
"command": "rails-mcp",
"env": { "RAILS_MCP_CONFIG_PATH": "C:\\path\\to\\rails.config.yaml" }
}
}
}
配置格式请参阅 examples/rails.config.example.yaml(或 .example.json)。
工具
这六个工具都以读取为主——没有一个能写入签署账本。
| 工具 | 用途 |
|---|---|
classify_action(action_type) | 默认拒绝的判定:始终返回 "GATED"。实现在 rails_mcp/registry.py::classify 中,测试位于 tests/test_registry.py 和 tests/test_server.py。 |
is_action_registered(action_type) | 检查已加载的注册表中是否有对应条目,并在存在时返回 enforcement_layer/enforcement_pointer/ceremony。实现在 rails_mcp/routes.py::is_action_registered 中,测试位于 tests/test_routes.py。 |
get_rails_hash() | 已加载注册表的 12 位十六进制 sha256 摘要及条目数——这是人工签署时记录的值。实现在 rails_mcp/registry.py::rails_hash 中,测试位于 tests/test_registry.py。 |
get_signoff_state() | 当前有效的人工签署,或 null。只读。实现在 rails_mcp/registry.py::load_signoff_state 中,测试位于 tests/test_registry.py 和 tests/test_routes.py。 |
record_spend_intent(amount_usd, vendor, purpose, actor) | 追加一条支出意向记录。绝不会调用供应商或付费 API。实现在 rails_mcp/spend_ledger.py::record_spend_intent 中,测试位于 tests/test_spend_ledger.py。 |
evaluate_budget(limit_usd, window_days=30.0) | 滚动窗口内的支出总额与限额对比。绝不会抛出异常。实现在 rails_mcp/spend_ledger.py::evaluate_budget 中,测试位于 tests/test_spend_ledger.py。 |
仅限 CLI 的签署边界——以及它存在的原因
append_signoff——用于记录人工批准注册表当前哈希的函数——刻意不作为 MCP 工具提供,今后也不会提供。它仅作为 CLI 命令开放,供人工手动运行:
rails-mcp sign --operator "jaime" --note "reviewed 2026-07-16 config"
**原因:**此边界旨在防止仅持有此服务 MCP 工具连接的 Agent 自行批准不可逆操作。如果 append_signoff 可作为 MCP 工具调用,任何持有此服务连接的 Agent 都能签署自己的注册表——悄无声息地破坏此边界所要执行的唯一约束。这与原始 shared/rails/ 实现所遵循的内部设计规则一致:**构建审计器的通道,绝不签署其交付的注册表。**既能签署又能审计的,就不是审计器。
**此边界不能证明什么:**签署账本没有防篡改的密码学证据,也没有与真实人工身份绑定——其完整性完全依赖文件系统 ACL 和可自托管部署模式,而非密码学。拥有该账本路径的 shell 或文件写入权限的 Agent(或任何人)都能自行运行 rails-mcp sign,也能直接向文件中追加伪造的 {"type": "signoff", ...} JSONL 行——账本无法区分这种操作与真实的 CLI 调用。MCP 专属边界仅能阻止更狭窄的情况:某个 Agent 仅持有此服务的 MCP 工具连接;它不能证明有人进行了人工审查,也不应被理解为能证明这一点。
此边界通过结构实现,而不只是约定:
rails_mcp/server.py和rails_mcp/routes.py在任何地方都不会导入或调用append_signoff——这一点由基于 AST 的检查证明(而非简单的字符串 grep;后者会因这段说明出现在其文档字符串中而产生误报),检查位于tests/test_server.py::test_append_signoff_unreachable_via_any_mcp_tool。- 已注册的 MCP 工具集恰好是上述 6 个以读取为主的工具——不存在
sign/append_signoff/revoke_signoff工具,由tests/test_server.py::test_all_six_rails_tools_registered检查。 - 一项行为测试会调用每个已注册工具,并确认绝不会创建签署账本文件(
test_no_registered_tool_can_create_a_signoff_record)。 run_server.py(~/.claude.json调用的入口点)只导入rails_mcp.server,从不导入rails_mcp.cli——因此,即使是提供 MCP 工具的进程,也没有通往sign子命令的代码路径。
环境变量
| 变量 | 默认值 | 用途 |
|---|---|---|
RAILS_MCP_CONFIG_PATH | 未设置 | rails.config.{yaml,yml,json} 的路径。未设置 = 空注册表(未注册任何内容,classify_action 仍无条件返回 GATED)。 |
RAILS_MCP_SIGNOFF_LEDGER_PATH | ./rails_data/signoff.jsonl | 仅追加式签署账本的存放位置。 |
RAILS_MCP_SPEND_LEDGER_PATH | ./rails_data/spend.jsonl | 仅追加式支出意图账本的存放位置。 |
配置文件格式
actions:
deploy_prod:
enforcement_layer: "L1"
enforcement_pointer: "CI gate requires a passing e2e suite + a manual approve step"
ceremony: "operator hand"
或者使用更精简的 3 元素格式(与内部注册表的原生格式一致):
actions:
deploy_prod: ["L1", "CI gate requires a passing e2e suite + a manual approve step", "operator hand"]
JSON 的效果相同({"actions": {"deploy_prod": [...]}})。完整示例请参阅
examples/。
enforcement_layer 应当如实填写,而非一厢情愿——"prose"
(尚无结构性护栏,只有文档)是合法且正确的值。
仅仅因为感觉更好,就把 "prose" 条目升为 "L1",会彻底违背如实登记的初衷。
测试
.venv/Scripts/python.exe -m pytest -q
CI(.github/workflows/ci.yml)会在每次推送 / PR 时运行此测试套件;如果上方 Tests 徽章与测试套件实际报告的结果不一致,就会导致构建失败——参见
scripts/check_readme_counts.py。
共 106 项测试,全部为隔离测试(所有账本 / 配置路径都通过 tmp_path +
tests/conftest.py 中自动使用的环境隔离夹具处理;不会触及真实的
./rails_data/)。无需网络,也无需实时冒烟测试门禁——此服务没有需要伪造的外部 API。
tests/test_registry.py(24 项)——移植并泛化的注册表逻辑: 默认拒绝属性测试、不可变性、哈希确定性、签署账本折叠 / 追加 / 加载、结构性无 shell 外调用证明。tests/test_spend_ledger.py(14 项)——几乎原样移植自内部测试套件:追加 / 加载往返、预算窗口计算、对朴素 datetime 的如实降级、结构性无效应器证明。tests/test_config.py(18 项)——新增:环境变量解析、两种入口格式的 YAML / JSON 加载、未配置时为空、显式指定路径不存在时明确报错。tests/test_routes.py(14 项)——MCP 工具接口的业务逻辑,直接进行测试。tests/test_server.py(17 项)——工具注册、透传正确性,以及仅限 CLI 的签署结构性与行为证明。tests/test_cli.py(8 项)——serve/sign子命令,包括验证sign确实仅追加,并会打印易读的确认信息。tests/test_check_readme_counts.py(11 项)——此 CI 门禁自身的 TDD 测试套件:针对匹配 / 漂移 / 缺失夹具,端到端测试解析声明数量、解析实际数量、比较以及main()。
安装 / 连接
python -m venv .venv
.venv/Scripts/python.exe -m pip install -e ".[test]"
在 ~/.claude.json 的 mcpServers.rails-mcp 下注册为 stdio 服务,通过绝对路径调用 run_server.py(无需 cwd——入口会将自身目录添加到 sys.path);或者从 PyPI 安装后使用 rails-mcp 控制台脚本。
握手检查
.venv/Scripts/python.exe scripts/list_tools.py
打印六个已注册工具的名称,不会启动传输。
竞争格局(已于 2026-07-16 核实)
最接近的既有方案不是托管式死亡开关产品——那解决的是另一个问题(“操作人员是否仍然存活并在监看”)。 实际核实后,更接近的对比如下:
- Microsoft Agent Governance Toolkit ——采用 MIT 许可证,由 Microsoft 支持,政策执行范围更广、更全面,覆盖 OWASP Agentic Top 10。属于相邻领域中“知名度高、资源充足”的新参与者。
- Marchward ——在功能上最为接近:服务端凭据注入、支出上限、针对不可逆操作的人类审批关卡、防篡改日志,以及采用 Apache-2.0 许可证的开源代理。
- AgentLedger ——采用 AGPL-3.0 许可证,与
spend_ledger.py有重叠之处(预算、审批、审计跟踪)。
rails-mcp 选择了更狭窄的方向:一个小巧、可检查、可自托管的注册表+账本+审计跟踪架构,具有一项不可妥协的不变量(默认拒绝分类绝不能被配置移除)和一项硬性边界(签核只能通过 CLI 进行,绝不允许通过 MCP 访问)——它不是一款完整的策略引擎产品。
不在范围内
- 实际执行。 不提供 git hooks、
settings.json拒绝规则或晋级关卡。你需要将classify_action/is_action_registered接入自己的拦截器。 - 覆盖审计器,用于检查你的特定执行机制(hook、CI 关卡)是否确实按注册表所述运行。这是独立且真实的工程工作(作者内部使用的
coverage_audit.py),不属于此软件包。 - 多租户/多操作人员签核。 v1 中,每个账本只对应一个操作人员字符串。
- 阻止超预算支出。
evaluate_budget会告诉你金额;这里没有任何机制会在调用发生前拦截它。 - 账本轮换/封顶。
record_spend_intent会无限追加——内置功能不包括轮换、大小上限或归档。这是已知限制,但在 v1 的规模下尚未构成问题。
商业支持
由 Jaimen Bell 维护。有关生产环境 MCP 集成、Agent 治理护栏或 Agent 可靠性工作,请参阅 jaimenbell.dev。
正在构建自己的 MCP 服务?MCP Starter Kit 提供模板、构建指南,以及发布该服务过程中的经验教训。
mcp-name: io.github.jaimenbell/rails-mcp
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。