rails-mcp について
rails-mcpは、エージェントのガバナンスと安全性を扱うセルフホスト可能なMCPサーバーです。アクション登録、支出意図の記録、人による承認の監査に対応し、分類結果は常にGATEDで、承認操作はCLI限定です。
主な機能
- 01アクションを常にGATEDに分類
- 02アクションの実施情報を登録
- 03追記型の支出意図台帳
- 04ローリング期間の予算評価
- 05レジストリハッシュと承認状態の確認
- 06CLIによる人の承認
活用シーン
- 01外部インターセプターでアクション分類を確認
- 02支出意図を記録して評価
- 03レジストリの承認状態を確認
MCP 対応
MCPクライアントに、アクション分類、登録情報の照会、予算評価、台帳記録などを行う読み取り中心の6ツールを提供します。人による承認はCLI限定で、MCPツールからは実行できません。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
6掲載時のツール一覧 · 2 週間前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| action_type | string | はい |
詳細
rails-mcp
MCP ツールとして公開される、セルフホスト可能な、呼び出し側が設定する デフォルト拒否のアクションレジストリ +追記専用の 支出台帳 + CLI 専用の 承認監査証跡 です。作者のほかの 6 つの MCP サーバー(mcp-factory、rag-mcp、bus-mcp、desktop-mcp、github-mcp、discord-mcp)とはカテゴリが異なります。これらは開発者向けツール(「エージェントを X に接続する」)ですが、こちらは ガバナンスと安全性 のためのものです。「人間が気づかないうちに、エージェントが取り消せない操作を実行するのを止める」ことを目的としています。
実運用中の内部レジストリ(shared/rails/、テスト 31 件、2026-07-06 以降、実際の複数ボットのフリートで稼働)から移植し、汎用化しました。このパターンは公開前に、社内で先行して導入されました。
これは何か/何ではないか
これは次のものです:
action_type文字列を、登録の有無にかかわらず無条件で GATED(デフォルト拒否)として分類するためのスキーマと純粋なロジックです。- アクションタイプの現在の強制適用状況(
enforcement_layer、enforcement_pointer、ceremony)について、既知の情報を 登録 する場所です。これは情報提供のみを目的とし、決して許可を与えるものではありません。 - 追記専用の 支出意図台帳 と、ローリングウィンドウの予算チェックです。
- 人間による 承認台帳 です。レジストリの現在のハッシュを誰がいつ承認したかを記録します。
これは次のものではありません:
- 強制適用するものではありません。
classify_actionがGATEDを返しても、それ自体では何もブロックしません。独自の PreToolUse フック、権限拒否リスト、または CI ゲートに接続する必要があります。rails-mcp が提供するのはスキーマと監査証跡であり、インターセプターではありません。record_spend_intentは支出意図を記録しますが、ベンダー、有料 API、ブローカーを呼び出すことはありません。また、予算超過の支出が発生するのをここで止めることもできません。 - アクションタイプのデータが事前に読み込まれているわけではありません。 導入する側がそれぞれ独自のレジストリ(YAML/JSON 設定ファイル、または通常の dict)を用意します。特定のフリート向けアクションタイプは、このパッケージには含まれていません。
- マルチテナントではありません。 承認台帳では、レジストリごとに人間のオペレーターを表す文字列が 1 つであることを前提としています。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)を参照してください。
ツール
6 つのツールはすべて読み取り主体です。署名台帳への書き込みはできません。
| ツール | 目的 |
|---|---|
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 桁の 16 進数 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) | 支出意図の記録を 1 件追記します。ベンダーや有料 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 ツール接続しか持たないエージェントが、取り消し不能な操作を自分で承認するのを防ぐために設けられています。append_signoff が MCP ツールとして利用可能であれば、このサーバーへの接続を持つエージェントはどれも自分のレジストリに署名でき、境界が守るべき唯一のことをひそかに無効化できてしまいます。これは、元の shared/rails/ 実装の基盤となった内部設計ルールを反映しています。**監査役を作るレーンは、出荷するレジストリに署名しません。**署名もできる監査役は、監査役ではありません。
この境界が証明しないこと: 署名台帳には暗号学的な改ざん検知機能も、実在する人間の身元との結び付きもありません。その完全性は暗号ではなく、ファイルシステムの ACL とセルフホスト可能なデプロイモデルのみに依存します。シェルまたは台帳のパスへのファイル書き込み権限を持つエージェント(またはその他の誰か)は、自分で rails-mcp sign を実行するか、偽造した {"type": "signoff", ...} の JSONL 行をファイルに直接追記できます。台帳には、それが実際の CLI 呼び出しと異なることを見分ける方法がありません。MCP のみの境界が防ぐのは、このサーバーの MCP ツール接続しか持たないエージェントという、より限定されたケースです。これは人間が何かをレビューした証拠ではなく、そのように解釈すべきではありません。
この境界は単なる慣習ではなく、構造によって強制されています。
rails_mcp/server.pyとrails_mcp/routes.pyは、どこでもappend_signoffをインポートも呼び出しもしません。これは AST ベースのチェックで証明されています(この説明が docstring に含まれることで誤検出する単純な文字列検索ではありません)。チェックは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)。 ~/.claude.jsonが呼び出すエントリーポイントであるrun_server.pyがインポートするのはrails_mcp.serverのみで、rails_mcp.cliはインポートしません。そのため、MCP ツールを提供するプロセスにもsignサブコマンドへのコードパスはありません。
環境変数
| 変数 | デフォルト | 用途 |
|---|---|---|
RAILS_MCP_CONFIG_PATH | unset | 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)は、push/PR のたびにこのテストスイートを実行します。また、上記の Tests バッジがテストスイートの実際の結果と異なる場合はビルドを失敗させます。詳しくは scripts/check_readme_counts.py を参照してください。
テストは106件で、すべてハーメチックです(すべての台帳/設定パスは tmp_path と tests/conftest.py の autouse による環境分離フィクスチャを経由します。実際の ./rails_data/ に触れることはありません)。ネットワーク接続は不要で、ライブスモークテストのゲートも必要ありません。このサーバーには、偽装する外部 API がありません。
tests/test_registry.py(24件)— 移植・一般化されたレジストリロジック:デフォルト拒否のプロパティテスト、不変性、ハッシュの決定性、サインオフ台帳の集約/追記/読み込み、シェルアウトしないことの構造的な証明。tests/test_spend_ledger.py(14件)— 内部テストスイートからほぼそのまま移植:追記/読み込みの往復、予算期間の計算、naive 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 に、絶対パスで run_server.py を呼び出す stdio サーバーとして登録します(エントリポイントが独自のディレクトリを sys.path に追加するため、cwd は不要です)。または、PyPI からインストールした後に rails-mcp コンソールスクリプトを使用します。
ハンドシェイクの確認
.venv/Scripts/python.exe scripts/list_tools.py
トランスポートを開始せずに、登録済みの6つのツール名を出力します。
競合の状況(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が対象を絞って賭けているのは、検査しやすい小規模なセルフホスト可能なレジストリ+台帳+監査証跡スキーマです。変更できない不変条件が1つ(デフォルト拒否の分類は設定で無効化できない)と、明確な境界が1つ(承認はCLIのみで行い、MCPからは到達できない)あります。完全なポリシーエンジン製品ではありません。
対象外
- 実際の適用。 Gitフックも、
settings.jsonの拒否ルールも、昇格ゲートもありません。classify_action/is_action_registeredは、ご自身のインターセプターに組み込んでください。 - お使いの特定の適用メカニズム(フックやCIゲート)が、レジストリの主張どおりに動作しているかを確認するカバレッジ監査ツール。これは独立した実際のエンジニアリング課題(この作者が内部で使用している
coverage_audit.py)であり、このパッケージには含まれません。 - 複数のテナント/運用担当者による承認。 v1では、台帳ごとに運用担当者を1つ指定します。
- 予算超過の支出のブロック。
evaluate_budgetは金額を返しますが、ここには実行前に呼び出しをインターセプトするものはありません。 - 台帳のローテーション/上限設定。
record_spend_intentは無期限に追記します。ローテーション、サイズ上限、アーカイブ機能は組み込まれていません。これは既知の制限ですが、v1の規模ではまだ問題になっていません。
商用サポート
Jaime Bellがメンテナンスしています。本番環境のMCP連携、エージェントガバナンスの仕組み、またはエージェントの信頼性に関する取り組みについては、jaimenbell.devをご覧ください。
独自のMCPサーバーを構築していますか? MCP Starter Kitには、テンプレート、ビルド手順書、この製品のリリースで得られたパッケージングの実践知が含まれています。
mcp-name: io.github.jaimenbell/rails-mcp
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。