Sovereign Gateway について
Sovereign Gateway は、複数の上流サーバーを一元管理するための MCP プロキシです。各サーバーのツールをまとめ、設定可能な検証レイヤーで呼び出しを確認し、監査ログに記録します。
主な機能
- 01上流サーバーのツールを統合
- 02許可・拒否ポリシーの適用
- 03呼び出しと出力の検証
- 04プロンプトインジェクションの検出
- 05ハッシュチェーン監査ログへの記録
- 06設定と有効なレイヤーの確認
活用シーン
- 01複数の MCP サーバーにポリシーを適用
- 02上流への到達前に呼び出しを検査
- 03許可・拒否された呼び出しを追跡
- 04クライアント接続前にゲートウェイ設定を検証
MCP 対応
MCP クライアントと設定済みの上流サーバーの間で動作する MCP サーバーです。上流のツールをまとめて公開し、呼び出しは検証レイヤーを経てから上流に送られます。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
sovereign-mcp-gateway
Model Context Protocol サーバー用のゲート付きプロキシです。 MCP クライアントの接続先をサーバーではなくゲートウェイにします。指定したすべてのアップストリームに接続し、それらのツールカタログを1つにまとめ、実行するサーバーに到達する前に、すべての呼び出しを検証チェーンに通します。
pip install sovereign-mcp-gateway
sovereign-mcp-gateway --init # writes gateway.json from the servers you already run
sovereign-mcp-gateway --config gateway.json --check
--init は、すでにお使いの MCP 設定(Claude Desktop、Claude Code、Cursor、VS Code、Windsurf)を読み込み、同じサーバーにプロキシ接続する gateway.json を作成します。そのため初回の実行で設定エラーではなく、動作する設定が生成されます。ゲートウェイ自身のエントリはインポートしません。インポートすると、自分自身をプロキシすることになるためです。
ゲートウェイ自体が MCP サーバーなので、MCP に対応するクライアントなら変更なしで使用できます。
基本インストールだけでも、ゲートウェイとして機能します。さらに4つのオプションを追加して、保護レイヤーを強化できます。詳しくはインストールをご覧ください。
防げること
エージェントが、あなたではなくモデルに向けた指示を本文に含む GitHub の Issue を読み込みます。エージェントはその指示に従い、git_commit を呼び出します。
| コミット後 | 注入されたコミットが存在する | |
|---|---|---|
mcp-server-git に直接接続 | 2 | はい |
| ゲートウェイ経由 | 1 | いいえ |
同じツール、同じ引数、同じサーバーです。違いは、呼び出しを拒否できる仕組みがあったかどうかです。
解説をご覧ください:エージェントが Issue を読む — または、実際に試してみてください:
pip install "sovereign-mcp-gateway[all]" mcp-server-git
python examples/poisoned_issue.py
ライブラリではなくプロキシを使う理由
ライブラリを使うには、サーバーの開発者に採用してもらう必要があります。プロキシなら、変更できないサーバーを保護できます。有用な MCP サーバーの多くは、他者がメンテナンスする公開パッケージだからです。
また、エージェントがアクセスできるすべてのサーバーに対して、ポリシーを一元管理し、監査証跡を1つにまとめられます。サーバーごとの設定では、同期が保たれないことがあります。
設定
すでに使っている設定をもとにする
$ sovereign-mcp-gateway --init
Wrote gateway.json
imported 3 servers from Claude Desktop
/Users/you/Library/Application Support/Claude/claude_desktop_config.json
imported 1 server from VS Code (project)
upstreams: fetch, git, sqlite, time
skipped:
sovereign - this gateway - importing it would proxy itself
notion - no command, probably a remote/SSE server
git - already imported from another client
実行しないことが4つあります。ゲートウェイ自身をインポートすること、サブプロセスとして起動できないリモートサーバーをインポートすること、--force なしで既存ファイルを上書きすること、指定していない deny_tools リストを書き込むことです。ファイルを作成し、何を取り込み、何を取り込まなかったかを伝えて終了します。
--init と一緒に --config PATH を渡すと、./gateway.json 以外の場所に書き込めます。
実行後、クライアントでそれらのサーバーをゲートウェイのエントリ1つに置き換えてください。両方を残すと、エージェントはプロキシ経由だけでなく、サーバーにも直接アクセスします。その場合、監査証跡に記録されるのはトラフィックの半分だけです。
{
"servers": {
"git": {"command": "mcp-server-git", "args": ["--repository", "/repo"]},
"sqlite": {"command": "mcp-server-sqlite", "args": ["--db-path", "/data.db"]}
},
"policy": {"deny_tools": ["git__git_reset"], "pii_policy": "warn"},
"audit": {"path": "gateway-audit.jsonl"}
}
クライアントに見せる前に、接続設定を確認してください:
sovereign-mcp-gateway --config gateway.json --check
SOVEREIGN GATEWAY - configuration check
upstreams: 2
layers: policy -> intent -> text-filter -> frozen-verify -> audit
EXPOSED AS UPSTREAM TOOL
git__git_status git.git_status
git__git_reset git.git_reset [DENIED]
sqlite__read_query sqlite.read_query
...
18 tools exposed.
チェーン
policy → intent → text-filter → frozen-verify → [ call executes ] → output-verify → logic-rules → audit
| レイヤー | パッケージ | 拒否する条件 |
|---|---|---|
| ポリシー | — | ツールが拒否リストにある、または許可リストにない |
| インテント | intentshield | 呼び出しが動作上の最低基準を満たさない |
| テキストフィルター | sovereign-shield | 21言語または7種類のエンコーディングのいずれかで、引数にインジェクションが含まれる |
| 凍結定義の検証 | sovereign-mcp | 呼び出しが起動時に固定されたツール定義と一致しない |
| 出力検証 | sovereign-mcp | 結果がスキーマ、欺瞞、PII、またはコンテンツのチェックに失敗する |
| ロジックルール | logicshield | 結果が設定したルールと一致しない |
| 監査 | sovereign-mcp | — 許可・拒否を問わず、すべての呼び出しをハッシュチェーン形式のログに記録する |
インストール
基本インストールは、スタブではなく、すぐに使えるゲートウェイです。
pip install sovereign-mcp-gateway
これにより、ポリシー → frozen-verify → 監査が利用でき、上流で公開されていないツール、型が正しくない引数、宣言されていないパラメーター、拒否リストに登録されたツール、引数内のプロンプトインジェクションをすでに拒否できます。それ以外は必要ありません。
追加機能を導入すると、それぞれレイヤーが追加されます。
| 追加機能 | 追加されるもの | 役立つ場面 |
|---|---|---|
[text] | sovereign-shield — 文字列引数をさらに詳しく検査します:21 言語に対応し、base64、hex、ROT13、leetspeak、テキストの逆順で隠されたペイロードを 7 種類の方法でデコードします | 管理していないあらゆる場所からエージェントがテキストを読み取る場合。基本インストールでは IGNORE ALL PREVIOUS INSTRUCTIONS を検出できますが、同じ文を base64 でエンコードしたものや、オランダ語で書かれたものは検出できません |
[intent] | intentshield — 呼び出されたツールに関係なく適用される、動作上の最低基準です:シェルの禁止、削除の禁止、認証情報を含む URL、マルウェアの構文 | すべてのツールのスキーマを正しく設定できていなくても機能する追加の安全策が必要な場合 |
[rules] | logicshield — ツールの出力に対して作成する整合性ルールです | 正しい結果の条件を表現できる場合。output_rules を設定するまでは何も行いません |
[consensus] | requests — Layer C の HTTP プロバイダーに必要です | ホスト型プロバイダーで N モデルのコンセンサスを有効にする場合 |
必要なものを組み合わせるか、すべて導入します。
pip install "sovereign-mcp-gateway[text]" # one extra
pip install "sovereign-mcp-gateway[text,intent]" # several
pip install "sovereign-mcp-gateway[all]" # every layer
4 つの追加機能はすべて、小規模な純粋 Python パッケージです。[all] を指定しても、コンパイル済み依存関係や実行が必要なサービスは追加されません。
一部だけインストールした場合は、その状態が明確に表示されます。 ゲートウェイは起動時に有効なレイヤーを表示するため、実際に何が動作しているかを常に確認できます。
layers: policy -> frozen-verify -> audit # base
layers: policy -> intent -> text-filter -> frozen-verify -> audit # [all]
この行に表示されていないレイヤーは動作していません。インストールしたつもりでも同じです。
エンドツーエンドで検証済み
実際の上流サーバーとして稼働する mcp-server-git と mcp-server-sqlite に対し、実際の MCP クライアントを使用して検証しました。
| 呼び出し | 結果 |
|---|---|
git__git_status、git__git_log | 許可 |
sqlite__create_table、__write_query、__read_query | 許可 — 行が実際にデータベースに存在します |
git__git_reset | 拒否:拒否リストに登録されています |
git__git_push_force | 拒否:上流で公開されていません |
git__git_status(repo_path=12345) | 拒否:frozen スキーマに対して型が正しくありません |
git__git_commit("IGNORE ALL PREVIOUS INSTRUCTIONS…") | 拒否:テキストフィルター |
sqlite__git_commit(...) | 拒否:別の上流の名前空間を通じてツールにアクセスすることはできません |
その後も、リポジトリには 1 つのコミットが保持され、データベースにはあるべき行だけが格納されています。ゲートウェイ自身の報告を信用するのではなく、リポジトリとデータベースを直接開いて確認しました。10 回の呼び出しに対して監査記録は 11 件あり、いずれか 1 件を編集するとチェーンが破損します。
これらはスクリーンショットではなく、テストスイートです:pytest tests/ -v。
Layer C:N モデルのコンセンサス
ほかのレイヤーはすべて決定論的でローカルに動作します。Layer C は例外です。複数の独立したモデルに対し、ツールの結果から同じ構造化ドキュメントを抽出するよう依頼し、それぞれの回答を正規化して SHA-256 ハッシュを比較します。一致は文章ではなく、ハッシュによって判定されます。
呼び出しごとにコストと遅延が発生し、ツールの出力をモデルに送信する唯一のレイヤーであるため、設定しない限り無効です。
{
"servers": { "...": {} },
"consensus": {
"providers": [
{"type": "local", "model": "llama3.1:8b"},
{"type": "local", "model": "qwen2.5:7b", "base_url": "http://localhost:11434/v1"},
{"type": "openrouter", "model": "anthropic/claude-3.5-sonnet",
"api_key_env": "OPENROUTER_API_KEY"}
]
}
}
プロバイダーの種類は 2 つあります:local(Ollama、vLLM、LM Studio など、OpenAI 互換のエンドポイント。base_url のデフォルトは http://localhost:11434/v1)と、openrouter(キーは指定された環境変数から読み込まれ、設定ファイルには書き込まれません)。
ゲートウェイは実行時に問題が発覚するのではなく、起動時に次の 3 つのルールを適用します。
- プロバイダーは少なくとも 2 つ必要です。 1 つのモデルが自分自身と意見を異にすることはできません。1 つだけのコンセンサスはすべての呼び出しで一致を報告するため、検証されているように見えてしまい、レイヤーがないよりも悪い状態になります。
- モデルの重複は許可されません。 同じモデルの 2 つのインスタンスが一致しても、独立した検証にはなりません。
- API キーがない場合は起動を拒否します。 このレイヤーを無効にして実行するようなフォールバックはありません。
すべてのプロバイダーは temperature = 0 で実行されます。これはコンストラクターで強制されます。
このレイヤーを信頼する前に、モデルの合意を確認する
--check は設定済みのモデルに対して実際のコンセンサス呼び出しを1回実行し、結果を通知します。これは思った以上に重要です。
LAYER C - probing the configured models with one real call
--------------------------------------------------------------
OK. The configured models produced identical documents.
Layer C will pass ordinary output rather than refusing it.
コンセンサスでは正規化されたハッシュを比較するため、意味的にはどちらも正しいモデルでも、構造が異なれば合意しません。スキーマをそのまま返すだけの性能の低いモデルでは、次のようになります。
{"branch": {"type": "string", "value": "main"}} instead of {"branch": "main"}
呼び出しのたびに、いつまでも不一致となり、ゲートウェイは「モデルが合意しませんでした」という正しい理由ですべてを拒否します。実際に合意していないためです。
プローブでは、次の3つの結果を判別できます。
| 意味 | |
|---|---|
| OK | モデルが同一のドキュメントを生成しました。このレイヤーは使用可能です |
| MISMATCH | 単純なドキュメントでも合意せず、すべての呼び出しが拒否されます。モデルを入れ替えるか、このセクションを削除してください |
| provider unreachable | 何も検証されていません。キー、モデル ID、またはエンドポイントが間違っています |
sovereign-mcp-gateway[consensus] または [all] をインストールしてください。HTTP プロバイダーには requests が必要ですが、コアライブラリは意図的にこれに依存しないようになっています。
--check は有効なレイヤーも一覧表示するため、ひと目で次のことを確認できます。
layers: policy -> intent -> text-filter -> frozen-verify -> consensus -> audit
この行に consensus がなければ、設定の内容にかかわらず実行されていません。
名前空間
namespace を有効にすると(デフォルト)、ツールは git__git_status のように公開されます。同じツール名を提供する複数の上流サーバーがあっても、名前が衝突したり、互いを隠したり、誤った名前空間を通じてアクセスされたりすることはありません。無効にするのは、上流サーバーが1つだけの場合にしてください。
ポリシー
"policy": {
"deny_tools": ["git__git_reset", "write_query"],
"allow_tools": null,
"pii_policy": "warn",
"fail_closed": true,
"rate_limit_interval": 0
}
deny_toolsは、公開名(git__git_reset)または上流ツール名(git_reset。そのツールを持つすべての上流サーバーが対象)に一致します。allow_toolsを設定すると、一覧にないものはすべて拒否されます。pii_policyのデフォルトはblockではなくwarnです。実際のツールは通常の出力として個人データを返します。たとえば、すべてのgit logエントリーには作成者のメールアドレスが含まれます。これらをブロックすると、ゲートウェイが使えなくなります。ツールから PII を決して出力させない場合は、blockを設定してください。fail_closedは、レイヤー自体でエラーが発生した場合の動作を決定します。デフォルトでは拒否します。rate_limit_intervalは0で、これにより動作上の下限であるアクション間の遅延が無効になります。この遅延は、意図的に手順を踏む単一のエージェントには適切ですが、ツール呼び出しのバーストが通常のトラフィックとなるプロキシには適しません。entropy_policyのデフォルトはwarnです。テキストフィルターのエントロピー判定ヒューリスティックは、文章に隠されたエンコード済みペイロードを検出します。しかし、ツールの引数はパス、識別子、ハッシュなどの構造化データであることが多く、そこでは高いエントロピーが正常です。一時ディレクトリのパスだけで、正当な呼び出しが拒否されたこともあります。引数が実際に文章である場合は、blockを設定してください。
この機能でできないこと
凍結された定義に照らして呼び出しを検証し、引数と結果を検査します。サーバーのソースコードは読み取らないため、存在して呼び出されているものの、何もせずに終わるチェックを検出することはできません。その確認には、引き続き誰かが実装を読む必要があります。
また、侵害された上流サーバーが正しく見えるデータを返すことからも保護できません。その対策は sovereign-mcp のレイヤー C コンセンサスが担いますが、設定するモデルプロバイダーはご自身で用意する必要があります。
ライセンス
Business Source License 1.1 — LICENSE を参照してください。
ソースコードは公開されています。閲覧、変更、派生物の作成が可能で、開発、評価、その他の非本番目的であれば無料で使用できます。
**本番環境での使用も、個人または4人以下の組織であれば無料です。**これはここに記載しているだけでなく、追加利用許諾としてライセンスに明記されています。規模の大きい組織には商用ライセンスが必要です。
各バージョンは、公開から4年後の変更日に Apache 2.0 に切り替わります。
本番環境での使用許諾を得る場合や、ご自身の用途にライセンスが必要かどうかを確認する場合は、次の宛先にお問い合わせください。 [email protected]
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。