mcpField
G
gpg-mcp

gpg-mcp

ローカル
github.comセキュリティ24 日前に更新

gpg-mcp について

gpg-mcp は、OpenPGP キーの署名、検証、暗号化、復号、管理を行う GnuPG MCP サーバーです。固定された型付き操作と承認・キー許可リストにより、秘密鍵を MCP 境界に出さず gpg-agent 内に保ちます。

主な機能

  1. 01データの署名と検証
  2. 02メッセージの暗号化と復号
  3. 03OpenPGP キーの管理
  4. 04高リスク操作の承認
  5. 05高リスク操作の監査

活用シーン

  1. 01秘密鍵を Agent に渡さず内容に署名
  2. 02許可リストのキーだけでメッセージを復号
  3. 03受け入れポリシーに沿った署名検証

MCP 対応

固定された型付き GnuPG 操作ツールを MCP クライアントに公開します。秘密鍵の情報とパスフレーズは MCP 境界を越えません。

設定

ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。

mcp.json · 共通設定
{
"mcpServers": {
"emiliano-go-gpg": {
"command": "uvx",
"args": [
"gpg-mcp"
],
"env": {
"GPG_MCP_CONFIG": "<GPG_MCP_CONFIG>"
}
}
}
}
起動コマンドuvx gpg-mcp
設定が必要な環境変数
GPG_MCP_CONFIGOptional path to the gpg-mcp config file.

ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。

パッケージ
pypigpg-mcp0.1.0

ツール

ツール一覧はまだ取得されていません

ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。

詳細

gpg-mcp

GnuPG 用の、セキュリティを重視したModel Context Protocol サーバーです。

gpg-mcp を使うと、AI エージェントは OpenPGP 鍵の署名、検証、暗号化、復号、管理を行えます。秘密鍵の情報を受け取ることは一切ありません。秘密鍵は gpg-agent に保持され、パスフレーズは pinentry にのみ渡されます。リスクの高い操作には人間による明示的な承認が必要で、破壊的な操作にはフィンガープリントの末尾を入力する必要があります。

脅威モデルを一文で表すと: MCP サーバーはポリシー境界であり、OS サンドボックスではありません。エージェントが秘密鍵を受け取ることや、秘密鍵を気づかれずに使用することを防ぎます。同じ OS ユーザーとしてエージェントがすでにシェルアクセスを持っている場合に備えて保護するには、署名処理を別のユーザーとして実行するか、ハードウェアトークンを使用してください(より強力な隔離を参照)。


開発の背景

多くの「GPG MCP」ラッパーは、薄い subprocess シェルです。command: str パラメーターを持つツールや、--export-secret-keys を要求できるエージェントがあれば、目的が損なわれます。それに対して gpg-mcp は、意図的に機能を制限した、固定の型付きインターフェイスを提供します。

  • 任意のコマンド実行はできません。 run_gpg(args) ツールはありません。
  • 秘密鍵のエクスポートやバックアップはできません。 --export-secret-keys、--export-secret-subkeys、--export-secret-ssh-key にはアクセスできません。
  • パスフレーズのパラメーターはありません。 --passphrase、--passphrase-fd、--passphrase-file、ループバック pinentry、環境変数や stdin でのパスフレーズ指定はできません。
  • --homedir による上書きはできません。 キーリングは設定で固定されます。
  • 短い鍵 ID は使用できません。 操作には 40 桁または 64 桁の完全なフィンガープリントが必要です。
  • 鍵を自動取得しません。 検証時にネットワークから鍵をひそかに取得することはありません。
  • 非表示の受信者は認めません。 復号前に暗号文を検査し、許可された鍵宛てではないメッセージを拒否します。
  • 応答ガードを備えています。 gpg が秘密鍵の情報と思われるものを出力すると、呼び出しは失敗し、出力は破棄されます。

セキュリティモデル

サーバーが保証すること
  1. 秘密鍵が MCP の境界を越えることはありません。 秘密鍵を一覧表示しても、返されるのはメタデータのみです。 署名と復号は gpg-agent によって実行されます。
  2. サーバーがパスフレーズを目にすることはありません。 --pinentry-mode ask が強制され、pinentry は人間と直接やり取りします。サーバーは argv、env、stdin からパスフレーズを読み取れません。
  3. 署名と復号には、許可リストに登録された鍵を使用します。 ~/.gnupg を共有している場合、許可リストが空であれば、どちらも拒否されます。専用のキーリングでは、キーリング自体が許可リストの境界となります。
  4. 復号では受信者を確認します。 復号する前に gpg --list-packets を使用して、暗号文の宛先が許可された鍵であることを確認します。隠し受信者は、同じメッセージに表示された許可済みの受信者が含まれていても、デフォルトでは拒否されます。
  5. 埋め込み署名が無効な場合、復号を中止します。 verify=true(デフォルト)で、復号されたメッセージに不正な署名、期限切れの署名、または失効した署名が含まれている場合、平文は返されません。valid はポリシー上の判定であり、暗号学的な結果は別途報告されます。複数の署名は NEWSIG シーケンスごとに集約されます。--proc-all-sigs に対応していない GnuPG では、パケットごとに集約されます。イベントの順序にかかわらず、いずれかの署名がポリシー上許容されない場合は、フェイルクローズで拒否されます。
  6. 認可にはフェイルクローズのレジストリを使用します。 高リスクの各ツールでは、登録済みの操作を指定します。不明な操作には承認が必要です。複合操作(sign_and_encrypt、および sign_with を指定した encrypt)には、構成要素となる各操作の承認要件が適用されるため、署名だけ、または暗号化だけを制限するポリシーを回避できません。
  7. 失効証明書は、インポート前に検証されます。 証明書には失効署名が含まれていなければなりません。また、秘密鍵パケットを拒否し、指定されたフィンガープリントと完全に一致する対象を示し、エフェメラルキーリングでその鍵が実際に失効することを確認できなければなりません。apply=false は真のドライランであり、実際のキーリングには一切触れません。
  8. 破壊的な操作には、入力による確認が必要です。 削除、失効、または失効証明書の適用には、オペレーターがフィンガープリントの末尾8文字を入力する必要があります。これは destructive_confirmation で制御され、require_approval とは独立しています。
  9. 高リスクの操作はすべて監査されます。 台帳には操作名、フィンガープリント、ペイロードの SHA-256、サイズ、判定が記録されます。平文、ペイロードのプレビュー、パスフレーズは記録されません。
  10. シェルは使用しません。 コマンドには execve 形式の argv 配列を使用します。シェルによる展開はなく、ユーザー文字列からオプションが注入されることもありません。
  11. 環境変数は最小限に制限します。 LD_*、GPG_AGENT_INFO、GPG_TTY、SSH_AUTH_SOCK などの変数は gpg に渡されません。pinentry に必要な表示・セッション変数のみ保持されます。
  12. バイナリとパスを安全性の確認済みのものに限定します。 gpg、gpgconf、zenity は絶対パスで解決され、通常ファイルであり、グループまたはその他のユーザーによる書き込みが禁止されていなければなりません。安全でない zenity が見つかった場合、差し替えられたダイアログを信用せず、ローカル承認をフェイルクローズで拒否します。
  13. リソースを制限します。 入出力サイズの上限、操作ごとのタイムアウト、タイムアウト時に強制終了される専用プロセスグループ、および 0700 の一時ディレクトリと 0600 のファイルを使用します。有効なステータス出力上限を超えた場合、部分的に解析するのではなく、フェイルクローズで拒否します。
  14. 汎用インポーターでは失効させられません。 import_public_key は、秘密鍵パケットと、鍵の素材に埋め込まれた失効署名を含むすべての失効署名を拒否します。失効には import_revocation を使用する必要があります。この操作では、対象が検証され、入力による確認が求められます。
  15. 実際に復号に使われた鍵を確認します。 復号後、DECRYPTION_KEY ステータスで許可済みの主鍵またはサブ鍵が指定されていることを確認します。指定されていない場合、平文は破棄されます。表示された受信者が許可済みでも、別の秘密鍵を使って暗号文が密かに復号されることはありません。
  16. GnuPG の設定は一貫しています。 実行処理では --no-options と --pinentry-mode ask を使用するため、悪意のある gpg.conf によって loopback pinentry が有効化されたり、その他のセキュリティ関連のデフォルト設定が変更されたりすることはありません。
  17. ファイルシステムのパスは、シンボリックリンクをたどらずに検査されます。 設定ファイルのパスは、ディレクトリのファイルディスクリプターと O_NOFOLLOW を使ってたどり、開いたファイルは fstat で検証するため、検証と使用の間に競合が起きたり、パスの差し替えによって別の場所へ誘導されたりすることはありません。キーリングのパスは未解決のまま保持されます(GNUPGHOME はシンボリックリンクの解決を行いません)。serve、doctor、init はキーリングの全祖先チェーンを検証し、シンボリックリンクになっているキーリングや祖先を拒否します。祖先はユーザーまたは root が所有し、sticky bit が設定されていない限り、グループまたはその他のユーザーによる書き込みが禁止されていなければなりません。不明なキーは拒否されます。既存の監査ファイルは fstat で検査し、通常ファイルでないファイルや所有者が異なるファイルは拒否されます。また、グループおよびその他のユーザーのアクセス権を 0600 に制限します。audit_required = true の場合、監査に失敗すると操作も失敗します。init は O_EXCL|O_NOFOLLOW を使って設定ファイルを安全に作成し、シンボリックリンクになっている gpg-agent.conf は、リンク先への書き込みや chmod を行わずに拒否します。存在しない設定、キーリング、監査の各ディレクトリは、検証済みのディレクトリディスクリプターを基準にコンポーネントごとに作成されるため、シンボリックリンクになっている祖先によって、拒否される前にパスが変更されたり、何かが作成されたりすることはありません。監査パスにも同じディレクトリファイルディスクリプターによる検査を適用するため、安全でない祖先によって台帳の保存先が変更されることはありません。
  18. 復号の経路を明確に区別します。 symmetric_decrypt は、公開鍵の受信者も含むハイブリッド暗号文を拒否します。decrypt は共通鍵暗号のみの暗号文を拒否し、GnuPG が実際に許可リストに登録された公開鍵を報告しない限り、平文を返しません。共通鍵暗号の経路にフォールバックすることはありません。したがって、symmetric_decrypt のみを制限するカスタムポリシーを decrypt 経由で回避することはできません。ハイブリッド入力では、GnuPG による回復可能な共通鍵パスフレーズの失敗のみを許容します。ただし、公開鍵についても DECRYPTION_KEY と DECRYPTION_OKAY が報告された場合に限ります。汎用の ERROR/FAILURE イベントと、理由が説明されていないゼロ以外の終了コードは拒否されます。
  19. 複数署名の処理はフェイルクローズです。 デタッチ署名では、--proc-all-sigs に対応していない GnuPG バージョンの場合、パケットごとのフォールバックを使用します。クリアテキスト署名、インライン署名、埋め込み署名では、対応している場合に --proc-all-sigs を使用します。古い GnuPG では、最初の署名が不正なメッセージの場合、最初の不正な署名の時点で列挙が停止することがありますが、そのメッセージは引き続き拒否されます。すべての署名が正常なメッセージでは、すべての署名が列挙されます。
  20. 共通鍵暗号による復号も同様に厳格です。 DECRYPTION_OKAY を必須とし、DECRYPTION_FAILED、BADMDC、ERROR、FAILURE を拒否します。また、理由が説明されていないゼロ以外の終了コードは致命的なエラーとして扱います。verify=false の場合、ゼロ以外の終了コードを許容するのは、埋め込み署名の結果として明示的に認識された場合に限ります。これに関係のない GnuPG の失敗は、決して許容されません。
検証結果の意味

verify(および decrypt が返す埋め込み署名の結果)では、次の4つの概念を区別します。

フィールド意味
cryptographically_validgpg が VALIDSIG を出力しました。署名の計算は正しいです
policy_acceptableさらに GOODSIG があり、署名の期限切れ、鍵の期限切れ、鍵の失効、公開鍵の欠落がありません
validpolicy_acceptable の別名で、互換性のために維持されています
identity_trusted署名者が完全または究極の信頼を得ています。別途報告され、受け入れの要件ではありません

復号では、埋め込まれたすべての署名が policy_acceptable の場合にのみ、平文を出力します。数学的に有効でも期限切れまたは失効した署名だけでは不十分であり、不正な署名が後続の有効な署名によって隠されることもありません。結果には、NEWSIG シーケンスごとに1つのエントリーを含む signatures リストが含まれます。

保証されないこと
  • 同一ユーザー内の分離。 OS のユーザーとして実行されているプロセスは、いずれも ~/.gnupg の読み取り、gpg-agent ソケットへの接続、または ~/.config/gpg-mcp/config.toml の編集が可能です。エージェントがシェルにアクセスできる場合、MCP ポリシーは OS レベルの境界にはなりません。より強力な分離を使用してください。
  • 悪意のある MCP クライアント。 approval = "client" モードでは、クライアントが承認ダイアログを表示します。悪意のあるクライアントはこれを偽装できます。approval = "local"(クライアントから独立した zenity)または別のユーザー/ハードウェアトークンを使用してください。
  • 侵害された gpg または gpg-agent。 侵害されたシステムバイナリは何でも実行できます。バイナリのチェックは PATH の乗っ取りを軽減しますが、サプライチェーンの侵害を防ぐものではありません。
  • 意味上の安全性。 サーバーは署名対象(ハッシュとプレビュー)を表示できますが、その内容が安全に署名できるかどうかは判断できません。その判断は人間に委ねられています。
脅威の一覧
脅威対策
エージェントが秘密鍵を要求する秘密鍵を返すツールはありません。レスポンスガードが誤った出力をブロックします
エージェントが --export-secret-keys を試すオプションは構築されず、生の exec もありません
エージェントが UID/フィンガープリントとしてオプションを指定するフィンガープリント全体を検証します。UID では先頭の - と制御文字を拒否し、鍵の作成にはパラメーターファイルを使用します
エージェントが悪意のあるタグ/リリースに気づかれず署名する許可リストと、鍵、サイズ、SHA-256、プレビューを表示する承認
エージェントが盗まれた暗号文を復号する許可リスト、承認、受信者の事前確認
エージェントが攻撃者の鍵で秘密情報を暗号化する承認画面に名前付き受信者を表示し、必要に応じて allowed_recipients を使用します
エージェントが秘密鍵をインポートする秘密鍵パケットを検出して拒否します
エージェントが鍵を削除するdestructiveHint と、フィンガープリント末尾の入力
エージェントが鍵を失効させるdestructiveHint と、フィンガープリント末尾の入力
エージェントが別の鍵の失効証明書を送信する一時的なキーリングで証明書を検証し、要求されたフィンガープリントに紐付けます
エージェントが失効のドライランで状態を変更しようとするapply=false は一時的なキーリングでのみ検証します
エージェントが、一方の複合構成要素だけを承認対象とするカスタムポリシーを悪用する複合操作は、すべての構成要素の承認要件を引き継ぎます
エージェントが監査台帳からペイロードを読み取る承認プレビューは UI 内にとどめ、監査にはハッシュ/メタデータのみを保存します
エージェントが表示されている受信者に隠れた受信者を混ぜる明示的に有効化されていない限り、隠れた受信者がいる場合は拒否します
エージェントが偽のローカル承認ダイアログを表示するzenity にも gpg と同じ信頼できるバイナリのチェックを適用します
エージェントが不正な署名の平文を読み取る不正/期限切れ/失効済みの埋め込み署名はポリシー上許容されず、中止されます
エージェントが後続の有効な署名で不正な署名を隠すNEWSIG ごとの集約では、許容できない署名が1つでもあると必ず失敗します
エージェントが承認なしでキーリングを変更するために鍵を取得するfetch_key は承認が必要な書き込み操作として登録され、インポートしたフィンガープリントを報告します
エージェントが UID を介して承認ダイアログに改行や双方向テキストを挿入する承認前に1行形式へのエスケープと検証を行います
既存の監査ファイルが全ユーザーから読み取り可能になっているfstat と fchmod で 0600 に設定し、通常ファイルでないファイルや別の所有者のファイルは拒否します
require_approval から破壊的操作が削除されるdestructive_confirmation はデフォルトで引き続き、指定された末尾の入力を要求します
汎用インポーター経由で失効証明書が送信されるパケットレベルで失効署名を拒否します。import_revocation を使用してください
復号時に許可リストにない秘密鍵が気づかれず使用されるDECRYPTION_KEY の状態を確認し、一致しない場合は平文を破棄します
巨大な/不完全な状態ファイルが成功として扱われる実効状態上限を適用し、部分的な状態は必ず失敗させます
ハイブリッドメッセージが公開鍵の許可リストを迂回して対称復号に回されるsymmetric_decrypt は公開鍵の受信者を拒否し、decrypt は報告された許可リスト内の公開鍵を要求します
対称鍵のみの入力で、制限の緩い decrypt の承認が使われるdecrypt は実行前に対称鍵のみの暗号文を拒否します
古い GnuPG が最初の不正な署名で処理を停止する分離署名パケットを個別に検証し、必ず失敗する形で集約します
検証とオープンの間に設定が差し替えられるディレクトリー fd によるパス走査、O_NOFOLLOW、およびオープンしたディスクリプターに対する fstat
別のユーザーによってパスの祖先が差し替えられる祖先を dir fd で走査し、スティッキービットのない書き込み可能な祖先は拒否します
init が仕掛けられた gpg-agent.conf のシンボリックリンクをたどるlstat/O_NOFOLLOW と通常ファイル/所有者のチェック
シンボリックリンクされたキーリングの祖先が GNUPGHOME の参照先を変える未解決のパスとそのすべての祖先チェーンを、serve/doctor/init の実行時に検証します
マルチバイトテキストが入力上限を大幅に超えるメモリーを割り当てる受け入れ前に、上限付きのチャンクで UTF-8 にエンコードします
不可逆操作後に結果の監査記録が失敗する意図と結果の段階を記録し、結果の記録に失敗した場合は操作が完了している可能性を示します
悪意のある gpg.conf が実行動作を変更する--no-options と明示的な --pinentry-mode ask
グループ/全ユーザーが書き込み可能な設定がポリシーを変更する設定の整合性チェックで、安全でないファイルと不明なキーを拒否します
監査書き込みの失敗が気づかれずに発生するaudit_required = true により操作が失敗します
圧縮爆弾/巨大な出力上限付きのストリーミング読み込みを行い、プロセスグループを強制終了します
PATH の乗っ取りバイナリの絶対パスと、所有者/モードのチェック
argv/環境変数/stdin を介したパスフレーズ漏えいPinentry のみを使用し、パスフレーズを扱うコードパスはありません
応答されないプロンプトタイムアウト時にプロセスグループを強制終了し、承認の迂回はできません

アーキテクチャ

MCP client (agent)
   │  stdio JSON-RPC
   ▼
gpg-mcp (Python, mcp SDK v2)
   │  fixed argv, stdin/stdout, --status-file
   ▼
gpg 2.2+ (2.4 shown) ──► gpg-agent ──► pinentry (human passphrase)
   │
   ▼
GNUPGHOME (encrypted private keys + public keyring)

サーバーが秘密鍵ファイルを開くことはありません。操作は gpg に依頼し、pinentry による認証が成功した後にのみ、gpg-agent が鍵のロックを解除します。


インストール

PyPI:gpg-mcp。MCP Registry:io.github.emiliano-go/gpg-mcp。

クライアント設定でバージョンを固定すると、再起動時にサーバーのビルドが変わりません。

# run without a global install
uvx [email protected] serve

# or install a pinned CLI
uv tool install gpg-mcp==0.1.0
# or
pipx install gpg-mcp==0.1.0
# or
pip install gpg-mcp==0.1.0

初回実行時は、CLI をインストールしていない場合、これらのコマンドの先頭に uvx [email protected] を付けてください。

gpg-mcp init
gpg-mcp doctor

グローバルインストールを使用しない場合の MCP クライアント設定:

{
  "mcpServers": {
    "gpg": {
      "command": "uvx",
      "args": ["[email protected]", "serve"]
    }
  }
}

uv tool または pipx でインストールした場合:

{
  "mcpServers": {
    "gpg": {
      "command": "gpg-mcp",
      "args": ["serve"]
    }
  }
}

要件:Python 3.11 以降、GnuPG 2.2 以降(2.4 推奨)、pinentry、および approval = "local" を使用する場合は zenity。Linux およびその他の Unix 系システムに対応しています。Windows には対応していません。

レジストリーのエントリーは、次の URL で検索できます。 https://registry.modelcontextprotocol.io/v0.1/servers?search=io.github.emiliano-go/gpg-mcp


クイックスタート(ソースから)

要件:Python 3.11 以降、GnuPG 2.2 以降(2.4 推奨)、pinentry プログラム。

git clone https://github.com/emiliano-go/gpg-mcp.git
cd gpg-mcp
uv sync
uv run gpg-mcp init

init は ~/.local/share/gpg-mcp/gnupg に分離されたキーリング(モード 0700)を、~/.config/gpg-mcp/config.toml に設定ファイル(モード 0600)を作成します。安全性を重視した gpg-agent.conf を書き込みます。

default-cache-ttl 60
max-cache-ttl 300
ignore-cache-for-signing
no-allow-external-cache
no-allow-mark-trusted
pinentry-timeout 120

ignore-cache-for-signing を設定すると、署名のたびに pinentry が再度表示されます。この設定は、トレードオフを理解している場合にのみ削除してください。

インストールを確認します。

uv run gpg-mcp doctor

MCP クライアントに追加します(JSON の mcpServers マップの例)。

{
  "mcpServers": {
    "gpg": {
      "command": "gpg-mcp",
      "args": ["serve", "--config", "/home/you/.config/gpg-mcp/config.toml"]
    }
  }
}

次に、エージェントから create_key を使って鍵を作成し(パスフレーズは pinentry に入力します)、返されたフィンガープリントを sign、encrypt、または decrypt で使用します。

**クライアントのタイムアウト:**承認と pinentry に、クライアントのデフォルトの MCP ツールタイムアウトを超える時間がかかることがあります。少なくとも 120 秒に設定してください。鍵の生成やパスフレーズの変更には、300 秒が余裕のあるデフォルト値です。opencode の場合:

"experimental": { "mcp_timeout": 300000 }

ダイアログが開いている間にクライアントがタイムアウトした場合は、ダイアログをキャンセルしてください。サーバーが自動で承認することはなく、操作を拒否します。

専用のキーリングは空の状態から始まります。gpg-mcp が既存の秘密鍵をコピーまたはエクスポートすることはありません。既存の鍵を再利用するには、別の方法で自分で移動するか、明示的な allowed_sign_keys/allowed_decrypt_keys の許可リストを設定して ~/.gnupg を引き続き使用してください。


設定

設定ファイルのパス:~/.config/gpg-mcp/config.toml、または --config、または GPG_MCP_CONFIG。

キーデフォルト意味
gnupg_home~/.local/share/gpg-mcp/gnupg分離されたキーリングです。0700 にする必要があります。
approvalclientclient(MCP エリシテーション)、local(zenity。ディスプレイが必要)、none(テスト専用)
require_approvalすべての高リスク操作承認が必要な操作
destructive_confirmationtrue破壊的操作の際に入力するフィンガープリントの末尾です。require_approval とは独立しています
allow_test_modefalseサービス実行時に approval = "none" を使用するために必要です
audit_requiredtrue監査台帳に書き込めない場合、高リスク操作を失敗させます
allowed_sign_keys[]署名を許可する完全なフィンガープリントです。空の場合、専用キーリングではすべて、~/.gnupg ではなしを意味します
allowed_decrypt_keys[]復号についても同じルールです
allowed_recipients[]暗号化で使用できる宛先のオプションの許可リストです
enable_networkfalseキーサーバーの検索/取得/送信
enable_symmetricfalse共通鍵暗号方式による暗号化/復号
allow_unprotected_keysfalseprotect=false での鍵の作成を許可します(テスト用キーリングのみ)
allow_hidden_recipientsfalse宛先非表示メッセージの復号を許可します
max_input_bytes10485760入力の上限
max_output_bytes20971520出力の上限。ステータスファイルの上限は max(1 MiB, this value) です
timeout_s120操作ごとのタイムアウト
keygen_timeout_s300鍵生成/パスフレーズ変更のタイムアウト
keyserverhkps://keys.openpgp.org設定ファイルのみで指定可能です。hkps:// または https:// のみ
audit_log~/.local/share/gpg-mcp/audit.jsonl追記専用の JSONL、0600

環境変数による上書き:GPG_MCP_CONFIG、GPG_MCP_HOME、GPG_MCP_APPROVAL、 GPG_MCP_ENABLE_NETWORK、GPG_MCP_ENABLE_SYMMETRIC、GPG_MCP_AUDIT、 GPG_MCP_ALLOW_TEST_MODE、GPG_MCP_AUDIT_REQUIRED。


ツール

読み取り専用:

ツール目的
list_keys公開鍵または秘密鍵のメタデータを一覧表示します(秘密鍵の実体は決して表示しません)
get_key1 つのフィンガープリントの公開メタデータをすべて表示します
export_public_keyASCII 装甲形式またはバイナリ形式の公開鍵
export_ssh_key認証用サブキーの OpenSSH 公開鍵
inspectインポートせずに OpenPGP パケット/鍵を検査します。秘密鍵は拒否されます
inspect_recipients復号せずに暗号文の宛先を表示します
verify分離署名、クリアテキスト署名、またはインライン署名を検証します
card_statusOpenPGP スマートカードのステータス
agent_infogpg のバージョン、ソケット、エージェントのキャッシュオプション
doctorバイナリ、キーリング、ポリシーの健全性チェック

暗号処理:

ツール目的
sign分離署名、クリアテキスト署名、またはインライン署名
encrypt宛先の完全なフィンガープリントを指定して暗号化します
sign_and_encrypt署名して暗号化します
decrypt許可リストに登録された鍵を使って公開鍵暗号文またはハイブリッド暗号文を復号します。対称鍵のみの入力には symmetric_decrypt を使用する必要があります
symmetric_encrypt / symmetric_decryptパスフレーズによる対称暗号化(オプトイン)

鍵管理:

ツール目的
create_key鍵を作成します。パスフレーズは pinentry を介して指定します
add_subkey、add_uid、set_expiry鍵を変更します
change_passphrase古いパスフレーズと新しいパスフレーズを pinentry を介して指定します
import_public_key公開鍵のデータをインポートします。秘密鍵パケットと失効署名は拒否されます
delete_key公開鍵、または秘密鍵と公開鍵を削除します。確認の入力が必要です
set_ownertrustnever/marginal/full を設定します。ultimate は CLI 専用です
generate_revocation保存済みの失効証明書を検証して返します
import_revocation一時的なキーリングで検証します。apply=false は実際に適用しないドライランです
revoke_key保存済みの証明書を検証して適用します。確認の入力が必要です

ネットワーク(オプトイン):

ツール目的
search_keyserver設定されたキーサーバーを検索します
fetch_key公開鍵を取得してインポートします。承認が必要で、インポートしたフィンガープリントを報告します
send_key公開鍵を公開します
意図的に含めていない機能
  • export_secret_key/秘密鍵のバックアップ。
  • run_gpg/生の argv の受け渡し。
  • パスフレーズのパラメーター。
  • ツールからの --homedir の指定。
  • 呼び出しごとの任意のキーサーバー URL。
  • --edit-key の対話型メニュー。
  • ユーザー入力からの --trust-model の指定。

承認モード

client(デフォルト)

サーバーは MCP クライアントに承認フォームの表示を要求します。フォームには、操作、鍵の完全なフィンガープリントと ID、ペイロードサイズ、SHA-256、短いプレビューが含まれます。MCP の リゾルバー として実装されているため、旧バージョンと現行バージョンの両方のプロトコルで動作します。

クライアントがエリシテーションのサポートを宣言していない場合(たとえば、一部の CLI クライアント)、サーバーはローカルの zenity ダイアログにフォールバックします。これも人間による承認ゲートであり、MCP クライアントとは独立しています。エリシテーションも安全なローカルダイアログも利用できない場合、呼び出しは approval_unavailable エラーで安全側に失敗し、自動承認されることはありません。

複合操作では、構成要素のいずれかが承認を必要とする場合に承認が必要です。sign_and_encrypt は sign と encrypt の両方を引き継ぎます。また、encrypt(..., sign_with=...) も sign を引き継ぎます。そのため、require_approval = ["sign"] をカスタム設定すると、署名付き暗号化にも引き続き承認が必要になり、require_approval = ["encrypt"] を設定すると、sign_and_encrypt にも引き続き承認が必要になります。

破壊的操作では、destructive_confirmation = true(デフォルト)の場合、操作が require_approval から削除されていても、フィンガープリント末尾の文字列を入力する必要があります。これを false に設定すると、入力による確認だけが不要になります。操作が require_approval に残っている場合、承認は引き続き必要です。approval = "none" は、使い捨てのテスト用キーリングに限り、どちらも回避します。

失効のインポートでは、承認フォームに、引数として渡されたフィンガープリントだけでなく、証明書自体から導出された ID が表示されます。異なる鍵の証明書は、承認が要求される前に拒否されます。

local

サーバーはzenityを使用します(ディスプレイが利用できない場合はフェイルクローズします)。これはMCPクライアントから独立しており、クライアントを完全には信頼できない場合に適しています。破壊的な操作では、フィンガープリントの末尾を入力するために、2つ目のzenity --entryプロンプトを使用します。

none

使い捨てのテスト用キーリングでのみ使用してください。allow_test_mode = true(またはGPG_MCP_ALLOW_TEST_MODE=1)を設定し、かつ専用のGNUPGHOMEを構成しない限り、serveはこのモードを拒否します。監査台帳にはdecision: skippedが記録されます。実際の鍵では決して有効にしないでください。


キーリングの分離

gpg-mcp initは専用のキーリングを使用します。これにより、次のことが可能になります。

  • 普段のGnuPGの使用時とは別のgpg-agentキャッシュを使用できます。
  • 空の許可リストが「このキーリングのみ」を意味するポリシー境界を設けられます。
  • テスト用の鍵やエージェント専用の鍵を安全に保管できます。

専用のキーリングは、同じOSユーザーに対するセキュリティ境界ではありません。そのための方法については、以下を参照してください。


より強力な分離

OSユーザーの分離(ソフトウェア)

キーリングを所有する別のユーザーとして署名処理を実行し、MCPサーバーには限定されたUnixソケットのみを公開します。エージェントのユーザーは秘密鍵を読み取ることも、エージェントソケットに接続することもできません。これはソフトウェアのみで実現できる最も強力な設計であり、自然な次のステップです。現行リリースでは、簡潔さを優先して同一ユーザーモデルを採用しています。

ハードウェアトークン(価値の高い鍵に推奨)

秘密鍵をOpenPGPスマートカードまたはYubiKeyに保存します。鍵がディスク上に存在することはなく、署名ごとにPINと物理的なタッチを要求できます。gpg-mcpは変更なしで動作します。card_statusはカードとその鍵を報告し、list_keysは秘密鍵のメタデータを返します。カード上での鍵の生成は、gpg --edit-cardを使って別途行います。

systemdの強化

サーバーをサービスとして実行する場合は、最低限、次の設定を行ってください。

NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=read-only
ReadWritePaths=%h/.local/share/gpg-mcp
RestrictAddressFamilies=AF_UNIX

また、ユーザーを分離する設計では、専用ユーザーとして実行してください。


監査台帳

すべての高リスク操作で、audit.jsonlに1つのJSONオブジェクトが追記されます。

{"ts":"2026-10-24T20:00:00Z","event":"operation","phase":"outcome","tool":"sign",
 "fingerprint":"F759...E793","mode":"detached",
 "payload_sha256":"...","size":42,"result":"ok"}

台帳には、平文、ペイロードのプレビュー、パスフレーズ、秘密鍵の内容は一切含まれません。承認の要約は人間向けに表示されますが、台帳には書き込まれません。このファイルは追記専用で、モードは0600です。書き込みのたびに、既存の監査ファイルをfstatで検査します。通常ファイル以外のファイル、および別のユーザーが所有するファイルは拒否されます。また、グループまたはその他のユーザーにアクセス権がある既存ファイルは、fchmodで0600に制限されます。gpg-mcpが権限を制限するのは、自身が作成した監査ディレクトリのみです。/tmpのような既存の任意の親ディレクトリに対してchmodを実行することはありません。

audit_required = true(デフォルト)の場合、監査エントリを書き込めなければ高リスク操作は失敗します。audit_required = falseに設定するのは、使い捨てのテスト用キーリングで使用する場合に限ってください。記録にはphaseが付与されます。approval/intentは実行前に、outcomeは実行後に書き込まれます。outcomeの追記に失敗した場合、操作がすでに完了している可能性があることを明示するエラーが返されます。操作は再試行されません。同じOSユーザーに対して、この台帳が改ざんを防止するわけではありません。


テスト

uv run pytest            # never prompts; uses an ephemeral keyring
uv run ruff check .

# Optional: the two operations that intentionally need a human at pinentry
GPG_MCP_INTERACTIVE=1 uv run pytest tests/test_interactive.py -s

デフォルトのテストスイートでは、一時的なキーリングで pinentry-program /bin/false を使用するため、予期しないプロンプトが表示されるとブロックされずにテストが失敗します。一時的なキーリングを作成し、実際の gpg 操作を実行します。特に、次の点を検証します。

  • 応答に PRIVATE KEY BLOCK が含まれないこと。
  • コマンドラインに禁止されたオプションやパスフレーズが含まれないこと。
  • 秘密鍵のインポートと秘密鍵の失効証明書のインポートが拒否されること。
  • デフォルトのポリシーで、import_revocation、revoke_key、delete_key に承認と入力による確認が必須であること。
  • 複合操作が、構成要素の承認要件を引き継ぐこと。
  • 失効処理のドライランで実際のキーリングが変更されず、別の鍵の証明書が拒否されること。
  • 有効期限切れの署名、有効期限切れの鍵、失効した鍵、公開鍵が見つからない場合は、いずれもポリシー上許可されないこと。
  • 埋め込み署名が複数ある場合、正常/不正の順序を問わずフェイルクローズすること。
  • fetch_key が書き込み操作として登録され、承認が必須であること。
  • 複数行または双方向テキストを含む UID が承認ダイアログでエスケープされ、承認前に検証されること。
  • 既存の 0644 の監査ファイルが 0600 に変更される一方、シンボリックリンクと FIFO は拒否されること。
  • 操作を require_approval から削除しても、破壊的操作の確認が引き続き必須であること。
  • 失効証明書を import_public_key 経由で失効に使用できないこと。
  • 実際の DECRYPTION_KEY が許可リストに登録されている必要があること。
  • 設定された上限を超えるステータス出力でフェイルクローズすること。
  • 悪意のある gpg.conf が無視されること。
  • 対称鍵のみの入力は decrypt で拒否され、ハイブリッド入力は許可リストに登録された公開鍵を通じて復号に成功すること。
  • symmetric_decrypt のみを制限するカスタムポリシーを decrypt 経由で回避できないこと。
  • 設定ファイルの祖先ディレクトリが安全にたどられ、sticky ビットのない書き込み可能な祖先ディレクトリが拒否されること。
  • init がシンボリックリンクされた gpg-agent.conf を拒否し、リンク先が存在しない設定ファイルのシンボリックリンクによってリンク先が作成されないこと。
  • 監査パスで、sticky ビットのない書き込み可能な祖先ディレクトリが拒否されること。
  • 複数署名のクリアテキスト、インライン、埋め込みメッセージが正しく列挙・集約されること。
  • ハイブリッド復号では、回復可能な対称鍵パスフレーズの失敗パターンのみが許容されること。
  • 対称鍵復号では、説明のつかないゼロ以外の終了コードが拒否され、verify=false の場合に限り、認識済みの署名エラーが許容されること。
  • 設定ファイル、キーリング、監査ディレクトリの作成時に、シンボリックリンクされた祖先ディレクトリ経由で書き込まれないこと。
  • サーバー起動、doctor、init の時点で、シンボリックリンクされたキーリングパスと書き込み可能なキーリングの祖先ディレクトリが拒否されること。
  • 無効なセキュアウォークパスによってディレクトリ記述子が漏えいしないこと。
  • 複数署名が --proc-all-sigs の有無を問わず列挙され、フェイルクローズすること。
  • ハイブリッド方式の対称鍵/公開鍵暗号文が symmetric_decrypt で拒否されること。
  • 監査の短い書き込み、意図/結果の各フェーズ、結果の失敗が適切に処理されること。
  • リンク先が存在しない設定ファイルのシンボリックリンクと安全でない設定ファイルの親ディレクトリが拒否されること。
  • 大きなメモリ割り当ての前に、マルチバイト UTF-8 がバイト数制限を超えること。
  • 安全でない設定ファイル、不明な設定キー、暗黙の approval="none" が拒否されること。
  • audit_required=true の場合、安全でない監査ファイルでエラーが発生すること。
  • 鍵生成の組み合わせが検証され、一部のみのインポートが分類されること。
  • ツールレジストリが、公開されているすべてのツールの読み取り/書き込みアノテーションと一致すること。
  • 別の鍵宛ての暗号文と、非表示/表示の受信者が混在した暗号文の復号が拒否されること。
  • 監査台帳にペイロードのプレビューが含まれず、既存のディレクトリのモードが変更されないこと。
  • 安全でない zenity/バイナリの権限が拒否されること。
  • オプションインジェクションの試行が検証に失敗すること。

CI では、GnuPG をインストールした環境で Python 3.11、3.12、3.13 を使用し、ruff と pytest を実行します(.github/workflows/ci.yml)。 main は保護されており、3 つすべての CI ジョブに合格する必要があります。直接のプッシュは拒否されます。


制限事項

  • テキストおよび Base64 の入力には上限があります。大きなファイルは別の方法で処理してください。
  • キーサーバーの検索結果は、人が読めるテキストであり、構造化されたリストではありません。
  • 失効には、キーの作成時に生成された証明書を使用します。見つからない場合は、別の方法で gpg --gen-revoke を使用して生成してください。対象のキーは設定済みの キーリングにすでに存在している必要があります。不明なキーの失効証明書は拒否されます。import_revocation は 主キー全体の失効を処理します。サブキーや UID の選択的な失効には対応していません。
  • スマートカードのキー生成と PIN 管理は、意図的に対象外としています。
  • approval = "client" は、クライアントが入力要求フォームを適切に表示することを前提としています。クライアントが入力要求を行えない場合、承認は検証済みのローカルな zenity ダイアログにフォールバックします。
  • Linux/Unix のみ対応です。実装は Unix の権限、os.getuid、POSIX プロセスグループ、 および zenity に依存しており、Windows はサポートされていません。
  • generate_revocation は、失効に使用できる証明書を呼び出し元に返します。結果は 機密情報として扱い、オフラインで保管してください。承認プロンプトで影響について説明します。
  • --proc-all-sigs に対応していない GnuPG バージョンでは、クリアテキスト、インライン、および埋め込み署名の列挙が、最初の不正な署名で停止する場合があります。それでも結果は拒否されます。分離署名では、パケットごとのフォールバックを使用します。

ライセンス

MIT。LICENSE を参照してください。

コメント

MCP は初めてですか?

プロトコルの概要から最初のサーバーの導入まで、よくある疑問にまとめて答えます。

AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。