mcpField
S
sealkeep

sealkeep

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

sealkeep について

sealkeepは、AIエージェント向けにシークレットを管理します。名前で指定した値をコマンド環境に渡し、出力から伏せ字にします。CLI、MCPサーバー、ガードフックを備えています。

主な機能

  1. 01コマンドへのシークレット注入
  2. 02コマンド出力のシークレット伏せ字化
  3. 03OSキーチェーンやVaultへの保存
  4. 04シークレットファイルのスキャンと取り込み
  5. 05値を表示する呼び出しの遮断

活用シーン

  1. 01APIキーを必要とするエージェントコマンドの実行
  2. 02.envやINIファイルからの認証情報移行
  3. 03エージェントの会話履歴へのシークレット混入防止

MCP 対応

`sealkeep mcp`サーバーは、`list_secrets`、`run_with_secrets`、`store_status`ツールを提供します。どのツールもシークレットの値を返しません。

設定

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

mcp.json · 共通設定
{
"mcpServers": {
"munhq-sealkeep": {
"command": "npx",
"args": [
"-y",
"@munhq/sealkeep"
],
"env": {
"SEALKEEP_CONFIG": "<SEALKEEP_CONFIG>"
}
}
}
}
起動コマンドnpx -y @munhq/sealkeep
設定が必要な環境変数
SEALKEEP_CONFIGPath of the config file (stores, aliases, guard rules). Default: the config folder of the OS. With no file, sealkeep uses the OS keyring.

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

パッケージ
npm@munhq/sealkeep0.5.0

ツール

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

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

詳細

sealkeep:エージェントはキーを使いますが、そのキーを見ることはありません

npm MCP registry CI Smithery MIT

Cursor にインストール VS Code にインストール

sealkeep

sealkeep を使うと、AI エージェントは秘密情報を見ることなく利用できます。

各秘密情報を shared/stripe/test/SECRET_KEY のような名前で、一度だけ保存します。エージェントは sealkeep list で名前を確認し、その名前を使ってコマンドを実行します。値を読み取ることはなく、値を尋ねる必要もありません。

エージェントは名前を指定して秘密情報を要求します。sealkeep は値を1つのコマンドの環境変数に設定してそのコマンドを実行し、すべての出力で値を [sealkeep:NAME] に置き換えます。値がコンテキスト、トランスクリプト、ファイルに入ることはありません。

agent ──► sealkeep run OPENROUTER_API_KEY -- sh -c 'curl -H "Authorization: Bearer $OPENROUTER_API_KEY" …'
              │
              ├─ reads the value from a store ──► OS keyring  (macOS Keychain, Secret Service, Windows Credential Manager)
              │                               └─► Vault KV v2 (a replica)
              ├─ starts the command with the value in its environment
              └─ redacts the value from stdout and stderr ──► agent sees [sealkeep:OPENROUTER_API_KEY]

以下の4つの要素で構成されています。

  1. CLI(sealkeep):set、list、run、import、scan、sync、エイリアス、およびストアコマンドを備えています。
  2. MCP サーバー(sealkeep mcp):list_secrets、run_with_secrets、store_status ツールを提供します。どのツールも値を返しません。
  3. ガードフック(sealkeep guard):秘密情報を出力するツール呼び出し(たとえば cat .env や sealkeep get)を拒否します。
  4. エージェントに CLI の使用タイミングと使用方法を伝えるスキル。

インストール

MCP サーバーのみを利用する場合(任意のクライアント)、コマンドは npx -y @munhq/sealkeep です。

{ "mcpServers": { "sealkeep": { "command": "npx", "args": ["-y", "@munhq/sealkeep"] } } }

Claude Code では、プラグインによって MCP サーバー、スキル、ガードフックが一度に追加されます。

/plugin marketplace add munhq/sealkeep
/plugin install sealkeep@sealkeep

以下のフルインストール手順では、Claude Code、Codex、Cursor に同じものをインストールします。

Linux および macOS:

curl -fsSL https://raw.githubusercontent.com/munhq/sealkeep/main/install.sh | sh

このスクリプトは最新リリースのバイナリをダウンロードして SHA256SUMS と照合し、~/.local/bin にコピーした後、sealkeep install を実行します。

Rust を使用する場合:

cargo install --locked --git https://github.com/munhq/sealkeep
sealkeep install

sealkeep install はマシン上の AI クライアントを検出します。各クライアントにスキル、MCP サーバー、ガードフックを追加します。

クライアントスキルMCP サーバーガードフック
Claude Code(各設定フォルダー)<config>/skills/sealkeepclaude mcp add --scope user<config>/settings.json、Bash、Read、Grep の PreToolUse
Codex$CODEX_HOME/skills/sealkeepcodex mcp add$CODEX_HOME/hooks.json、PreToolUse(/hooks で一度承認してください)
Cursor~/.cursor/skills/sealkeep~/.cursor/mcp.json~/.cursor/hooks.json、beforeShellExecution

オプション:--client claude,codex を指定すると、指定したクライアントにのみインストールします。--dry-run はインストール計画を表示します。--no-skills、--no-mcp、--no-hooks を指定すると、該当する要素を省略します。sealkeep は JSON ファイルを変更する前に、バックアップ(<file>.bak-<unix time>)を作成します。sealkeep uninstall は install で追加したものを削除します。

sealkeep doctor を実行すると、ストアとクライアントを確認できます。

名前

名前の形式は <scope>/<project>/<env>/<KEY> です。

部分値例
scopeシークレットの所有者です。personal、雇用主またはクライアントの名前、あるいは複数のスコープで使うアカウントの場合は shared ですpersonal、acme、shared
projectリポジトリまたはサービスですexample-app、stripe、ovh
envprod、dev、test、local です。シークレットに環境がない場合(アカウントの API キーなど)は省略しますprod
KEYプログラムが読み取る環境変数ですDATABASE_URL

フォルダー名は小文字(a-z、0-9、.、_、-)です。キーは大文字(A-Z、0-9、_)で、run が設定する変数です。

personal/example-app/prod/DATABASE_URL
personal/example-app/dev/DATABASE_URL
personal/example-app/dev/STRIPE_SECRET_KEY   -> shared/stripe/test/SECRET_KEY   (alias)
acme/ovh/ovh-eu/APPLICATION_KEY
acme/cloudflare/API_TOKEN
shared/stripe/test/SECRET_KEY
shared/openrouter/API_KEY

1 つの値に 1 つの名前を付けます。 2 つのプロジェクトが同じアカウントを使う場合は、その値を shared/… に 1 回だけ保存し、各プロジェクトのフォルダーにエイリアスを作成します。これにより、プロジェクトのフォルダーに必要なすべての変数が揃い、ローテーション時には 1 つの値を変更するだけで済みます。

シークレットを保存する
sealkeep set shared/openrouter/API_KEY -d "OpenRouter, the main account"   # writes to every store

sealkeep は値の入力を 2 回求めます。入力内容は表示されません。値をパイプで渡すには、--stdin を使います。

some-password-tool show openrouter | sealkeep set shared/openrouter/API_KEY --stdin

マシン上のシークレットを見つけるには、scan を実行します。各 .env ファイルのパス、キー名、各キーの分類(secret、config、empty)、そして複数の場所にある値ごとのグループ番号が表示されます。値が表示されることはありません。また、認証情報が含まれていることの多いほかのファイルも、パスのみを一覧表示します。

sealkeep scan ~/code --max-depth 4

ファイルをフォルダーにコピーするには、次のようにします。

sealkeep import ../example-app/.env --to personal/example-app/dev \
  --map STRIPE_SECRET_KEY=shared/stripe/test/SECRET_KEY
sealkeep import ~/.ovh.conf --to acme/ovh            # INI: one folder for each section
sealkeep set personal/github/PAT --from-file ~/.github-token

import は dotenv ファイルと INI ファイル(.ini、.conf、AWS の credentials)を読み込みます。名前のみが表示されます。--map KEY=NAME は値を NAME に保存し、プロジェクトのキーをそのエイリアスにします。NAME にすでに別の値がある場合、import は処理を停止し、その旨を伝えます。インポート後は、元のファイルを削除するか、エージェントがアクセスできない場所に保管してください。

エージェントに使わせる

エージェントに指示します。スキルは、名前の確認には sealkeep list を、コマンドの実行には sealkeep run を使うよう指示します。

sealkeep run shared/openrouter/API_KEY -- sh -c 'curl -sS -H "Authorization: Bearer $API_KEY" https://openrouter.ai/api/v1/key'
sealkeep run --all personal/example-app/dev -- npm run dev
sealkeep run -e GITHUB_TOKEN=personal/github/PAT -- gh api user

名前を指定すると、そのキー名の変数が設定されます。--all FOLDER は .env ファイルと同じように、フォルダー内の各シークレットに対して変数を 1 つずつ設定します。--recursive はサブフォルダーも対象にします。この場合、同じキー名のシークレットが 2 つあるとエラーになります。-e VAR=NAME は別の名前の変数を設定します。STORE:NAME は 1 つのストアのみから読み込みます。

シークレットをファイルから読み取るツールでは、--dotenv を使うと、自分だけが読み取れる一時ファイルが作成されます。$XDG_RUNTIME_DIR/sealkeep が存在する場合、ファイルはその中に作成されます。sealkeep は、コマンド内の {dotenv} の位置にファイルのパスを渡し、コマンドの終了時にファイルを削除します。この例では、テストアカウントのログイン情報を Playwright MCP に渡します。エージェントは ADMIN_PASSWORD という名前を入力し、Playwright が値を設定します。

sealkeep run --dotenv personal/example-app/dev/ADMIN_EMAIL --dotenv personal/example-app/dev/ADMIN_PASSWORD \
  -- npx @playwright/mcp@latest --secrets {dotenv}

--secrets <path> は @playwright/mcp のオプションです(README を参照してください)。

自分で値を確認する
sealkeep get shared/openrouter/API_KEY

get が動作するのは、標準入力と標準出力が端末の場合だけです。エージェントは端末なしでコマンドを実行するため、get は拒否し、ガードフックも同様に拒否します。

ストア

sealkeep は、設定ファイルに記載された順にストアを検索し、単独の名前を探します。その名前を持つ最初のストアから値を取得します。

設定ファイルは、Linux では ~/.config/sealkeep/config.toml、macOS では ~/Library/Application Support/sealkeep/config.toml です。$SEALKEEP_CONFIG を使うと、別のパスを指定できます。設定ファイルがない場合、sealkeep は local という名前のキーチェーンストアを 1 つ使います。

[[store]]
name = "local"
kind = "keyring"

[[store]]
name = "vault"
kind = "vault"
address = "http://127.0.0.1:{port}"
mount = "agent"
auth = "kubernetes"
role = "sealkeep"
jwt_command = ["kubectl", "-n", "vault", "create", "token", "sealkeep", "--duration", "10m"]
port_forward = ["kubectl", "-n", "vault", "port-forward", "svc/vault", "{port}:8200"]

[aliases]
"personal/example-app/dev/STRIPE_SECRET_KEY" = "shared/stripe/test/SECRET_KEY"

[guard]
block_dotenv = true
deny = ["vault kv get", "ansible-vault view"]
OS のキーリング
OSストア
macOSログインキーチェーン
Linux, BSDセッション D-Bus 上の Secret Service(GNOME Keyring、KWallet)
Windows資格情報マネージャー

各シークレットは、サービスを sealkeep、アカウントをシークレット名とする 1 つのエントリーです。インデックスエントリー(__index__)には、名前と説明が保存されます。

Linux では、キーリングのロックを解除しておく必要があります。デスクトップセッションでは、ログイン時にロックが解除されます。デスクトップのないセッション(SSH、キーリングのパスワードを使わないログイン)ではキーリングがロックされ、ロック解除のプロンプトを表示できません。起動するたびに、次のコマンドを 1 回実行してください。

sealkeep unlock

ログインキーリングのパスワードを求められ、そのパスワードが gnome-keyring-daemon --unlock に渡されます。各キーリング呼び出しは最大 30 秒(SEALKEEP_KEYRING_TIMEOUT)待機するため、エージェントにはエラーが返され、呼び出しがハングすることはありません。

レプリカとしての Vault

Vault(または OpenBao)の KV v2 マウントには、別のマシンで使うため、またはバックアップ用にキーリングのコピーを保存できます。各フォルダーが 1 つの KV シークレットとなり、各キーがそのフィールドになります。たとえば、shared/stripe/test/SECRET_KEY は agent/shared/stripe/test の SECRET_KEY フィールドです。各シークレットの custom_metadata にはキーとその説明が記載されるため、list は値を読み取りません。

Kubernetes 内の Vault には、sealkeep はポートフォワードを使って Kubernetes API 経由で接続し、有効期間の短い ServiceAccount トークンでログインできます。その場合、マシンに Vault トークンを保存する必要はありません。

sealkeep store add-vault vault \
  --address 'http://127.0.0.1:{port}' --mount agent --auth kubernetes --role sealkeep \
  --jwt-command 'kubectl -n vault create token sealkeep --duration 10m' \
  --port-forward 'kubectl -n vault port-forward svc/vault {port}:8200'
sealkeep sync --from local --to vault   # one time, for the secrets that are already in the keyring

set、import、mv はすべてのストアに書き込みます(Vault ストアはフォルダーを含む名前のみを受け付けます)。そのため、ストア間で内容が同じ状態に保たれます。--store NAME を指定すると、1 つのストアに書き込みます。Vault 側には、KV v2 マウント、agent/data/* に対する create、read、update と、agent/metadata/* に対する read、list、update の権限を持つポリシー、および ServiceAccount に紐付けられた Kubernetes 認証ロールが必要です。--auth token を指定した場合、sealkeep は $VAULT_TOKEN、または sealkeep store token vault でキーリングに保存したトークンを読み取ります。

その他のシークレットマネージャー

以下はそれぞれストアの種類です。各ストアはベンダー公式の CLI を実行するため、ベンダー独自のサインイン方法(SSO、サービスアカウント、生体認証)が適用され、sealkeep はベンダーのトークンを保存しません。値は stdin 経由、または自分だけが読み取れるファイル経由で CLI に渡されます。ps で表示されるコマンド引数として渡されることはありません。

ストア追加方法レイアウト値の受け渡し方法
AWS Secrets Managersealkeep store add-aws aws --region eu-west-1各フォルダーにつき 1 つの JSON シークレット、sealkeep/<folder>--secret-string file://…
Google Secret Managersealkeep store add-gcp gcp --project acme-prod各名前につき 1 つのシークレット。名前はアノテーションに保存--data-file=-(stdin)
Azure Key Vaultsealkeep store add-azure azure --vault acme-kv各名前につき 1 つのシークレット。名前はタグに保存--file …
1Password(CLI 2.23+)sealkeep store add-1password op --vault Engineering各フォルダーにつき 1 つのセキュアノート、各キーにつき 1 つの非表示フィールドアイテムの JSON を stdin で渡す
Bitwarden / Vaultwardensealkeep store add-bitwarden bwsealkeep:<folder> というセキュアノート 1 つ、各キーにつき 1 つの非表示フィールドアイテムの JSON を stdin で渡す
OpenBaosealkeep store add-vault …Vault と同じVault と同じ

Google と Azure ではシークレット ID に使える文字が限られているため、ID は名前の / を -- に置き換え、短いハッシュを付けたものになります。実際の名前はアノテーションまたはタグに保存されます。Azure では削除したシークレットがソフト削除状態で保持され、後で同じ名前に対して set を実行すると復元されます。Bitwarden では、先にロックを解除してください。export BW_SESSION=$(bw unlock --raw)。Bitwarden Secrets Manager CLI(bws)では値をコマンド引数としてしか渡せないため、sealkeep はパスワードマネージャー CLI(bw)を使用します。

SSH キー

SSH エージェントは、パスフレーズ付きのキーをメモリ内にのみ保持します。再起動後は空になり、エージェントの git push は Permission denied (publickey) で失敗します。sealkeep はパスフレーズを保持し、キーを読み込みます。

sealkeep set personal/ssh/ID_ED25519_PASSPHRASE
sealkeep ssh-add ~/.ssh/id_ed25519 --passphrase personal/ssh/ID_ED25519_PASSPHRASE
sealkeep ssh-load      # unlock runs it too

ssh-load は sealkeep を SSH_ASKPASS プログラムとして ssh-add を実行します。askpass の処理では、親プロセスが ssh-add であり、1 回限りのトークンが一致した場合にのみ応答します。また、パスフレーズはストアから読み込まれるため、ファイルや出力に書き込まれることはありません。--agent はエージェントのソケットを指定します。デフォルトは $SSH_AUTH_SOCK です。

MCP

sealkeep mcp は stdio で次のツールを提供します。

ツール内容
list_secretsすべての名前、または 1 つの folder に含まれる名前、ストア、説明を返します。
run_with_secretsシェルを介さず、引数のリストである command を実行します。環境変数には folders と secrets を設定し、一時ファイルには dotenv を設定します。終了コード、stdout、stderr を返し、値はマスキングされます。制限時間はデフォルトで 120 秒、最大 900 秒です。各ストリームは 100 KiB で切り詰められます。
store_status各ストアを現在使用できるかどうかを返します。

ガードフック

このフックは次のツール呼び出しを拒否し、エージェントに sealkeep run を使うよう伝えます。

  1. $(…)、バッククォート、bash -c 内での使用を含む sealkeep get。
  2. sealkeep のキーチェーンエントリの読み取り:secret-tool lookup service sealkeep …、security find-generic-password -s sealkeep … -w、keyring get sealkeep …。
  3. block_dotenv が有効な場合、シェルコマンド、または Read と Grep ツールによる .env ファイルの読み取り。.env.example、.env.sample、.env.template、.env.dist は引き続き読み取り可能です。
  4. guard.deny にある各コマンドのプレフィックス。

Claude Code では、さらに 2 つの層が機能します。

  1. 出力ガード(sealkeep guard --after。Bash、Read、Grep 用の PostToolUse フック)。ツール呼び出し後、結果を保存済みシークレットの値と照合します。照合には run と同じ形式のマスキングを使います。結果に値が含まれている場合、エージェントが結果を読む前にフックがその値を [sealkeep:NAME] に置き換え、メモでシークレット名を示します。これにより、env > out.txt を実行してから out.txt を読み取る場合や、パスに glob や変数を使う場合も保護されます。ストアは最大 4 秒の制限で並行して読み込まれ、応答しないストアからは値を取得しません。Claude Code は元の出力を自身のテレメトリに記録します。
  2. 拒否ルール(settings.json の permissions.deny)。sealkeep install は Read(**/.env)、Read(**/.env.local)、Read(**/*.env) と、ほかの .env.* の名前に対するルールを追加します。Claude Code はパスに基づいてこれらのルールを確認するため、Read ツールと、Claude Code が認識するファイルコマンドは、シェルのトリックを使ってもファイルにアクセスできません。block_dotenv が有効な場合にインストール時にルールが追加され、sealkeep uninstall で削除されます。

sealkeep が保護するもの、保護しないもの

sealkeep はシークレットをエージェントのコンテキスト、トランスクリプト、プロジェクトのファイルに残さないようにします。使用のたびに監査ログ(Linux では ~/.local/share/sealkeep/audit.jsonl、または $SEALKEEP_AUDIT_LOG)に、名前とコマンドを記録します。値は記録しません。

マスキングでは、値そのもの、JSON エスケープ形式、パーセントエンコード形式、base64 形式の値を照合します。キー名にシークレットを示す語(KEY、TOKEN、SECRET、PASS、AUTH など)が含まれる場合、パスワード付きの URL の場合、または値が 16 文字以上の場合、その値はマスキングされます。PORT=3000 のような設定値は読み取り可能なままです。4 文字未満の値はマスキングされません。値を別の方法で変換するコマンド(たとえば、値のハッシュ化や一部の抽出)では、sealkeep が照合できない形式で出力されることがあります。

ユーザーとして任意のシェルコマンドを実行できるエージェントは、そのユーザーが読み取れるものを読み取れます。sealkeep はこの点を変えません。安全な方法を簡単に使えるようにし、値にアクセスする一般的な方法を拒否し、使用のたびに記録します。エージェントには、スコープを絞ったキーを渡してください。たとえば、制限付きの Stripe キー、支出上限付きの OpenRouter キー、ウェブログイン用のテストアカウントなどです。

ビルドとテスト

cargo build --release
cargo test --features test-store

test-store 機能は、テスト時に限り、OS のキーリングをファイルに置き換えます。リリース用バイナリには含まれません。

ライセンス

MIT

コメント

MCP は初めてですか?

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

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