enpass-mcp について
enpass-mcp は、AI アシスタントが Enpass の項目にアクセスできるローカル MCP サーバーです。保管庫ファイルとマスターパスワードは端末内に保ち、通常は読み取り専用で、書き込みは明示的に有効化した場合に限られます。
主な機能
- 01OS のキーチェーンに保存したパスワードで保管庫を解除
- 02パスワードを表示せず保管庫と項目を検索
- 03要求に応じて項目のフィールド・パスワード・TOTP コードを取得
- 04添付ファイルの一覧表示と復号
- 05Enpass フォルダー同期状態の確認
- 06書き込みツールを初期状態で無効化
活用シーン
- 01検索語でログイン情報などの Enpass 項目を探す
- 02要求に応じてパスワードと現在の 2FA コードを取得
- 03保管庫の添付ファイルをディスクにエクスポート
- 04同期状態を確認し、必要に応じて変更機能を有効化
MCP 対応
stdio 経由で MCP クライアントと通信し、保管庫、項目、秘密情報、添付ファイル、同期状態のツールを公開します。解除時にマスターパスワードを引数として受け取らず、OS のキーチェーンから読み取ります。書き込みツールは明示的な有効化が必要です。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
enpass-mcp
Model Context Protocol(MCP)サーバーです。AI アシスタントに、Enpass のパスワード保管庫への制御されたローカルアクセスを提供します。保管庫のロック解除、保管庫の一覧表示、エントリーの一覧表示と読み取りができます。エントリーの作成と削除も可能ですが、有効にするまで無効になっています。
stdio 経由でローカルに動作します。Enpass の保管庫がマシンの外に出ることはなく、マスターパスワードがモデルに渡されることもありません。マスターパスワードはオペレーティングシステムのキーチェーンに保存され、サーバーが直接読み取ります。
安全性について
- マスターパスワードは OS のキーチェーン(macOS Keychain、Windows Credential Manager、Linux Secret Service)に保存されます。設定ファイルや環境変数には保存されず、ツールの引数として渡されることもありません。
unlock_vaultツールには意図的にパスワード引数がありません。そのため、パスワードがモデルのコンテキストやログに含まれることはありません。 - 保管庫はローカルに保持されます。 サーバーは暗号化された
vault.enpassdbファイルを SQLCipher で直接読み取ります。どこかにアップロードされることはありません。 - 読み取りは明示的に行われます。 エントリーの一覧表示でパスワードが返されることはありません。シークレットは、明示的に要求した場合にのみ
get_item/get_passwordによって返されます。 - 指定がない限り読み取り専用です。 初期状態では、サーバーは何も変更できません。書き込みツールは公開すらされません。
ENPASS_MCP_ALLOW_WRITES=1を設定すると有効になります(書き込みのオプトインを参照)。
エントリーのパスワードは、要求すると設計上アシスタントに返されます。そのため、信頼できるアシスタントと保管庫にのみ接続してください。
必要条件
- Node.js 18 以降
- Enpass 6 / 7 / 8 の保管庫(SQLCipher 形式の
vault.enpassdb) - Linux の場合:パスワード保存用の Secret Service プロバイダー(GNOME Keyring または KWallet)
ネイティブ依存関係(better-sqlite3-multiple-ciphers、@napi-rs/keyring)には一般的なプラットフォーム向けのビルド済みバイナリが含まれているため、通常はコンパイラーは不要です。
インストール
git clone https://github.com/bitterdev/enpass-mcp.git
cd enpass-mcp
npm install
npm link # optional: makes the `enpass-mcp` command available globally
保管庫の登録(ターミナルで一度だけ実行してください)
これはマスターパスワードをモデルから遠ざけるための安全な手順です。ご自身で実行してください。パスワードは非表示の入力プロンプトに入力され、OS のキーチェーンに保存されます。
# Find your vault files automatically
enpass-mcp discover
# Register a vault (you will be prompted for the master password)
enpass-mcp add-vault personal --path "/Users/you/Documents/Enpass/Vaults/primary/vault.enpassdb"
enpass-mcp add-vault work --path "/path/to/work/vault.enpassdb"
# With a keyfile
enpass-mcp add-vault personal --path "/path/vault.enpassdb" --keyfile "/path/vault.keyfile"
# Manage
enpass-mcp list-vaults
enpass-mcp test-unlock personal
enpass-mcp remove-vault work
add-vault は、保存前にパスワードで実際に保管庫のロックを解除できることを確認します。
保管庫ファイルは通常、次の場所にあります。
| OS | 一般的な場所 |
|---|---|
| macOS | ~/Documents/Enpass/Vaults/<vault>/vault.enpassdb |
| Windows | %USERPROFILE%\Documents\Enpass\Vaults\<vault>\vault.enpassdb |
| Linux | ~/Documents/Enpass/Vaults/<vault>/vault.enpassdb |
Dropbox / OneDrive / WebDAV 経由で同期する場合は、同期されたコピーを --path に指定してください。
アシスタントへの接続
このサーバーは stdio 経由で MCP を使用します。MCP クライアントで enpass-mcp serve を指定してください。
Claude Desktop(claude_desktop_config.json):
{
"mcpServers": {
"enpass": {
"command": "enpass-mcp",
"args": ["serve"]
}
}
}
npm link を実行していない場合は、代わりに絶対パスを使用してください。
{
"mcpServers": {
"enpass": {
"command": "node",
"args": ["/absolute/path/to/enpass-mcp/src/cli.js", "serve"]
}
}
}
Claude Code:
claude mcp add enpass -- enpass-mcp serve
ツール
| ツール | 説明 |
|---|---|
list_vaults | 登録済みの vault、そのファイルが存在するか、パスワードが保存されているか、ロック解除されているかを一覧表示します。 |
unlock_vault | OS のキーチェーンにあるマスターパスワードを使って vault のロックを解除します。vault 名のみを受け取り、パスワードは受け取りません。 |
lock_vault | vault をロックし、メモリから導出キーを消去します。 |
list_items | エントリ(タイトル、ユーザー名、URL)を一覧表示します。パスワードは返しません。query、category、folder、limit に対応しています。 |
get_item | すべてのフィールド値(パスワード、TOTP など)と添付ファイルの一覧を含む、エントリ全体を返します。 |
get_password | エントリのパスワードと、設定されている場合は現在の TOTP コードを返します。 |
get_otp | エントリの現在の TOTP/2FA ワンタイムコードと、コードが切り替わるまでの秒数を生成します。 |
list_attachments | エントリのファイル添付(名前、サイズ、MIME)を一覧表示します。 |
export_attachment | 添付ファイルを復号し、ディスクに書き込んでパスを返します(小さなファイルの場合はインラインで base64 を返します)。 |
sync_status | Enpass フォルダー同期を使用する vault と、同期フォルダー内のコピーのほうが新しいかどうかを一覧表示します。 |
ENPASS_MCP_ALLOW_WRITES=1 を設定すると、さらに 3 つのツールが表示されます(書き込みのオプトインを参照)。
| ツール | 説明 |
|---|---|
create_item | カスタムフィールドを含むエントリを作成します。機密値は Enpass と同じ方法で暗号化されます。 |
delete_item | エントリを削除するか、ゴミ箱に移動します。削除が同期されるよう、Enpass が使用する tombstone を残します。 |
sync_pull | ローカル vault をバックアップした後、同期フォルダーにある新しいコピーを取り込みます。 |
list_items/get_item はログイン情報だけでなく、すべての Enpass エントリタイプ(ログイン、クレジットカード、安全なメモ、ID 情報など)に対応しており、すべてのフィールドを返します。
一般的なアシスタントのフロー:list_vaults → unlock_vault → list_items → get_password。
仕組み
Enpass は各 vault を標準的な SQLCipher データベース(vault.enpassdb)として保存します。生の暗号化キーは、マスターパスワード(オプションでキーファイルと組み合わせ)とファイル先頭の 16 バイトのソルトから導出されます。
- PBKDF2-HMAC-SHA512 を 100000 回(古い vault)または 320000 回(新しい vault)反復し、最初の 32 バイトを生の SQLCipher キーとして使用します
cipher_compatibility4(Enpass 6.8 以降)または 3(古い vault)で開きます
サーバーはこれらの組み合わせを自動的に試すため、Enpass の各バージョンの vault で動作します。導出キーはサーバープロセスの実行中のみメモリに保持され、ディスクに書き込まれることも、モデルに返されることもありません。
参考資料:Enpass Security Whitepaper、 hazcod/enpass-cli。
アイテムごとのフィールド暗号化
Enpass は「機密」として指定された値をそれぞれ、SQLCipher の下層で、vault ではなくエントリに属するキーを使ってもう一度暗号化します。この暗号化層が適用されているフィールドでは、itemfield.algo_version = 1 となります。
| 要素 | 場所 | 形式 |
|---|---|---|
| キーと nonce | item.key | 44 バイト:32 バイトの AES-256 キーと、それに続く 12 バイトの GCM nonce |
| 値 | itemfield.value | ciphertext || 16-byte GCM tag の 16 進数表現 |
| 追加データ | エントリの uuid | ハイフンを除去し、16 バイトの生データに 16 進デコード |
AAD をエントリの uuid にバインドすることで、値を別のエントリにコピーしても使用できないようにしています。Enpass はこの暗号化層を導入した際、既存のエントリを再暗号化しませんでした。そのため、同じ algo_version のもとで暗号文と平文が混在する vault もあります。値が暗号化されていると判断されるのは、ペイロードの形式(純粋な 16 進数、バイト単位で完全、タグ単体より長い)を満たす場合に限られます。
暗号化されているように見えるものの認証に失敗した値は、decryptionFailed: true を付けて null として返され、生の列の内容が返されることはありません。保存された暗号文はもっともらしい文字列に見えるため、それを返すと誤ったシークレットを本物であるかのように、気付かないまま渡してしまう可能性があります。
2 要素認証コード(TOTP)
ワンタイムパスワードのシークレット(Enpass では otpauth:// URI として保存されます)があるエントリーでは、現在有効な 2FA コードを生成できます。get_otp は現在の 6 桁のコードと、次のコードに切り替わるまでの秒数を返します。また、get_password はパスワードとあわせて現在のコードを返します。これにより、アシスタントはパスワードと 2FA プロンプトの両方を入力できます。
添付ファイル
Enpass ではファイル添付が暗号化されます。小さいファイル(最大 1 KB)はボルト内にインラインで保存され、大きいファイルはボルトと同じ場所にある別個の <uuid>.enpassattach SQLCipher ファイルに保存されます。各ファイルは、ボルトに保存された専用のキーで暗号化されます。export_attachment はどちらにも対応しています。ファイルを復号し、デフォルトではディスクに書き込んでパスを返すため、バイナリデータをモデルに渡さずに、あらゆるサイズのファイルを扱えます。
この形式には見落としやすい点が 2 つあり、実際のボルトで確認するまで、どちらもここでは誤っていました。
attachment.passwordはキーのデータではありません。完成した SQLCipher の raw-key 式x'<64 hex key chars><32 hex salt chars>'がテキストとして格納されており、そのまま渡す必要があります。これを 16 進エンコードすると SQLCipher が拒否するキーになり、すべての外部添付ファイルで「file is not a database」エラーが発生します。- 保存されているペイロードは、ファイルそのものではなく、base64 データ URI(
data:application/pdf;base64,...)であることがよくあるため、デコードが必要です。これらのバイト列をそのままディスクに書き込むと、.pdfという名前のテキストファイルになります。attachment.sizeは保存されたバイト数を数えるため、この形式で格納されたファイルでは、エクスポート後のファイルより大きくなります。
添付ファイルを復号できないボルトが見つかった場合は、attachment テーブルの(シークレットを含まない)スキーマを添えて issue を作成してください。
添付ファイルはフォルダー同期コンテナー内にも格納されません。Enpass は .enpassattach ファイルを、同期フォルダー内のボルトの隣に配置します。sync_pull はこのマシンにないファイルを取得し、書き込みを公開するときには、同期フォルダーにないローカルファイルをコピーします。どちらの方向でも、既存のファイルが上書きまたは削除されることはありません。
書き込み(オプトイン)
書き込みはデフォルトで無効になっています。パスワード保管庫は、モデルの判断だけでツールがデータを変更できるようにすべきではない場所です。そのため、サーバーは読み取り専用で起動し、書き込みを有効にするまで create_item、delete_item、add_attachment、sync_pull も一覧に表示しません。
ENPASS_MCP_ALLOW_WRITES=1
MCP クライアントの設定、または vaults.json と同じ場所にある .env で設定してください。それ以外は何も変わりません。どちらの場合も、読み取りはまったく同じように動作します。
書き込み中は Enpass を終了してください。 アプリはデータベースをメモリ上に保持しているため、変更が加えられると、キャッシュされた独自のコピーを上書きして書き戻す可能性があります。Enpass が起動中の場合、すべての書き込みツールは実行を拒否します。
以前のバージョンのこの README では、最近の保管庫(スキーマバージョン 6)ではエントリーを直接挿入すると Enpass がクラッシュするため、書き込みは不可能だと説明していました。クラッシュは実際に発生していましたが、原因の診断が誤っていました。Enpass 自体が書き込む内容から導き出した、次の 3 つの具体的なルールを守れば動作します。
- Enpass は
NULLを保存しません。 クラッシュは、null ポインターに対するstrlen内でのEXC_BAD_ACCESSです。INSERTで省略されたカラムはデフォルトでNULLになり、アプリがその値に対してstrlenを呼び出します。すべてのカラムに明示的に値を書き込み、NULLの代わりに空文字列を使います。 - テンプレートのフィールドセットは固定されています。
login.defaultには、ほとんどが空でも、常に同じ 9 つのフィールドが、同じ順序で、同じフィールド UID とともに含まれます。値があるフィールドだけを書き込むと、アプリが表示できないエントリーが作成されます。 - アイテムごとのキーは再現可能です。
item.keyは 32 バイトの AES-256 キーと 12 バイトの GCM ノンスで構成され、アイテム UUID を追加認証データとして、hex(ciphertext || tag)の形式で保存されます。Enpass の内部実装に依存する要素はないため、アイテムごとに新しいランダムキーを使っても問題ありません。
実際の保管庫を使って一連の処理を検証済みです。書き込み、読み戻し、復号して元の内容との一致を確認し、削除し、双方向に同期した後、Enpass がクラッシュせずに保管庫を開くことを確認しました。
ファイルの添付
add_attachment が受け取るのはパスであり、引数リスト内の base64 ではありません。バイト列は添付ファイル専用の暗号化データベースにそのまま保存されます。読み取りと同じフォーマットの詳細から、2 つのルールが導き出されます。どちらかを誤ると、保管庫内のすべてのバイトが正しくても、ファイルが破損しているように見えます。
- データ URI ではなく、生のバイト列を保存します。
data:;base64,...形式のペイロードは Enpass アプリからそのまま渡されるため、エクスポートされたファイルは.pdfや.jpegという名前のテキストファイルになります。add_attachmentはそのような入力を保存せず、拒否します。 - キーの式は変更せずに渡します。これはすでに ASCII の SQLCipher 生キー式であり、再度 16 進数にエンコードすると「file is not a database」というエラーになります。
行は、保管庫の attachment テーブルに実際に存在するカラムから構築します。カラムの構成は保管庫の世代によって異なります。また、Enpass に NULL が渡らないよう、すべてのカラムに明示的に値を設定します。
回帰テスト:npm test は 0x00 と不正な UTF-8 シーケンスを含むペイロードを書き込み、読み戻したうえで、バイト列が同一であり、エンコードされていない状態で保存されていることを確認します。
データ URI として保存された添付ファイルの修復
scripts/repair-data-uri-attachments.mjs は、そのようなペイロードをデコードして生のバイト列に戻します。--apply を指定しない限りドライランとして動作し、Enpass の起動中は実行を拒否します。また、書き込む前に、デコードしたペイロードがファイル名から推定されるファイルシグネチャと一致することを確認します。
外部添付ファイルのバイト列は、専用の .enpassattach ファイルに保存されます。また、フォルダー同期では、そのファイルのもう 1 つのコピーが同期フォルダーに保持されます。そのため、Enpass のコンテナ内の保管庫を修復しても、直るのは 1 台のマシンだけです。--sync-folders を使うと共有コピーも修復できます。このオプションが書き込むのは、ローカルマシンにすでにある内容とバイト単位で一致するようにデコードされるペイロードだけです。
設定
マスターパスワードは OS のキーチェーンに保存されます。秘密情報以外のデータ(保管庫の名前とパス)のみが、小さな vaults.json に保存されます。
- macOS:
~/Library/Application Support/enpass-mcp/vaults.json - Windows:
%APPDATA%\enpass-mcp\vaults.json - Linux:
~/.config/enpass-mcp/vaults.json
ENPASS_MCP_CONFIG_DIR でディレクトリを変更できます。
環境変数:
| 変数 | 効果 |
|---|---|
ENPASS_MCP_ALLOW_WRITES | 1、true、yes、または on を設定すると、書き込みツールが有効になります。未設定を含め、それ以外の場合はサーバーが読み取り専用になります。 |
ENPASS_MCP_CONFIG_DIR | vaults.json と、任意の .env の保存場所です。 |
ENPASS_MASTER_PASSWORD | キーチェーンのエントリがない保管庫用の、任意のフォールバックマスターパスワードです。キーチェーンの使用を推奨します。 |
ENPASS_MASTER_PASSWORD_<VAULT> | 同じ設定を、特定の保管庫に適用します。 |
開発
npm test # runs against genuine SQLCipher fixtures in test/fixtures
# Rebuild the fixtures from scratch with real SQLCipher (vault + entries + attachments)
npm install --no-save @journeyapps/sqlcipher
npm run generate-fixtures
CI(GitHub Actions)は、実際の SQLCipher を使って保管庫をゼロから作成し、エントリと添付ファイルを追加してから、Node 18/20/22 で読み取り専用のテストスイート全体を実行します。
セキュリティに関する注意事項と制限
- この MCP サーバーに接続できる人は、保管庫のロックが解除されると、保管庫内のすべてのパスワードを読み取れます。信頼できるクライアントのみを接続してください。
- このサーバーは Enpass の同期、アイテムの履歴、またはゴミ箱機能を実装していません。
- このサーバーは読み取り専用で、保管庫を変更することはありません。最近の Enpass の保管庫では、データベースへの直接書き込みによってクラッシュが発生するため、エントリの作成や編集は意図的にサポートしていません(書き込みをサポートしない理由を参照)。
- このプロジェクトは独立したもので、Enpass とは提携しておらず、Enpass による承認も受けていません。
ライセンス
MIT © Fabian Bitter
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。