mcp-bastion について
mcp-bastionは、MCPクライアントと上流サーバーの間に置くプロキシです。接続復旧、ツールのセキュリティ制御、監査を必要とする環境向けに、複数サーバーを集約し、標準MCP呼び出しで状態確認や再接続を提供します。
主な機能
- 01ヘルスチェックと自動再接続
- 02ツールの集約と名前空間化
- 03ツール定義とセキュリティリスクの確認
- 04呼び出し元とツール単位の認可
- 05ハッシュチェーン付き監査記録の作成
活用シーン
- 01長時間セッションでの切断の影響軽減
- 02ツール定義の変更有無の確認
- 03呼び出し元ごとのツールアクセス制限
- 04MCP活動の監査証跡の保存
MCP 対応
クライアントにはMCPサーバーとして、上流サーバーにはMCPクライアントとして動作します。上流ツールを集約し、状態確認、再接続、セキュリティ、コンプライアンスの制御ツールをクライアントに提供します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
🛡️ mcp-bastion
Model Context Protocol(MCP)向けの信頼性・セキュリティプロキシです。
MCP サーバー向けの自己修復接続、実行時のツールセキュリティ、コンプライアンスに対応した監査証跡を提供します。
mcp-bastion は、MCP クライアント(Claude Code、Cursor、Cline、Windsurf、Zed、Claude
Desktop、または MCP 準拠のエージェント)と MCP サーバーの間に位置します。クライアントに依存せず、クライアント固有のコードを一切使わず、設定だけであらゆる準拠クライアントに対応します。また、既存環境に変更を加えません。サーバーは変更なしで動作し、Bastion を削除する場合も設定を1行戻すだけです。
📦 パッケージ: mcp-bastion(npm) · 🗂️ 公式 MCP Registry: io.github.Gowthaman90/mcp-bastion
🔒 測定済みのセキュリティ: オープンかつベンダー中立の mcp-defense-bench v0.9.0 において、Bastion は開発用フィクスチャで MCP の攻撃対象領域の66%(37ベクトル中24.6、うち23ベクトルを適用)、事前登録されたホールドアウトセットで 53% をカバーし、一致する対照群で誤検知はゼロです。測定対象となったプロキシの中で、最も幅広くカバーしています。
👤 作成・保守担当:Gowthaman Arumugam — 独立研究者。関連ベンチマーク:mcp-defense-bench。
目次
- 概要
- 仕組み
- セキュリティモデル
- 機能
- クイックスタート
- デモ
- 制御ツール
- 設定
- トランスポート
- ユーザーごとのアイデンティティ(ゲートウェイモード)
- 委任チェック
- 実行時の認可
- 実行時のセキュリティ
- 監査とコンプライアンス
- クライアントのセットアップ
- アーキテクチャ
- 開発
- ロードマップ
- コントリビューション
- セキュリティ
- ライセンス
理由
セッションの途中で MCP サーバーが切断されると、エージェントには一般的な 「利用可能なツールがありません」 というエラーしか表示されません。これは 最初から存在しなかったツールと区別がつかず、再接続もできません。再接続できるのは人間だけです。長時間のエージェントセッションでは、機能が気付かれないまま失われ、原因のわかりにくい形で失敗します。
Bastion はこの問題を解消します。すべてのサーバーのヘルスチェックを行い、バックオフを伴って自動再接続します。そして重要なのは、制御ツールを公開することで、エージェント自身が接続の健全性を調べ、人間の介入なしに切断されたサーバーを復旧できる点です。
Bastion は現在、3 つの層に対応しています。信頼性(v0.1)、ランタイムセキュリティ(v0.2 — ツールのピン留め/ラグプルとポイズニングの検出)、監査とコンプライアンス(v0.3 — NIST AI RMF/OWASP LLM Top 10 に対応付けられた、差し替え可能なシンク)です。ロードマップを参照してください。
仕組み
現在、クライアントは各サーバーに直接接続します。Bastion を使うと、クライアントは Bastionに接続し、Bastion がクライアントに代わって同じサーバーに接続します。つまり、Bastion はツール呼び出しの経路に入り、信頼性(そして将来的にはセキュリティ)を透過的に追加できます。
Before: Client ─▶ server A / server B / server C
After: Client ─▶ mcp-bastion ─▶ server A
─▶ server B
─▶ server C
Bastion はクライアントに対して標準的な MCP サーバーとして、各アップストリームに対して標準的な MCP クライアントとして動作します。プロトコルに忠実に準拠しているため、適合するすべてのクライアントで自動的に動作します。クライアントごとに異なるのは、設定を数行追加する場所だけです。
セキュリティモデル
Bastion のセキュリティは、互いに独立した 3 つの仕組みを基盤としています。ヒューリスティックは 3 つすべてに情報を提供しますが、その代わりにはなりません。ヒューリスティックによる検出結果はリスクの兆候であり、ツールが安全であることの証明ではありません。
| 仕組み | 得られること | チェック項目 |
|---|---|---|
| 定義の完全性 | 承認したツール、サーバー、設定が実際の呼び出しに使われていること | ツールのピン留め(ラグプル)、サーバーの識別情報、設定のドリフト、引数スキーマ |
| ランタイム認可 | 各呼び出し元が、ポリシーで許可されたツールと引数値にのみアクセスでき、判定はアップストリームへの接続前に行われること | authorization ルール、委任チェック(誰が誰に代わって行動するか)、MRTR 継続の管理 |
| 信頼できる監査証拠 | 秘密情報を漏らさずにすべての判定を記録し、変更または短縮されたログを検出できること | 監査イベント、ハッシュチェーン、署名付きチェックポイント、シンクの健全性、秘匿化 |
すべての検出結果には kind が付与されます。決定論的(ピン、スキーマ、ポリシー、またはトークンのクレームとの厳密な比較)か、ヒューリスティック(無害なテキストにも誤検出する可能性があり、新しいペイロードによって回避される可能性があるパターンマッチング)のいずれかです。各適用プロファイルでの扱いは次のとおりです。
| チェック項目 | 種別 | observe | balanced(デフォルト) | strict |
|---|---|---|---|---|
| ツールの固定(rug pull)、サーバーの識別情報 | 決定論的 | warn | block | block |
| 実行時の認可 | 決定論的 | warn | block | block |
| 委任トークンのチェック | 決定論的 | warn | block | block |
| 委任チェーンの深さ/循環 | 決定論的 | warn | warn | block |
| サーバー間のデータフロー | 決定論的 | warn | block | block |
| 引数の検査:スキーマ、およびコマンドインジェクションと指示の注入パターン | 混合 | warn | block | block |
MRTR(input_required)ゲート | 混合 | warn | block | block |
| 説明文のポイズニング | ヒューリスティック | warn | warn | block |
| 応答のヒューリスティクス(インジェクション、誘導) | ヒューリスティック | warn | warn | block |
引数の検査にはヒューリスティックな要素も含まれますが、balanced ではブロックします。誤検知の場合、エージェントに再試行が必要になる一方、検知漏れはコマンドの実行につながるためです。結果のインラインシークレットのマスキング(redactResponseSecrets)は、すべてのプロファイルで有効です。observe では何もブロックされず、各監査イベントに wouldBlock(balanced での動作)が記録されます。
既知の制限。 ポイズニングと応答のヒューリスティクスは、未確認のペイロードによって回避される可能性があります。マスキングで対応できるのは既知の形式のシークレットであり、すべてのシークレットではありません。Bastion は上流のサーバー自体をサンドボックス化しません。認可は与えられた ID を信頼します。ベアラークライアントは Bastion 自身が認証し、委任クレームの検証は署名モードの場合に限られます(trustStructuralClaims を参照)。
特長
- 🔌 クライアントに依存しません — 1つのバイナリと設定だけで連携でき、クライアントごとのプラグインは不要です。
- ♻️ 自己修復 — stdio サーバーのヘルスチェックと、上限付き指数バックオフによる自動再接続を備えています。
- 🧭 エージェントによる復旧が可能 —
bastion__statusとbastion__reconnectを使って、エージェント自身が接続切れを検出して修復できるため、原因の分からない「そのようなツールはありません」という状態に陥りません。 - 🧩 透過的な集約 — 複数のサーバーを1つにまとめ、サーバーごとにツール名を名前空間で分けて、名前の衝突やツールのシャドーイングを防ぎます。
- 💬 分かりやすいエラー — サーバーが切断されてもクラッシュせず、対処可能なメッセージを返します。
- 🛡️ 実行時セキュリティ (v0.2 で追加) — 各ツールの定義を固定して「ラグプル」(承認後にサーバーがツールを変更すること)をブロックし、ヒューリスティックに基づいて説明文のポイズニングを検査し、サーバー間のシャドーイングを検出します。実行時セキュリティをご覧ください。
- 🔐 実行時認可 (v1.4 で追加、オプトイン) — 上流サーバーへ接続する前に、呼び出し元ごと、ツールごとにポリシーを決定します。どのクライアント、ユーザー、エージェントが、どの引数値でどのツールを呼び出せるかを指定でき、拒否優先、デフォルト拒否、ポリシーを事前確認できる監視モードにも対応します。実行時認可をご覧ください。
- 📝 監査とコンプライアンス (オプトイン) — 構造化されたハッシュチェーン監査イベントを、プラグイン可能なシンク(コンソール/ファイル/Webhook/OTLP)に送信し、NIST AI RMF と OWASP LLM Top 10 に対応付けます。v1.4 以降は HTTPS 専用のリモートシンク、再試行付き配信、シンクごとの編集処理、およびログの短縮を検出できる Ed25519 署名付きチェックポイントに対応しています。監査とコンプライアンスをご覧ください。
- 🪶 非侵襲的で元に戻せます — サーバーは変更せずに動作し、アンインストールは設定を元に戻すだけです。
- 🧱 エンタープライズ品質のコードベース — 厳格な TypeScript、レイヤー化されたアーキテクチャ、ESLint + Prettier、ユニットテストおよびエンドツーエンドテストを備えています。
クイックスタート
Bastion は mcp-bastion として npm で公開されています。以下の npx コマンドが自動的に取得するため、事前のインストールは不要です。
1. クライアントに Bastion を追加し、設定ファイルを指定します。
// your client's mcpServers config
{
"mcpServers": {
"bastion": {
"command": "npx",
"args": ["-y", "mcp-bastion", "--config", "bastion.config.json"],
},
},
}
2. bastion.config.json に実際のサーバーを記述します(クライアントからそのまま移します)。
{
"servers": {
"github": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-github"] },
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/dir"],
},
},
"reconnect": { "auto": true },
"healthCheck": { "enabled": true },
}
3. クライアントを再起動します。 ツールは名前空間付き(例:github__create_issue)で、Bastion の制御ツールとともに表示されます。すべてのオプションについては、bastion.config.example.jsonをご覧ください。
🔒 セキュリティはデフォルトで有効です。 初期設定では、Bastion は
balanced適用プロファイルで動作します。 信頼度の高い攻撃(ラグプル、引数/コマンドインジェクション、サーバー間の情報流出)をブロックし、ヒューリスティックに基づく攻撃(説明文/応答のポイズニング)には警告を表示するとともに、ツールの結果から漏えいしたシークレットを編集します。security.enforcementProfileをobserve(警告のみ)またはstrict(すべてブロック)に設定するか、個々の制御を調整してください。詳しくは実行時セキュリティをご覧ください。
デモ
セッション中にサーバーがクラッシュし、自動復旧する様子をご覧ください。
npm run demo
コマンドによってクラッシュするサーバーの前段で Bastion を起動し、エージェントが不可解なエラーではなく、対処可能な「再接続」メッセージを受け取る様子と、人手を介さずに接続が自動復旧する様子を確認できます。GIF として記録するには、asciinema rec demo.cast -c "npm run demo" && agg demo.cast assets/demo.gif を実行します。
制御ツール
Bastion は、標準の MCP 呼び出しのみを使用して、エージェントが接続を管理し、セキュリティを自ら確認できるよう、制御ツールを注入します。
| ツール | 目的 |
|---|---|
bastion__status | プロキシ経由のすべてのサーバーの状態:接続済み/切断/再接続中/失敗、ツール数、最後のエラー。 |
bastion__reconnect | 人の介入なしで、指定したサーバーを再接続します(引数:{ "server": "<name>" })。 |
bastion__security | ツールごとのセキュリティレポート:ピン留めの状態(承認済みか変更済みか)、ポイズニングの検出結果、シャドーイング。 |
bastion__compliance | 最近のアクティビティを NIST AI RMF/OWASP LLM Top 10 に対応付けた監査概要(audit.enabled が必要です)。 |
再承認できるのはオペレーターのみです。 ラグプルブロックの解除はセキュリティ権限に関わるため、エージェントが呼び出せるツールではありません。プロンプトインジェクションを受けたエージェントが、ブロックされたツールを再承認できてはなりません。変更されたツールは、オペレーターが帯域外で解除するまでブロックされたままです。
bastion__approveは公開されず、クライアントからの呼び出しも拒否されます。
設定
| キー | 型 | デフォルト | 説明 |
|---|---|---|---|
servers | map | — | プロキシする上流サーバー(必須、少なくとも1つ)。 |
servers.<name>.command | string | — | 起動する実行ファイル(例:npx、node)。 |
servers.<name>.args | string[] | [] | command に渡す引数。 |
servers.<name>.env | map | — | プロセス環境変数にマージする環境変数の上書き。 |
servers.<name>.cwd | string | — | 起動したプロセスの作業ディレクトリ。 |
reconnect.auto | boolean | true | 予期しない切断後に自動再接続します。 |
reconnect.maxRetries | number | 10 | 断念するまでの最大試行回数(-1 = 無制限)。 |
reconnect.initialBackoffMs | number | 500 | 初回のバックオフ時間。試行ごとに倍増します。 |
reconnect.maxBackoffMs | number | 30000 | バックオフの上限。 |
healthCheck.enabled | boolean | true | 定期的な稼働確認を有効にします。 |
healthCheck.intervalMs | number | 30000 | 確認間隔。 |
healthCheck.timeoutMs | number | 5000 | 1回の確認に対するタイムアウト。 |
namespace.strategy | prefix | passthrough | prefix | 上流のツール名を公開する方法。 |
namespace.separator | string | __ | prefix 戦略で使用する区切り文字。 |
security.pinTools | boolean | true | ツール定義を固定し、後の変更を検出します。 |
security.onRugPull | block | warn | block | 固定されたツールの定義が変更された場合のアクション。 |
security.inspectDescriptions | boolean | true | ツールの説明に対してポイズニングのヒューリスティック検査を実行します。 |
security.onPoisoning | block | warn | warn | 重大度の高いポイズニング検出時のアクション。 |
audit.enabled | boolean | false | すべてのツール呼び出しについて監査イベントを記録します。 |
audit.includeArgs | none|redacted|full | none | ツールの引数をどのように記録するか。 |
audit.tamperEvident | boolean | false | イベントをハッシュチェーン化し、改ざんを検出可能にします。 |
audit.sinks | array | console | 出力先:console、file、webhook、otlp。 |
servers.<name>.transport | stdio | http | stdio | ローカルのサブプロセスまたはリモートエンドポイント。 |
servers.<name>.url | string | — | リモート MCP URL(http の場合は必須)。 |
servers.<name>.headers | map | — | http の上流に送るヘッダー(例:Authorization)。 |
servers.<name>.forwardHeaders | map | — | http のみ。上流ヘッダー ← 受信ヘッダー。リクエストごとにコピーされます(ゲートウェイモード)。listen.mode: "http" が必要です。 |
servers.<name>.onMissingForwardedHeader | error | omit | error | リクエストに転送対象のヘッダーがない場合:上流を呼び出さずにツールエラーを返すか、ヘッダーなしで呼び出します。 |
servers.<name>.connect | startup | onDemand | startup | onDemand:この上流を必要とする最初のリクエスト時に、そのリクエストの転送ヘッダーを使って接続します。 |
servers.<name>.authHeaders | string[] | — | bastion__status で認証として扱う追加のヘッダー名(forwardHeaders のキーは常に対象です)。 |
servers.<name>.delegation | object | — | http のみ。forwardHeaders が必要です。転送ヘッダー内の委任 JWT をキーなしで検査します(以下)。 |
servers.<name>.delegation.verify | structural | signature | structural | signature は公開鍵(jwksUrl または jwks)と issuer、algorithms 許可リストを使って JWT も検証します。 |
delegation.gatewayAudiences | string[] | [] | Bastion 自体を識別する Audience。一致するトークン(または aud のないトークン)はパススルーされます。 |
delegation.oneUserPerRequest | boolean | true | 1つのリクエスト内のすべての委任トークンで、同じユーザー(iss + sub)を指定する必要があります。 |
delegation.recordSubject | hash | plain | hash | 監査対象:iss|sub の HMAC 仮名、またはそのままの sub。 |
delegation.subjectKey | string (≥16) | 下記参照 | 仮名化キー。MCP_BASTION_SUBJECT_KEY、次に監査整合性キー、次にプロセスごとのランダム値が使われます。 |
security.onDelegation | block | warn | block | チェーンルール以外の委任検出時のアクション。 |
security.onDelegationChain | block | warn | warn | delegation-chain-depth / -chain-cycle に対するアクション(strict では block)。 |
listen.mode | stdio | http | stdio | stdio または Streamable HTTP 経由で Bastion を提供します。 |
listen.host / listen.port | string / number | 127.0.0.1 / 3000 | http モードのバインドアドレス。 |
listen.validateRoutingHeaders | boolean | true | 本文と一致しない Mcp-* ルーティングヘッダーを拒否します(-32020、MCP 2026-07-28)。 |
security.maxCacheTtlMs | number (ms) | 3600000 | 下流に転送する上流の ttlMs キャッシュヒントの上限(MCP 2026-07-28)。 |
servers.<name>.protocol | auto|legacy|2026-07-28 | auto | 上流ごとの世代ネゴシエーション(2026-07-28 をプローブしてフォールバック、または固定)。 |
listen.legacy | stateless | reject | stateless | 2026-07-28 より前のクライアントをステートレスで処理するか、拒否します(-32022)。 |
security.inspectInputRequests | boolean | true | input_required のラウンドを検査します(認証情報のフィッシング、モデル誘導)。 |
security.onInputRequired | block | warn | block | 重大度の高い MRTR 検出時のアクション(warn はリクエストを取り除きます)。 |
security.requestStateKey | string (≥16) | プロセスごとのランダム値 | requestState エンベロープを封印する HMAC キー。または MCP_BASTION_REQUEST_STATE_KEY。 |
security.requestStateTtlSeconds | number | 300 | 封印された requestState エンベロープの有効期間。 |
security.enforcementProfile | observe | balanced | strict | balanced | すべての on* アクションを一括設定します。セキュリティモデルを参照してください。明示的な on* 設定が優先されます。 |
security.onAuthorization | block | warn | block | authorization が呼び出しを拒否した場合のアクション(observe では warn)。 |
security.redactResponseSecrets | boolean | true | エージェントに表示する前に、ツール結果からシークレット値を秘匿化します。 |
authorization.enabled | boolean | false | 実行時認可を有効にします。実行時認可を参照してください。 |
authorization.default | deny | allow | deny | どのルールでも許可されていない ID に対する判断。 |
authorization.rules | array | [] | { id, effect, principal, tools, args? } ルール。拒否は許可より優先されます。 |
authorization.trustStructuralClaims | boolean | false | 構造モードの委任トークンからの user / agent を受け入れます。 |
listen.authToken | string | — | クライアント default 用の Bearer トークン。listen.clients が設定されていない場合、ループバック以外へのバインドには必須です。 |
listen.clients | map | — | 名前付きクライアント:{ "<name>": { "tokenEnv": "VAR" } }。各クライアントに Bearer トークンを1つ設定します。 |
audit.integrityKey | string | — | チェーン用の HMAC キー。または MCP_BASTION_AUDIT_KEY。 |
audit.onSinkFailure | continue | block | continue | どの出力先にも配信できない間、block は呼び出しを拒否します。 |
audit.sinks[].includeArgs | none|redacted|full | audit.includeArgs | 出力先ごとの引数記録設定。 |
audit.sinks[].headersEnv | map | — | webhook / otlp:ヘッダー名 → 環境変数。 |
audit.sinks[].allowInsecureTransport | boolean | false | webhook / otlp:ループバック以外のホストへの平文 HTTP を許可します。 |
audit.sinks[].maxQueue | number | 10000 | webhook / otlp:受信側が停止している間に保持するイベント数。 |
audit.checkpoint | object | — | 署名付きチェックポイント:privateKeyFile、everyEvents(100)、everySeconds(60)、stateFile、sinks。 |
トランスポート
Bastion は MCP TypeScript SDK 2.0 で動作し、上流サーバー側とクライアント側の両方で、2つのプロトコル世代に対応しています。ステートレスな 2026-07-28 リビジョンと、2026 年以前の initialize ハンドシェイクの両方です。プロトコルがステートレスの場合、セキュリティ状態を保持できるコンポーネントはゲートウェイだけです。そのため、v1.0 では requestState の管理と input_required による同意ゲートが追加されています(CHANGELOG.md を参照)。
Bastion は、両方の接続側で2つのトランスポートに対応しています。
- stdio(デフォルト) — クライアントが Bastion を起動し、Bastion がローカルサーバーを起動します。
- Streamable HTTP — リモート MCP サーバーへの接続(
transport: "http"、url、および任意の認証用headersを指定したservers.<name>)と、HTTP 経由で複数のクライアントやリモートクライアントに Bastion を提供する設定(listen.mode: "http"または--http <port>)が可能です。
認証ヘッダーなしで設定された HTTP 上流サーバーは、bastion__status で authenticated: false として示され、接続時に警告が表示されます。カスタム認証情報ヘッダーは、authHeaders で名前を指定すると認証済みとして扱われます。転送されるヘッダーは常に認証済みとして扱われます。
ユーザーごとのアイデンティティ(ゲートウェイモード)
Bastion が、サインイン済みユーザーとして動作する必要のあるエージェントとサブエージェントの間に位置する場合、上流への各呼び出しには固定トークンではなく、そのユーザーのアイデンティティを含める必要があります。forwardHeaders を使うと、これを実現できます。
{
"servers": {
"pfqa": {
"transport": "http",
"url": "http://localhost:8011/mcp",
"protocol": "legacy",
"connect": "onDemand",
"forwardHeaders": { "x-cso-identity": "x-cso-delegate-pfqa" },
},
},
"listen": { "mode": "http" },
}
このマップは 上流のヘッダー ← 受信したヘッダー を表します。下流の HTTP リクエストを処理する際に行われるすべての上流リクエスト(initialize、tools/list、tools/call、ping)について、Bastion は受信した x-cso-delegate-pfqa ヘッダーの値を x-cso-identity として上流リクエストにコピーします。
このモードでは、Bastion は認証情報を保持しません。各リクエストに含まれる情報をそのまま渡すだけです。
- リクエストに紐付けられます。 受信したヘッダーは、1 つの下流リクエストの処理期間に限り、
AsyncLocalStorageに保持されます。上流トランスポートのカスタムfetchが送信時にヘッダーを読み取ります。異なるユーザーからの同時リクエストは 1 つの上流接続を共有しますが、互いのヘッダーを見ることはありません。 - 指定したヘッダーのみ転送されます。 それ以外の受信ヘッダーは転送されません。ホップバイホップのヘッダーやトランスポートが管理するヘッダー(
connection、mcp-session-id、content-typeなど)は、設定の読み込み時に転送先として拒否されます。listen.authTokenが設定されている場合、受信したauthorizationヘッダー(Bastion 自身のベアラートークン)は転送できません。 - 転送されたヘッダーは、同じ名前の静的な
headersエントリより優先されます。 - ヘッダーがない場合。 デフォルト(
onMissingForwardedHeader: "error")では、上流は呼び出されません。呼び出し元には、次のようなツールエラーが返されます。pfqa: the request carried no x-cso-delegate-pfqa header, so the call was not forwarded.上流を呼び出して、処理を任せるには"omit"を使用します。 - オンデマンド接続。
connect: "onDemand"の場合、起動時には何も送信されません。上流を必要とする最初のリクエスト(tools/list、またはpfqa__…の直接のtools/call)で、そのリクエストのヘッダーを使って接続します。その後、通常どおりツール一覧がキャッシュされます。ヘルスチェックはオンデマンドの上流をスキップし、初回使用まではidleと表示されます。接続に失敗するとidleに戻り、再接続タイマーは設定されません。forwardHeadersとconnect: "startup"を組み合わせると、起動時に静的なheadersのみで接続するため、上流がinitializeの認証も行う場合はonDemandを使用してください。 - 401 は認証エラーです。 ツールの結果と
bastion__status(lastError)に認証エラーとして報告され、クラッシュや不明なツールとして扱われることはありません。1 人のユーザーの 401 によって、ほかのユーザーが共有する接続が切断されることはありません。 - 値は記録されません。 ログ、監査シンク、
bastion__statusに転送された値が含まれることはありません。監査イベントには、転送されたヘッダー名のみが記録されます("forwardedHeaders": ["x-cso-identity"])。 - ピン留めは共有されます。 ツール定義は最初に確認された時点でピン留めされ、どのユーザーのリクエストで変更が確認されたかにかかわらず、変更はブロックされます。リクエストごとに異なるのはアイデンティティだけです。
forwardHeaders、onMissingForwardedHeader、connect、authHeaders が有効なのは、transport: "http" の上流のみです。forwardHeaders には listen.mode: "http" も必要です。それ以外の組み合わせは、設定の読み込み時に拒否されます。1 つの Bastion の背後に 3 つのサブエージェントを配置する例については、examples/identity-forwarding.config.json を参照してください。
委任チェック
v1.2.0 以降。 ゲートウェイモードでは、呼び出し元(たとえば、サインイン済みユーザーのために動作するマスターエージェント)が、サブエージェントごとに有効期間の短い委任 JWT を 1 つずつ、それぞれ独自のヘッダーに入れて送信します。各サブエージェントから見えるのは、自身のトークンだけです。Bastion はリクエスト全体を参照できるため、シークレットやキーを保持することなく、サブエージェントにはできないチェックを実行できます。
"servers": {
"pfqa": {
"transport": "http", "url": "http://localhost:8011/mcp", "protocol": "legacy", "connect": "onDemand",
"forwardHeaders": { "x-cso-identity": "x-cso-delegate-pfqa" },
"delegation": {
"audience": "pfqa", // required: what this upstream's tokens must carry in `aud`
"header": "x-cso-identity", // forwardHeaders key carrying the JWT (default: the only one)
"verify": "structural", // or "signature" (below)
"maxLifetimeSeconds": 120, // default 3600
"clockSkewSeconds": 30, // default 30
"allowedActors": ["master-quote-agent"],
"requireActor": false,
"maxChainDepth": 2
}
}
},
"delegation": { "gatewayAudiences": ["mcp-bastion"], "oneUserPerRequest": true, "recordSubject": "hash" }
| ルール | 発生条件 | デフォルト(balanced) |
|---|---|---|
delegation-malformed | 厳密な JWS コンパクトトークンではない(下記参照)、またはクレームの型が誤っている | block |
delegation-audience-mismatch | aud の値に、この上流の audience と一致するものがない(兄弟のトークン) | block |
delegation-passthrough | aud が存在しない、または aud の値が gatewayAudiences に含まれている | block |
delegation-subject-mixing | リクエストの委任トークンが、複数の(iss、sub)を示している | block |
delegation-expired / -not-yet-valid | now > exp + skew / nbf > now + skew | block |
delegation-lifetime-excess | exp − iat > maxLifetimeSeconds、または exp が存在しない | block |
delegation-actor-not-allowed / -actor-required | 現在のアクター(act.sub、それ以外は act.client_id)が allowedActors に含まれない / act がない | block |
delegation-chain-depth / -chain-cycle | act チェーンが maxChainDepth より長い / 同じアクターを2回示している | warn |
delegation-alg-disallowed | 署名モード:alg が algorithms に含まれていない(大文字と小文字を区別します。none と HMAC は対象外です) | block |
delegation-key-unknown | 署名モード:kid に一致する信頼済みキーがない、またはキーセットを取得できなかった | block |
delegation-signature-invalid | 署名モード:信頼済みキーで署名を検証できない | block |
delegation-issuer-mismatch | 署名モード:iss が設定済みの issuer と一致しない | block |
チェーンの深さと循環は過去のアクターに関するもので、RFC 8693 §4.1 では情報提供のみとされているため、
重大度は中程度であり、security.onDelegationChain(または strict プロファイル)で
block が指定されていない限り、警告のみとなります。それ以外はすべて security.onDelegation(observe では warn)に従います。
- 厳密なデコード。 base64url セグメントは正確に 3 つで、パディングなし、正規のエンコード形式である必要があります。JSON オブジェクトのメンバー名は(エスケープ解除後に)一意で、
algは文字列でなければなりません。任意でBearerプレフィックスを指定できます。それ以外の場合はすべてdelegation-malformedとして安全側に拒否されます。 - リクエストごとに判定は 1 回。 Bastion は最初に必要になった時点で、リクエストに含まれる委任設定済みのすべてのトークンをデコードし、アップストリームごとのチェックとトークン間のサブジェクトチェックを実行して、リクエストの残りの期間にわたって判定をキャッシュします。チェッカーは
checkDelegation(policy, carriedHeaders, now)(構造チェック、同期)とcheckDelegationAsync(policy, carriedHeaders, now)(署名検証を追加)としてエクスポートされています。 - アップストリームに接続する前に処理。 ブロックされた
tools/callは、Bastion が接続する前(オンデマンド接続も含む)に拒否されます。ツールエラーにはルール名を記載し、トークン値やクレーム値は含めません。また、blocked_delegationの判定を示す監査イベントが記録されます。tools/listでは、リクエストがブロックされるアップストリームを除外します。さらに保護策として、アップストリームのトランスポートは、判定でブロックされたトークンの送信を拒否します(リクエスト内の再接続やその他の送信も対象です)。 - 誰が誰のために操作したか。 委任設定済みのアップストリームへの呼び出しには、監査用の
delegationレコードが付加されます。内容はsubject、issuer、audience、tokenId(jti)、expiresAt、actors(現在のアクターが先頭)、chainDepth、verified(構造チェックのみの場合はstructural、署名を検証した場合はsignature、検証失敗時はfailed)、および検出事項です。トークンそのものは記録しません。hashモードでは、サブジェクトは"hmac:"+ HMAC-SHA256(key,iss|sub) の先頭 16 桁の 16 進文字列になります。キーを持つオペレーターはこれを再計算し、同一ユーザーのレコードを特定できます。キーはdelegation.subjectKey、次にMCP_BASTION_SUBJECT_KEY、次に監査整合性キーの順で使用されます。いずれもない場合はプロセスごとにランダムなキーが使われ、その疑似識別子は再起動をまたいで関連付けられません。 - ステータス。
bastion__statusは、アップストリームごとにdelegation: { mode, audience, lastViolation }を表示します。最後の違反にはルール ID と時刻のみが含まれます。 - 設定チェック。
delegationにはforwardHeadersが必要です。headerはそのキーのいずれかでなければなりません。2 つのアップストリームでaudienceを共有することはできず、アップストリームのaudienceをゲートウェイのaudienceにすることもできません。不明なキーは拒否されます。署名モードではissuer、空でないalgorithmsリスト、およびキーソースが正確に 1 つ必要です。
署名モード
発行者が非対称鍵(ES256、EdDSA、RS256、PS256、…)で委任トークンに署名する場合、Bastion は発行者の公開鍵を使って検証できます。
"delegation": {
"audience": "pfqa",
"verify": "signature",
"issuer": "https://spire.example/identity", // exact match on `iss`
"algorithms": ["ES256", "EdDSA"], // allow-list; HS256/384/512 and none are rejected
"jwksUrl": "https://spire.example/.well-known/jwks.json" // or "jwks": { "keys": [ … public JWKs … ] }
}
- 鍵の取得元は、設定されたソースのみです。
jku、x5u、x5c、埋め込みのjwkヘッダーは参照されません。秘密鍵またはシークレットを含むメンバー(d、p、q、dp、dq、qi、oth、k)を含むインラインのjwksは、設定の読み込み時に拒否されます。jwksUrlは、ループバックホストを除き、HTTPS である必要があります。 - アルゴリズムの許可リストは、鍵の検索より先に、大文字と小文字を区別して適用されます。
alg: none(大文字・小文字のいずれの場合も)と公開鍵で署名された HS256 は、フェッチせずに拒否されます。クリティカルヘッダー拡張(crit、例:エンコードされていないペイロード)も拒否されます。 - リモート鍵セットは初回使用時に取得され、キャッシュされます。不明な
kidを含むトークンによって、30 秒のクールダウン中に再取得が行われるのは最大 1 回です。取得に失敗した場合、または 5 秒のタイムアウトが発生した場合は、フェイルクローズとなります。呼び出しはdelegation-key-unknownとしてブロックされ、アップストリームのlastErrorには鍵セットを利用できない旨が記録され、以降の取得はクールダウンが終わるまで待機します。 - 検証済みトークンにも、同じ名前で構造上のルールが引き続き適用され、監査記録には
verified: "signature"と記録されます。
制約について。
- 構造モードでは何も認証されません。トークンを偽造できる者は、一貫性のあるクレームを偽造できます。このモードが防ぐのは、悪意はないものの誤った呼び出し元やプロンプトインジェクションを受けた呼び出し元による、誤ったルーティング、パススルー、ユーザーの混同、古いリレー、チェーンの悪用です。検証は引き続きアップストリームが行います。ゲートウェイで認証するには、署名モード(非対称トークン)を使用してください。
- 署名モードが保持するのは公開鍵のみなので、Bastion は鍵を持たず、トークンを検証できても発行することはできません。発行者が非対称アルゴリズムで署名する必要があります。HS256 トークンは構造上の検証のみ可能です。検証には共有シークレットが必要なためです。設定された鍵セットの内容が信頼されるため、
jwksUrl(HTTPS、発行者自身のホスト)の安全性が、そのまま検証の安全性になります。 - リクエストごとに 1 人のユーザーのみを許可するチェックの対象は、
delegationが設定されたトークンに限られます。 - トークンの有効期間中のリプレイは防止されません(
jtiキャッシュはまだなく、将来的にオプトインかつ上限付きで対応する可能性があります)。
3 つのサブエージェントについては、examples/delegation.config.json を参照してください。
ランタイム認可
v1.4 で追加、オプトイン方式です。 すべての呼び出しについて、上流サーバーに接続する前に、誰がどのツールをどの引数で呼び出せるかを判定します。authorization.enabled が有効でない限り、無効です。
"listen": {
"mode": "http",
"clients": { // one bearer token per client, read from the environment
"docs-assistant": { "tokenEnv": "BASTION_TOKEN_DOCS" },
"release-pipeline": { "tokenEnv": "BASTION_TOKEN_RELEASE" },
"ops-console": { "tokenEnv": "BASTION_TOKEN_OPS" }
}
},
"security": { "enforcementProfile": "observe" }, // preview first: log, never block
"authorization": {
"enabled": true,
"default": "deny",
"rules": [
{ "id": "docs-read", "effect": "allow", "principal": { "client": "docs-assistant" },
"tools": ["files__read_file", "files__list_dir"],
"args": { "path": { "pathWithin": "/srv/docs" } } },
{ "id": "release-staging", "effect": "allow", "principal": { "client": "release-pipeline" },
"tools": ["deploy__*"], "args": { "env": { "in": ["staging"] } } },
{ "id": "no-prod-rollback", "effect": "deny", "principal": "*",
"tools": ["deploy__rollback"], "args": { "env": { "equals": "prod" } } },
{ "id": "ops-control", "effect": "allow", "principal": { "client": "ops-console" },
"tools": ["bastion__*"] }
]
}
呼び出し元。 呼び出しには、Bastion が認証したすべての ID が含まれます。具体的には、クライアント(名前付きの listen.clients ベアラートークン、listen.authToken 用の default、または stdio)に加え、該当する場合は呼び出しの委任トークンに含まれるユーザーと、実行中のエージェントです。引数、ヘッダー、_meta、入力レスポンスに含まれる ID は無視されます。リクエストが別人を名乗って、自らの権限を昇格させることはできません。
呼び出しの判定方法。
- すべての ID に許可が必要です。 ユーザーの代理として動作するエージェントには、ユーザー自身の許可とエージェント自身の許可の両方が必要です。そのため、エージェントに広範なサービス権限があっても、権限のないユーザーのためにそれを使うことはできず(混乱した代理人の問題)、ユーザーの権限を、その権限を与えられていないエージェントが使うこともできません。委任チェーン内の以前のエージェントは何も許可しません。現在のエージェントだけが対象です。
- 拒否は許可より優先されます。 ID ごとに、条件に一致する
denyがあれば拒否されます。それ以外の場合は、すべての引数制約を満たすallowが必要です。default: "deny"の場合、一致する許可ルールがなければアクセスできません。 - ルール。
principalは"*"、またはclient、user、agentのいずれか(名前またはリスト)です。toolsは名前空間付きの名前で、完全一致するか、末尾に*が 1 つ付きます。argsは、equals、in、max、min、pathWithinを使ってトップレベルの引数を制約します。一致判定は厳密です。大文字と小文字の変換、Unicode 正規化、型の強制変換は行いません。max/minが受け付けるのは JSON 数値のみです。pathWithinは.と..を解決し、/で境界を判定します(そのため、/srv/docs-archiveは/srv/docsの配下ではありません)。 - フェイルクローズ。 制約対象の引数がない場合、
allowは不成立になります。argsを持つdenyは、制約を評価でき、かつ条件が成立しない場合を除き適用されます。そのため、引数がない場合や型が誤っている場合に、拒否をすり抜けることはできません。 - 制御ツール(
bastion__*)も、他のツールと同様にサーバー名bastionの下で認可されます。default: "deny"の場合は、上記のops-consoleのように、オペレーターのクライアントに許可を付与してください。
実行タイミング。 tools/call において、委任チェックの後、上流に接続する前に実行されます。そのため、拒否された呼び出しによって、呼び出し元の転送ヘッダーを含む接続が開始されることはありません。継続処理(input_required の再試行)でも再認可されます。tools/list では、呼び出し元が許可される可能性のないツールを非表示にします。
段階的な導入。 まず enforcementProfile: "observe" で開始します。呼び出しは一切拒否されず、各監査イベントには authorization レコード(effect、判定に使われた rule、agent:argument などの violations)と、強制適用されていれば拒否されていたことを示す wouldBlock: "blocked_authorization" が含まれます。ログに、意図した拒否だけが記録されるようになったら、balanced に切り替えます。balanced では、拒否された呼び出しに対して Blocked by mcp-bastion: this caller is not authorized to call "<tool>" (rule <id>). と応答します。その他のポリシー内容は開示されません。
ユーザー ID とエージェント ID の信頼性。 これらは、署名モードで検証されたもの、または構造モードで trustStructuralClaims: true が設定された場合に限り、信頼できる委任トークンから取得されます。上流側でも同じトークンを検証する場合に限り、この設定を有効にしてください。そうすれば、Bastion を通過した偽造クレームも上流側で拒否されます。それ以外の場合、構造モードの上流に対して user または agent を指定するルールは設定エラーとなり、信頼できないトークンが存在する場合は呼び出しが拒否されます(delegation:unverified)。
測定済み。 この一連のチェックは、コードの作成前に mcp-defense-bench でテストケースとして事前登録されました(タグは authorization-prereg-2026-10-26)。呼び出し元ごとの MCP 認可は、他のゲートウェイ(たとえば agentgateway の CEL ルールや ToolHive の Cedar ポリシー)にも実装されており、このベンチマークの事前登録では、これらを並べて評価することが約束されています。
ランタイムセキュリティ
v0.2で追加されました。 Bastionは、デフォルトで有効な、ツール呼び出し経路におけるセキュリティレイヤー(インターセプターパイプライン)を追加します。
- ラグプル検出(ツールのピン留め)。 各ツールの定義は初回使用時にピン留めされます。サーバーが後からその定義を変更した場合、オペレーターが確認し、別経路で再承認するまで、ツールはブロックされます(
onRugPull: "block")。この再承認はオペレーターのみが行え、エージェントから呼び出せるツールではありません。これは、インストール時には無害に見えたサーバーが、その後悪意のある動作に変わるケースを検出します。 - ポイズニング検査。 ツール名と説明を、操作を誘導するヒューリスティック(指示の上書き、シークレットへのアクセス、データの持ち出し、隠された指示、埋め込みディレクティブ、不可視文字やゼロ幅文字)に照らしてスキャンします。ヒューリスティックは誤検知する可能性があるため、デフォルトは
warn(記録して報告しますが、ブロックはしません)です。適用するにはonPoisoning: "block"を設定してください。 - シャドーイング。 2つのサーバーが同じ名前のツールを公開している場合、レポートに表示されます。
bastion__securityツールを使って、すべての項目を確認できます。各検出結果には、heuristicかdeterministicかが示されます。セキュリティモデルを参照してください。
監査とコンプライアンス
オプトインです。 auditを有効にすると、セキュリティレイヤーまたは認可によって拒否された呼び出しを含め、すべてのツール呼び出しについて、構造化されたバージョン付きイベントが記録されます。
"audit": {
"enabled": true,
"includeArgs": "redacted", // none | redacted | full (default for every sink)
"tamperEvident": true, // hash chain; keyed with integrityKey / MCP_BASTION_AUDIT_KEY
"onSinkFailure": "continue", // or "block": refuse calls while no sink can deliver
"sinks": [
{ "type": "file", "path": "./bastion-audit.jsonl", "includeArgs": "full" },
{ "type": "otlp", "endpoint": "https://collector.example:4318",
"headersEnv": { "authorization": "OTEL_AUTH_HEADER" }, "includeArgs": "none" }
],
"checkpoint": { // signed checkpoints (needs tamperEvident)
"privateKeyFile": "/etc/bastion/checkpoint-private.pem",
"stateFile": "/var/lib/bastion/audit-state.json",
"sinks": [{ "type": "webhook", "url": "https://witness.example/checkpoints" }]
}
}
イベント。 各イベントには、サーバー、ツール、判定(allowed、blocked_rug_pull、blocked_authorizationなど)、結果、kind付きの検出結果、存在する場合はauthorizationと委任の記録、runId、さらにNIST AI RMFの機能およびOWASP LLM Top 10のカテゴリーとの対応付けが含まれます。bastion__complianceは集計値を返します。
各シンクは、それぞれ独立したセキュリティ境界です。
console(stderr)、file(JSON Lines、0600で作成)、webhook、otlp(OpenTelemetryログ)。- リモートシンクでは、ホストがループバックの場合を除き、HTTPSを使用する必要があります。シンクに
allowInsecureTransport: trueを設定していない場合、リモートホストへのプレーンHTTPは設定エラーになります。この設定を有効にすると、警告が記録されます。 - 認証情報は設定ファイルではなく、環境変数(
headersEnv)から取得されます。変数が見つからない場合、起動は停止します。 - 配信に失敗した場合、イベントは破棄されず、指数バックオフで再試行されます。イベントは上限付きキュー(
maxQueue、デフォルトは10 000)で待機します。上限を超えると、最も古いイベントが破棄され、その件数がカウントされます。受信側は各イベントのseqから欠落を検出することもできます。 bastion__statusには、各シンクの状態(healthy、delivered、dropped、queued、lastError)が表示されます。onSinkFailure: "block"を設定すると、どのシンクも配信できない間、呼び出しは拒否されます(blocked_audit_unavailable)。監査なしの呼び出しを許容できないデプロイ向けの設定です。シンクの確認と復旧には、Bastion自身の制御ツールを引き続き使用できます。
レダクションを中核機能として備えています。
- 引数はデフォルトでは記録されません。各シンクでは、それぞれ記録するレベルを設定できます(シンクごとの
includeArgs)。たとえば、ローカルファイルには引数全体を記録し、共有SIEMには何も記録しない、といった設定が可能です。 redactedは構造を維持し、認証情報を示すキー名の値と、シークレットらしい値をマスクします。対象には、クラウドおよびプロバイダーのキー、GitHub、Slack、Stripe、Google、npmのトークン、JWT、Bearer認証情報、URL内のパスワード、秘密鍵ブロック、NAME=secret形式の代入が含まれます。同じパターンにより、エージェントに表示される前にツールの結果からシークレットをレダクションします(redactResponseSecrets、デフォルトで有効)。45ケースのコーパス(test/redaction-corpus.test.ts)で測定した結果、シークレット29件中29件を検出し、良性の類似表現16件はいずれも変更されませんでした。- シンクには決して書き込まれないもの:ツールの結果、委任トークンの値、転送されるヘッダーの値(名前のみ記録)、および
delegation.recordSubjectがhashの場合の未加工のユーザーsub。引数はincludeArgsの設定に従ってのみ記録されるため、fullでは引数として渡されたシークレットも保持されます。 - レダクションはパターンベースです。認識されないキーの下に、認識されない形式のシークレットがある場合、記録される可能性があります。そのため、機密性の高いシンクには
noneを推奨します。
改ざんの証拠と、その限界。
tamperEvidentを有効にすると、イベントはハッシュチェーンを形成します。integrityKeyを指定すると、チェーンは HMAC-SHA256 で保護されます。 キーがなければ、ログを書き換えた当事者はハッシュを再計算できません。キーを使わない場合、検出できるのは単純な改ざんだけです。- シンクによって引数の記録方法が異なる場合、チェーン(v2)は各イベントの
argsビューを除いた内容とargsDigest(すべての引数の HMAC)を対象とするため、すべてのシンクで同じチェーンを検証できます。 - ハッシュチェーンでは、最新の記録が切り詰められたことは検出できません。署名付きチェックポイントなら検出できます。
audit.checkpointはeveryEvents(100)件ごと、everySeconds(60)秒ごと、シャットダウン時に、チェーンヘッドを示す Ed25519 署名付きステートメントを書き込みます。また、各実行はstateFileを介して前回の実行とリンクされたrun-startレコードから始まります。ログをホストするマシンから書き換えられない証人シンクにチェックポイントを送信してください。 mcp-bastion audit verify <log> --checkpoints <witness.jsonl> --public-key <pem>は、チェーン、seqの連続性、チェックポイントの署名、実行間のリンク、ログの途中での切断、実行の削除を検証します。終了コードは、問題がなければ0、改ざんされていれば1、検証できない場合は2です。mcp-bastion audit keygen --out <dir>は鍵ペアを作成します。- **制限事項:**切断を検出できるのは、攻撃者が書き換えられない証人に届いた最後のチェックポイントまでです。証人がなければ、チェックポイントと一緒にログを切り詰めても検出できません。秘密鍵を持つ攻撃者はチェックポイントを偽造できるため、ログのホストから離れた場所で保管してください。
シャドウモード。 security.enforcementProfile: "observe" では何もブロックされず、各イベントに、適用モードなら何が行われたかが記録されます。wouldBlock には balanced が記録したはずの判定が入り、ラグプルは findings に tool-definition-changed として表示されます。また、responseFindings / redactedSecrets には、結果スキャンとインライン DLP で検出された内容(または、リダクションが無効な場合は secret-in-result)が記録されます。
標準への準拠
各セキュリティチェックは、広く認知されたフレームワークであるNIST AI Risk Management Framework(米国連邦標準)、OWASP Top 10 for LLM (2025)、OWASP Top 10 for Agentic (2026) Applications、およびSTRIDEに対応しています。チェックごとの完全な対応表(チェックの根拠となる MCP セキュリティ関連文献への参照リンクを含む)は、docs/CHECKS-MAPPING.md にあります。
カバレッジは独立して測定されています。Bastion は、ベンダー中立の mcp-defense-bench ベンチマークで 22 種類の攻撃対象領域に対して評価されており、公開されているリーダーボードとフレームワークの対応表も参照できます。
クライアントのセットアップ
手順はどのクライアントでも同じで、異なるのは設定ファイルの場所だけです。
| クライアント | bastion エントリの追加場所 |
|---|---|
| Claude Code | プロジェクトの .mcp.json(または claude mcp add) |
| Cursor | ~/.cursor/mcp.json またはプロジェクトの .cursor/mcp.json |
| Claude Desktop | claude_desktop_config.json |
| Cline | cline_mcp_settings.json |
| Windsurf | ~/.codeium/windsurf/mcp_config.json |
**段階的な導入:**すべてのサーバーを Bastion 経由にする必要はありません。不安定なサーバーや信頼できないサーバーだけをその背後に置き、残りは直接接続したままにできます。
アーキテクチャ
Bastion は明確なレイヤー構成を採用し、依存関係が一方向に流れるよう設計されています。そのため、各機能を個別にテストでき、容易に発展させられます。
src/
├── cli.ts # thin CLI entrypoint (parse → wire → serve)
├── index.ts # public library API
├── errors.ts # error hierarchy (BastionError, …)
├── config/ # schema (Zod) + loader
├── core/ # domain: upstream connection lifecycle, aggregation & routing
├── proxy/ # client-facing MCP server + control tools
├── observability/ # logging (audit sinks in v0.3)
└── internal/ # small cross-cutting utilities
クライアントに依存しない設計の理由、インターセプターパイプライン、監査シンクの方針など、設計の詳細はプロジェクトの設計ドキュメントに記載されています。
開発
npm install
npm run check # format:check + lint + typecheck + test (the full gate)
npm test # unit + end-to-end (in-memory transport) tests
npm run build # bundle to dist/ (CLI + library)
npm run dev -- --config bastion.config.json
| スクリプト | 内容 |
|---|---|
build | tsup で CLI とライブラリをバンドルします。 |
dev | tsx でソースから CLI を実行します。 |
typecheck | tsc --noEmit(厳密モード)。 |
lint / lint:fix | ESLint(フラット設定)。 |
format / format:check | Prettier。 |
test / test:watch | Vitest。 |
check | 上記すべてを一括で実行します。 |
ロードマップ
| バージョン | テーマ | 主な内容 |
|---|---|---|
| v0.1 ✅ | 信頼性 | 集約プロキシ、自動再接続、bastion__status / __reconnect。 |
| v0.2 ✅ | ランタイムセキュリティ | ツール定義の固定(rug-pull 検出)、ポイズニング検査、シャドーイング検出。 |
| v0.3 ✅ | 監査とコンプライアンス | プラグイン可能な監査シンク(コンソール / ファイル / webhook)、NIST AI RMF / OWASP LLM Top 10 へのマッピング。 |
| v1.2 ✅ | 委任 | 委任トークンのキーレス検証:audience、subject mixing、有効期限、actor chains、署名。 |
| v1.4 | 認可と証跡 | 呼び出し元ごとのランタイム認可、HTTPS のみを使用し、再試行とシンクごとの秘匿化に対応した監査シンク、署名付きチェックポイントと audit verify。 |
stdio と Streamable HTTP の両方のトランスポートに対応しています(トランスポートを参照)。
コントリビューション
コントリビューションを歓迎します。このプロジェクトはコミュニティによる所有を目指して開発されています。開発環境のセットアップ、プロジェクトの構成、PR のワークフローについては CONTRIBUTING.md と、行動規範 をお読みください。
概要:大規模な変更については issue を作成し、テストを含む範囲を絞った PR を作成して、必ず
npm run check が成功するようにしてください(CI では Node 18/20/22 で実行されます)。最初の取り組みに適した分野:クライアントのセットアップ手順の追加、上流のテスト用フィクスチャの拡充、Streamable HTTP トランスポートへの対応です。
セキュリティ
mcp-bastion はセキュリティに関わるソフトウェアであるため、高い基準を設けています。脆弱性は非公開で報告してください。公開 issue は作成しないでください。報告手順については SECURITY.md をご覧ください。
ライセンス
Apache-2.0 © Gowthaman Arumugam および mcp-bastion コントリビューター
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。