Cordon for MCP について
Cordonは、LLMとMCPサーバーの間に置くセキュリティゲートウェイです。エージェントのツール利用を制御し、ポリシー、承認、監査ログで呼び出しを管理します。
主な機能
- 01ツール別・サーバー別ポリシー
- 02端末またはSlackでの承認
- 03構造化された呼び出し監査ログ
- 04読み取り専用・SQL対応ポリシー
- 05ツールの非表示とカタログ制限
- 06呼び出し順序への追加制約
活用シーン
- 01データベース書き込みに承認を要求
- 02エージェントのツール利用を監査
- 03上流で追加されたツールを遮断
- 04機密情報の読み取り後の操作を制限
MCP 対応
CordonはMCPサーバーを集約してプロキシし、LLMクライアントと上流サーバーの間でツール呼び出しを検査します。stdioとHTTPに対応し、ポリシーで制御されたツールをMCPクライアントに提供します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
Cordon for MCP
MCP ツール呼び出しのためのセキュリティゲートウェイ
クイックスタート • Cordon を選ぶ理由 • 仕組み • 設定 • ロードマップ • コントリビューション
どの企業も AI エージェントを導入したいと考えています。しかし、エージェントにデータベースの鍵を渡したい企業はありません。
Cordon が信頼のギャップを埋めます。
Agent Toolbelt のメンテナーが開発 — 25 以上の MCP ツール、npm の週間ダウンロード数は約 1,600 件。
デモ
https://github.com/user-attachments/assets/153d978f-6303-443a-b49b-b4ec7ebf0452
課題
Model Context Protocol (MCP) によって、AI エージェントにデータベース、ファイルシステム、API、クラウドインフラストラクチャなどの強力なツールへのアクセスを簡単に付与できるようになりました。
しかし、MCP には組み込みのセキュリティモデルがありません。監査ログも、承認ワークフローも、レート制限もありません。現在、AI エージェントは停止状態か完全な管理者権限のどちらかです。その中間はありません。
これこそが、AI エージェントの本番環境への導入を妨げている最大の障壁です。
解決策
Cordon は、LLM と MCP サーバーの間に配置されるセキュリティゲートウェイです。
ファイアウォール、監査ツール、リモートコントロールとして機能し、AI エージェントができること、できないことを完全に可視化し、制御できるようにします。
┌─────────┐ ┌──────────┐ ┌──────────────┐
│ LLM / │ ──▶ │ Cordon │ ──▶ │ MCP Server │
│ Agent │ ◀── │ Gateway │ ◀── │ (database, │
└─────────┘ └──────────┘ │ fs, APIs) │
│ └──────────────┘
├── Policy Engine
├── Audit Logger
└── Approval Workflows
インフラストラクチャの変更は不要です。書き換えも不要です。設定ファイル 1 つで使えます。
クイックスタート
ステップ 1 — 初期化
プロジェクト内(claude_desktop_config.json がある場所)で次を実行します。
npx @getcordon/cli init
既存の Claude Desktop MCP 設定を読み込み、cordon.config.ts を生成して、すべてのツール呼び出しが Cordon 経由になるよう Claude Desktop の設定を書き換えます。
ステップ 2 — 起動
npx @getcordon/cli start
Cordon が起動し、MCP サーバーに接続して、ツール呼び出しのインターセプトを開始します。Claude Desktop を再起動すると、すべてのツール呼び出しがゲートウェイ経由になります。
手動セットアップ
手動で設定する場合は、グローバルにインストールして設定ファイルを作成します。
npm install -g @getcordon/cli
cordon init
cordon init を実行すると、cordon.config.ts が生成されます。
import { defineConfig } from '@getcordon/policy';
export default defineConfig({
servers: [
{
name: 'database',
transport: 'stdio',
command: 'npx',
args: ['-y', '@my-org/db-mcp-server'],
policy: 'read-only', // Block all write operations
},
{
name: 'github',
transport: 'stdio',
command: 'npx',
args: ['-y', '@modelcontextprotocol/server-github'],
policy: 'approve-writes', // Reads pass; writes require approval
tools: {
delete_branch: 'block', // Never, regardless of approval
},
},
],
audit: {
enabled: true,
output: 'stdout', // or 'file'
},
approvals: {
channel: 'terminal',
timeoutMs: 60_000, // auto-deny after 60s; the request is retained
// and replayable if approved late
},
});
Cordon を選ぶ理由
| Cordon なし | Cordon あり |
|---|---|
| エージェントがツールに無制限にアクセスできる | ツールごとにきめ細かなポリシーを設定できる |
| エージェントの操作内容を確認できない | すべての呼び出しを記録した構造化監査ログ |
| 「エージェントがテーブルを削除したのでは?」 | リアルタイムのターミナル承認 |
| 読み取りと書き込みが同じように扱われる | approve-writes により、読み取りは自動的に許可される |
| コンプライアンスチームが AI の利用を認めない | 監査ログをすぐにエクスポートできる |
機能
ポリシーエンジン
ツールごと、サーバーごと、またはグローバルにルールを定義できます。ツールレベルのポリシーはサーバーポリシーより優先されます。
// Server-level default
policy: 'approve-writes',
// Per-tool overrides
tools: {
query: 'allow', // reads: pass through
execute: 'approve', // writes: pause for human approval
drop_table: 'block', // catastrophic: always reject
list_tables: 'log-only', // audit but don't interrupt
},
人間が介在する承認
ツールの呼び出しに承認が必要な場合、Cordon はエージェントを一時停止し、ターミナルで直接確認を求めます。
╔══════════════════════════════════════╗
║ ⚠ APPROVAL REQUIRED ║
╚══════════════════════════════════════╝
Server : database
Tool : execute_sql
Args :
{
"query": "DELETE FROM sessions WHERE expires_at < NOW()"
}
[A]pprove [D]eny
>
エージェントは待機します。判断するのはあなたです。
Slack を使いたい場合は、ダッシュボードの Slack に追加 からワークスペースを一度接続します。作成や貼り付けが必要なボットトークンはありません。その後、approvals: { channel: 'slack' } を設定します。フラグが付いた呼び出しがチャンネルに承認/拒否カードを投稿し、人間がクリックするまで一時停止します。また、承認者の名前は監査記録に書き込まれます。Slack 承認の設定をご覧ください。
時間内に誰も応答しなかった場合。 呼び出しは拒否され、エージェントは処理を続けますが、リクエストは失われません。Cordon は保留中の承認をコンテキストごと保持し、ダッシュボードの 変更内容 → タイムアウトした承認 に一覧表示します。カードの期限が切れた後に誰かが承認した場合、その遅れて届いた判断が記録され、呼び出しを再実行できます。
cordon replay <callId>
再実行ではツールが実行され、結果が replay of late-approved call という理由とともに同じ監査ストリームに記録されます。復旧されるのは ツール呼び出しであり、エージェントのセッションではありません。呼び出し元のエージェントはすでに終了しています。再実行できるのは、タイムアウト後に承認された呼び出しだけです。すでに実行済みの呼び出しを再実行すると、二重に実行されてしまいます。
監査ログ
すべてのツール呼び出しは、リクエスト、ポリシーの判断、応答、処理時間を含む構造化 JSON として記録されます。コンプライアンス担当者向けに、標準出力にパイプするか、ファイルに書き込みます。
{"event":"tool_call_received","callId":"...","serverName":"database","toolName":"execute_sql","timestamp":1773434469641}
{"event":"approval_requested","callId":"...","serverName":"database","toolName":"execute_sql","timestamp":1773434469641}
{"event":"tool_call_approved","callId":"...","serverName":"database","toolName":"execute_sql","timestamp":1773434471203}
{"event":"tool_call_completed","callId":"...","durationMs":34,"isError":false,"timestamp":1773434471237}
読み取り専用モード
1 つのポリシー設定で、サーバー全体のすべての書き込み操作をブロックできます。書き込みに該当する操作を推測する必要はありません。Cordon がツール名から検出します。
policy: 'read-only' // any tool starting with write/create/update/delete/drop/execute/... is blocked
非表示のツール
モデルに決して表示させないツールを設定できます。呼び出しを拒否するだけでなく、tools/list の応答から完全に除外します。これにより、プロンプトインジェクションの攻撃対象領域を減らせます。モデルがツールの存在を知らなければ、だまされて呼び出すこともありません。
{
name: 'database',
policy: 'approve-writes',
tools: {
drop_table: 'block', // call attempts are rejected
internal_admin: 'hidden', // not advertised to the client at all
},
}
SQL 対応ポリシー
1 つのツールで任意の SQL を受け付けるデータベース MCP サーバー(Postgres、SQLite、BigQuery など)では、ツール名に基づく推測だけでは不十分です。query という名前からは、エージェントが SELECT を実行しようとしているのか、DROP TABLE を実行しようとしているのかわかりません。Cordon には、SQL 自体を解析し、文の種類に基づいて判断する 2 つのポリシーが用意されています。
tools: {
// Allow SELECTs (including CTEs that wrap a SELECT). Block everything else.
query: 'sql-read-only',
// Reads pass; writes (INSERT/UPDATE/DELETE/DROP/ALTER/...) pause for human approval.
execute: 'sql-approve-writes',
// When the tool takes SQL in a different arg name:
run: { action: 'sql-read-only', sqlArg: 'statement' },
}
どちらのポリシーもデフォルトでは PostgreSQL 方言を使用し(その他の方言は後日対応予定)、フェイルクローズで動作します。解析できない SQL は許可されず、ブロックされます。SELECT 1; DROP TABLE users; のようなプロンプトインジェクションのパターンや、ブロックコメントで囲まれたキーワードも、AST パーサーによって書き込みとして正しく分類されます。
クローズドワールドのツールカタログ
上流サーバーが公開すると想定されるツールの範囲を、正確に宣言します。今後のリリースで上流サーバーに新しいツールが追加された場合、明示的に許可するまで Cordon が自動的にブロックします。
{
name: 'postgres',
command: 'npx',
args: ['-y', '@modelcontextprotocol/server-postgres', process.env.POSTGRES_URL!],
policy: 'read-only',
knownTools: ['query', 'list_tables', 'describe_table'], // your approved surface
onUnknownTool: 'block', // default when knownTools is set
}
次の Postgres MCP リリースで truncate_table が追加された場合、Cordon は stderr に警告を出してブロックします。ポリシーを更新する必要はありません。後方互換性のあるオープンワールドの動作にするには、knownTools を未定義のままにします。
エージェントごとのポリシーと呼び出しグラフの制約

ツールごとのポリシーは、危険な個々の呼び出しを検出します。呼び出しグラフのルールは、意図しない順序で使われる許可済みツールの組み合わせ、つまり危険な一連の呼び出しを検出します。典型的な例として、エージェントが read_data で機密データを読み取り(許可されています)、その後 write_file でディスクに書き込みます(こちらも許可されています)。個々の呼び出しに問題はありません。問題なのは呼び出しの順序です。
Cordon の呼び出しグラフのルールは、ツールごとのポリシーに追加で適用され、累積的に作用します。重大度を引き上げることはできますが、引き下げることはできません。
export default defineConfig({
// Optional identity for this Cordon process. Surfaced in audit logs.
agentId: 'et-acquisition-agent',
servers: [{
name: 'demo-db',
transport: 'stdio',
command: 'npx',
args: ['-y', '@my-org/db-mcp'],
policy: 'approve-writes',
}],
callGraph: [
// Reading data and then writing to disk is the exfil shape — block it,
// even though write_file would only require approval on its own.
{ from: 'read_data', to: 'write_file', action: 'block',
reason: 'No file writes after database reads.' },
// Glob matching: any send_* tool right after a database read needs human approval.
{ from: 'read_data', to: 'send_*', action: 'approve' },
// `*` matches anything: after a privileged read, every next call must be approved.
{ from: 'sensitive_read', to: '*', action: 'approve' },
],
});
ルールとツールごとのポリシーの組み合わせ方(重大度の累積):
重大度の順序:allow < approve < block。
呼び出しグラフのルールは、そのアクションの重大度がツールごとの判定より高い場合にのみ有効になります。つまり、次のようになります。
action: 'block'のルールは、ツールごとのallowポリシーを上書きします ✓action: 'approve'のルールはallowを上書きしますが、blockを引き下げることはありません ✓action: 'allow'のルールが、より厳格な基本設定を緩和することはありません。何も変更しません- 複数のルールに一致する場合は、最も重大度の高いルールが優先されます(設定の順序は関係ありません)
一方向のラチェットです。厳格化のみ可能で、緩和はできません。
監査ログに呼び出しチェーンのコンテキストが追加されます。 すべての tool_call_received イベントに、直前に正常に実行されたツールを示す previousTool が含まれるようになりました。ブロックされたイベントや承認が必要なイベントには、ルールが適用された場合、callGraphRule: { from, to } も含まれます。
{"event":"tool_call_received","toolName":"write_file","previousTool":"read_data","..."}
{"event":"tool_call_blocked","toolName":"write_file","reason":"No file writes after database reads.","previousTool":"read_data","callGraphRule":{"from":"read_data","to":"write_file"},"..."}
v1 のスコープ(本番環境でエージェントごとのポリシーを運用する場合はお読みください):
stdio モード(および現在のシングルテナント HTTP モード)では、1 つの Cordon プロセスが 1 つのエージェント ID に対応します。そのため、設定の agentId は呼び出しごとの実行時 ID ではなく、このデプロイメントを識別します。1 つの Cordon インスタンスで、異なるポリシーを持つ複数のエージェントをホストするマルチテナント HTTP ゲートウェイは、まだ対応待ちです。対応時には agentId の設定元に HTTP ヘッダーが追加されるため、設定を書き換える必要はありません。
lastTool が更新されるのは、上流から正常に戻った場合のみです。ブロック、拒否、トランスポート障害が発生した呼び出しでは、チェーンは更新されません。v1 ではプロービングを検出できません。たとえば、攻撃者が fs:delete を試みて(ブロックされます)、その後 http:post を実行した場合、http:post はプローブではなく、プローブより前に実行されたツールを基準に評価されます。これは意図的な設計です。ブロックされたあと処理を続ける正当なフローで、ブロックされた試行すべてを追跡すると、過剰に誤検知するためです。実際の悪用データが得られた段階で、改めて検討してください。
仕組み
Cordon は、単一の集約型 MCP プロキシとして動作します。Claude Desktop が MCP サーバーに直接接続する代わりに、Cordon に接続します。その後、Cordon が内部でサーバーを管理します。
Before: Claude ──▶ MCP Server A (full access)
Claude ──▶ MCP Server B (full access)
After: Claude ──▶ Cordon ──▶ MCP Server A (governed)
──▶ MCP Server B (governed)
LLM クライアントと MCP サーバーは、まったく変更する必要はありません。設定の修正は cordon init が行います。
HTTP トランスポート(n8n およびその他の HTTP 対応 MCP クライアント)
HTTP 経由で MCP を利用するクライアント(n8n の MCP Client Tool ノード、子プロセスを起動できないホスト型エージェント、ネットワークエンドポイントを必要とするその他のクライアントなど)向けに、Cordon は stdio の代わりに HTTP リスナーとして実行できます。
export CORDON_GATEWAY_TOKEN=your-secret-token
npx @getcordon/cli start --http --port 7777
# [cordon] HTTP gateway listening on http://127.0.0.1:7777/mcp
または、設定で指定します。
import { defineConfig } from '@getcordon/policy';
export default defineConfig({
servers: [ /* your upstream MCP servers */ ],
gateway: {
transport: 'http',
authToken: process.env.CORDON_GATEWAY_TOKEN!,
port: 7777,
host: '127.0.0.1', // localhost-only by default; set to '0.0.0.0' to expose externally
},
});
クライアントは Authorization: Bearer <your-token> ヘッダーを付けて、http://your-host:7777/mcp に接続します。このトランスポートは MCP Streamable HTTP spec を実装しており、1 つのエンドポイントで SSE レスポンスストリームと直接の JSON レスポンスの両方を提供します。セッションの多重化は、ヘッダー内のセッション ID によって処理されます。
ポリシーの適用、監査ログの記録、承認ワークフローは、どのトランスポートでも同じように機能し、変更されるのはワイヤープロトコルだけです。
n8n からの接続。 MCP Client Tool ノードに Cordon の URL を指定し、Bearer トークンを認証情報として設定します。非推奨の SSE 専用エンドポイント形式(従来の MCP SSE 仕様を使用する古い n8n バージョン向け)は実装されていません。Cordon が提供するのは現在の Streamable HTTP トランスポートのみで、n8n もこれに移行中です。
シングルテナント。 現在の HTTP トランスポートはシングルテナントです。すべてのセッションで、同じ上流 MCP サーバー、ポリシー設定、認証トークンを共有します。マルチテナントのホスト型ゲートウェイ(ヘッダーから呼び出しごとに agentId を取得し、テナントごとにポリシーを設定する機能)はロードマップに含まれています。
設定
ポリシーアクション
| ポリシー | 動作 |
|---|---|
allow | すぐに通過させます |
block | 拒否します — エージェントにエラーが返されます |
approve | 一時停止し、ターミナルで人間の承認を待ちます |
approve-writes | 読み取りは通過させ、書き込みには承認を要求します |
read-only | すべての書き込み操作をブロックします |
log-only | 通過させますが、監査ログにフラグを付けます |
hidden | tools/list から除外します — モデルには表示されません |
sql-read-only | SQL 引数を解析し、SELECT/WITH-SELECT を許可して、それ以外はすべてブロックします(解析できない場合はフェイルクローズします) |
sql-approve-writes | SQL 引数を解析し、読み取りを許可して、書き込みは一時停止して人間の承認を待ち、解析できない場合はブロックします |
ポリシーはサーバーレベル(すべてのツールに適用されるデフォルト)またはツールごとに設定できます(サーバーのデフォルトを上書きします)。
{
name: 'my-server',
policy: 'approve-writes', // server default
tools: {
safe_read: 'allow', // override: always allow
nuke_db: 'block', // override: always block
},
}
承認チャネル
| チャネル | ステータス |
|---|---|
terminal | 利用可能 — ターミナルで対話型プロンプトを表示します |
slack | 利用可能 — ワンクリックの Slack に追加(OAuth)、サーバーから投稿する Block Kit カード、HMAC によるインタラクションの検証、承認者の記録への保存に対応します |
web | v0.3 で提供予定 |
webhook | v0.3 で提供予定 |
監査出力
| 出力 | ステータス |
|---|---|
stdout | 利用可能 |
file | 利用可能 — JSON Lines をローカルファイルに書き込みます |
hosted | 利用可能 — イベントを Cordon ダッシュボードに送信します |
otlp | v0.3 で提供予定 |
パッケージ
| パッケージ | 説明 |
|---|---|
@getcordon/cli | CLI — npx @getcordon/cli start |
@getcordon/policy | TypeScript 設定 SDK — defineConfig() とすべての型 |
@getcordon/core | コアプロキシエンジン — ポリシー評価、監査ログ記録、承認管理 |
ロードマップ
- アグリゲーターモデルの MCP プロキシ(複数のサーバー、1 つのゲートウェイ)
- ポリシーエンジン — 許可、ブロック、承認、書き込みを承認、読み取り専用、ログのみ、非表示
- 閉世界型ツールカタログ —
knownTools+onUnknownToolによる、将来にわたって有効な上流サーフェス制御 - SQL 対応ポリシー —
sql-read-only/sql-approve-writesが呼び出し時に SQL 引数を解析(PostgreSQL 方言) - TTY セーフなプロンプトを備えたターミナル承認チャネル
- Slack 承認チャネル — Block Kit メッセージを送信し、応答をポーリング
- stdout、ファイル、またはホスト型ダッシュボードへの構造化 JSON 監査ログ記録
-
cordon init— Claude Desktop の設定を自動で読み取り、パッチを適用 - レート制限 — スライディングウィンドウ、グローバル/サーバーごと/ツールごと
- ホスト型ダッシュボード — 監査ログ履歴、CSV/JSON エクスポート、GitHub OAuth、個人向け無料
- エージェントごとのポリシーと呼び出しグラフ制約 — 重大度を加算するシーケンス対応ブロック
- HTTP/Streamable HTTP トランスポート — n8n および HTTP 対応 MCP クライアント向けのシングルテナントゲートウェイ
- ドリフト検出 — ダッシュボードで「今週、エージェントの動作にどのような変化があったか」を表示
- ポリシーの提案 — 監査履歴を分析し、呼び出しグラフのルールとゲートを提案
- 永続的な承認 — タイムアウトした承認を保持して表示し、
cordon replayで再生可能 - マルチテナント HTTP ゲートウェイ — ヘッダーから呼び出しごとの
agentIdを取得し、1 つの Cordon インスタンスで多数のエージェントを利用 - OpenTelemetry エクスポート
- チームアカウントと一元化されたガバナンス
例
本番データベースのテーブルを削除しようとするエージェントを Cordon がインターセプトする実際に動作するデモについては、examples/security-showcase をご覧ください。
cd examples/security-showcase
npm install
npm run demo
ユースケース
エンタープライズ — すべての AI エージェント導入環境にわたる一元化されたガバナンス。ポリシー・アズ・コード、構造化ログ、SOC2 対応の監査証跡を実現する明確な道筋を提供します。
スタートアップチーム — 安心してエージェントを導入できます。すべてのツール呼び出しが記録され、書き込みには承認が必要で、コンプライアンスチームが確認できる証跡が残ります。
個人開発者 — ローカルの Claude/Cursor 環境を保護します。エージェントが何を呼び出しているかを正確に確認し、危険な操作が本番環境に届く前にブロックできます。
優れた連携先
-
Agent Toolbelt — すぐに使える MCP ツール(ウェブ検索、取得、ファイルシステムなど)をまとめた型付きツールキットです。Claude Desktop に接続し、ポリシー適用と監査ログ記録のために、ツール呼び出しを Cordon 経由でルーティングします。Agent Toolbelt がエージェントに力を与え、Cordon が利用前の確認を徹底します。
-
Build & Ship MCP Tools — MCP サーバーを最初から最後まで構築する方法を解説する関連コースです。7 モジュール、33 レッスンで構成され、モジュール 0 は無料、モジュール 6 では Cordon を使ったサーバーの保護を扱います。
コントリビューション
Cordon はオープンソースであり、コントリビューションを歓迎します。
git clone https://github.com/marras0914/cordon.git
cd cordon
npm install
npm run build
npm run dev
ライセンス
MIT — 詳細は LICENSE をご覧ください。
信頼するのをやめ、統制を始めましょう。
⭐ GitHub でスターを付ける
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。