MongoDB MCPを本番で使うときの読み取り専用設定
MongoDB MCPサーバーを本番クラスタに繋ぐ前提で、--readOnlyフラグ・IPアクセスリスト・DBユーザー権限を重ねる手順をまとめます。
MongoDB MCPサーバーの接続手順で動作確認を終えたら、本番クラスタに繋ぐ前に権限を絞り込みます。MDB_MCP_READ_ONLYの既定値はfalseで、何も指定しなければinsert-manyやdrop-collectionのような書き込み・削除ツールもそのまま登録されます。--readOnlyフラグ・接続元IPの制限・DBユーザー権限の3層を重ねておくと、どれか1つの設定ミスだけでは本番データに書き込みが届きません。
前提条件
この記事は接続手順の記事で解説した接続文字列またはAtlas APIサービスアカウントでの接続を前提にします。Atlasを使っている場合は、IPアクセスリストの操作にAtlas APIの認証情報が必要です。
--readOnlyで書き込み系ツールを非公開にする
readOnlyを有効にすると、operation typeが「read」「connect」「metadata」以外のツールはサーバー起動時に登録されません。create-collection・insert-many・update-many・delete-many・drop-collection・drop-database・drop-index・rename-collectionはすべて非公開になり、Claudeからは存在しないツールとして扱われます。
claude mcp add-json mongodb \
'{"command":"npx","args":["-y","mongodb-mcp-server@latest","--readOnly"],"env":{"MDB_MCP_CONNECTION_STRING":"mongodb+srv://readonly:pass@cluster.mongodb.net/myDatabase"}}' \
-s user環境変数で渡す場合はMDB_MCP_READ_ONLY=trueです。優先順位はコマンドライン引数が最も高く、次に環境変数、最後に設定ファイルの順になるため、両方を設定して食い違わせないようにします。
IPアクセスリストで接続元を絞る
Atlasクラスタは既定でIPアクセスリストに登録されたアドレスからしか接続を受け付けません。MCPサーバーを動かすマシンのIPが登録済みか、Atlas管理コンソールの「Network Access」で先に確認します。
Atlas APIサービスアカウントで接続している場合、atlas-inspect-access-listで現在の登録状況をClaudeに確認させ、atlas-create-access-listで追加できます。atlas-create-access-listは既定のconfirmationRequiredToolsに含まれるツールなので、elicitationに対応したクライアントでは実行前に確認が入ります。CI環境やヘッドレス実行のように確認プロンプトを挟めない場面では、事前にAtlas管理コンソールから手動で登録しておくほうが確実です。
DBユーザーの権限を絞る
--readOnlyはMCPサーバー内部でのツール公開範囲を絞るだけで、接続文字列に含まれるDBユーザーの権限そのものは変えません。接続文字列に管理者権限のユーザーをそのまま渡していれば、readOnlyの設定ミスや将来のアップデートでの挙動変化があったとき、権限の面では書き込みが通ってしまう状態が残ります。
Atlasでは、Project Access Managerからデータベースユーザーを作成する際にビルトインロールreadまたはreadAnyDatabaseを割り当てます。セルフホストのCommunity・Enterpriseでも同様に、db.createUser()でreadロールのみを持つ専用ユーザーを作成し、MCPサーバー専用の接続文字列として使います。管理者アカウントの使い回しは避けます。
Atlas APIを使うなら、サービスアカウントの権限も絞る
Atlas API経由でクラスタ一覧やパフォーマンスアドバイザーを使う場合、サービスアカウントに付与するロールも用途に応じて最小限にします。MongoDB公式が示す用途別の推奨ロールは次のとおりです。
| やりたいこと | 割り当てるロール(スコープ) |
|---|---|
| 組織・プロジェクトの一覧を見る | 割り当てるロール(スコープ)Org MemberまたはOrg Read Only(組織) |
| 新しいプロジェクトを作る | 割り当てるロール(スコープ)Org Project Creator(組織) |
| プロジェクト内のクラスタ・DBを見る | 割り当てるロール(スコープ)Project Read Only(プロジェクト) |
| クラスタを作成・管理する | 割り当てるロール(スコープ)Project Cluster Manager(プロジェクト) |
| アクセスリストを管理する | 割り当てるロール(スコープ)Project IP Access List Admin(プロジェクト) |
| データベースユーザーを管理する | 割り当てるロール(スコープ)Project Database Access Admin(プロジェクト) |
| Stream Processingリソースを管理する | 割り当てるロール(スコープ)Project Stream Processing Owner(プロジェクト) |
読み取り専用の分析用途であれば、Project Read Onlyだけで足ります。Organization Ownerのような組織全体に及ぶロールは、全プロジェクトの管理権限が必要な場合を除いて選ぶ理由はほとんどありません。
クエリ1回あたりの取得量に上限をかける
--readOnlyは書き込み系ツールを止めますが、読み取り系ツールが返すデータ量そのものは別の設定で制限します。maxDocumentsPerQueryとmaxBytesPerQueryは、findやaggregateが1回で返せる件数とバイト数の上限です。既定値はそれぞれ100件と16MBですが、コレクションが巨大な本番環境ではこの上限を意識して調整します。
{
"maxDocumentsPerQuery": 50,
"maxBytesPerQuery": 5242880,
"maxTimeMS": 10000
}maxTimeMSはクエリの実行時間そのものに上限をかける設定で、既定では未設定です。本番のプライマリノードに対して重いaggregateを走らせてしまうリスクを避けたいなら、数秒〜十数秒程度の上限を明示しておくと安全側に倒せます。
サーバーサイドJSと全件スキャンを塞ぐ
disableServerSideJsは既定値がtrueで、$where・$function・$accumulatorのようなサーバーサイドJavaScriptを使うクエリ演算子をあらかじめ禁止しています。これはreadOnlyを付けていなくても既定で有効な防御層で、任意コード実行に近いクエリをMCP経由で通さない設計です。意図的に無効化しない限り、この設定を追加で意識する必要はありません。
インデックスを使わない全件スキャンのクエリを止めたい場合はindexCheckを有効にします。
{
"indexCheck": true
}有効にすると、インデックスを使わないコレクションスキャンを伴うクエリはエラーになります。本番のプライマリに対して意図しないフルスキャンが実行され、レイテンシが跳ね上がる事故を防げます。読み取り専用の分析用途で、インデックス設計がまだ甘いコレクションに対して使うと、Claude自身が「インデックスがないから実行できない」と気づける状態になります。
ログとエクスポートファイルの置き場所を絞る
exportツールでEJSON形式のデータをエクスポートすると、その内容はexportsPath(既定は~/.mongodb/mongodb-mcp/exports)に一時ファイルとして書き出されます。本番データを扱う以上、この一時ファイルにも機密情報が含まれ得るため、書き込み・読み取り権限をMCPサーバーを実行するユーザーだけに絞っておきます。エクスポートは既定で5分後に期限切れとなり、2分ごとのクリーンアップで自動削除されます。
ログの出力先も同様です。diskロガーを使う場合、ログファイルはlogPath(既定は~/.mongodb/mongodb-mcp/.app-logs)に書き出されます。クエリ内容がログに残ることがあるため、chmod 600相当のアクセス制御をログディレクトリにもかけておくと安全です。外部にテレメトリを送りたくない場合は、MDB_MCP_TELEMETRY=disabledまたはDO_NOT_TRACK=1で無効化できます。
設定ファイル自体の権限も絞る
接続文字列やAPI認証情報をMDB_MCP_CONFIG環境変数経由でJSON設定ファイルから読み込む構成にしている場合、そのファイル自体のアクセス権限も本番運用では見落とせません。公式ドキュメントは、設定ファイルの所有者をMCPサーバーを実行するユーザーだけに絞ることを推奨しています。
chmod 600 /path/to/config.json
chown your-username /path/to/config.json同じサーバー上に複数ユーザーがいる環境では、この権限設定を怠ると、接続文字列に含まれるDBユーザーのパスワードやAtlasのAPIシークレットが他ユーザーから読める状態になります。コマンドライン引数に認証情報を書かないという方針と同様、設定ファイルという「もう1つの平文の置き場所」にも同じ注意が必要です。
Atlasクラスタへの接続では、atlasTemporaryDatabaseUserLifetimeMsという設定もあります。Atlas API経由でクラスタに接続する際にMCPサーバーが内部で作成する一時的なデータベースユーザーの生存時間で、既定は4時間(14400000ミリ秒)です。この時間を過ぎると一時ユーザーは自動的に削除されるため、長時間起動しっぱなしのセッションでは接続が切れることがあります。運用時間に合わせて延ばすかどうかを検討します。
複数の防御層をどう重ねるか
ここまでの設定は、どれも「書き込みを止める」ように見えて効く階層が違います。1つが漏れても他の層で被害を抑え込める構成にしておくと安全です。
| 層 | 止めるもの | 抜け穴になり得るケース |
|---|---|---|
--readOnly | 止めるものMCPサーバーが登録するツール自体 | 抜け穴になり得るケースフラグの設定漏れ・優先順位の取り違え |
| DBユーザー権限 | 止めるものデータベース側での書き込み実行 | 抜け穴になり得るケース管理者アカウントを使い回している |
| IPアクセスリスト | 止めるもの未許可のネットワークからの接続 | 抜け穴になり得るケース開発時に0.0.0.0/0を許可したまま放置 |
confirmationRequiredTools | 止めるもの削除系ツールの無確認実行 | 抜け穴になり得るケースクライアントがelicitationに未対応 |
maxDocumentsPerQuery / indexCheck | 止めるもの1クエリでの過大な取得・全件スキャン | 抜け穴になり得るケース上限を既定値のまま放置している |
--readOnlyだけに頼ると、フラグの設定を1箇所間違えただけで防御が総崩れになります。DBユーザー権限とIPアクセスリストは--readOnlyとは独立した層なので、MCPサーバー側の設定に穴があっても被害の範囲を抑えられます。さらに細かく、ツール単位で許可・要確認を分けたい場合は、Claude Code側のpermissions設定も重ねられます。書き方全般はClaude Code MCP設定ガイドにまとめています。
よくあるつまずき
readOnlyを有効にしたのにAtlasクラスタの作成が失敗する: 想定どおりの挙動です。クラスタ作成・スケーリングは書き込み操作に分類されるため、readOnlyが有効な接続では実行できません- 接続元IPが変わって突然繋がらなくなる: 動的IPの回線からMCPサーバーを動かしている場合に起きます。固定IPの環境に寄せるか、VPNやプロキシ経由で送信元IPを固定します
confirmationRequiredToolsが効かない: elicitationに対応していないMCPクライアントでは、確認プロンプトを出す仕組み自体が機能せず、対象ツールはそのまま実行されます。クライアントの対応状況を先に確認します- 開発用の広いDBユーザー権限を本番接続にそのまま使い回す: 検証時に作った管理者権限の接続文字列を、本番用の設定にコピーしたまま忘れているケースです。環境ごとに接続文字列とDBユーザーを分けておきます
よくある質問
confirmationRequiredToolsのツール名は自分で追加・変更できますか
できます。既定のリスト(atlas-create-access-list,atlas-create-db-user,drop-database,drop-collection,delete-many,drop-index,atlas-streams-manage,atlas-streams-teardown)はあくまで初期値です。カンマ区切りの文字列を上書きすれば、確認を挟みたい任意のツールを追加できます。ただし、対象のクライアントがelicitationに対応していない場合、リストに加えても確認プロンプトは表示されません。
Dockerで動かす場合も同じ読み取り専用設定が使えますか
使えます。docker runの-e MDB_MCP_READ_ONLY=trueで同じ設定を渡せます。加えて、Dockerコンテナで動かすこと自体がホストのファイルシステムやネットワークから隔離される利点になり、exportsPathやlogPathをコンテナの外に持ち出さない構成にしておけば、ファイル権限の管理もコンテナのライフサイクルに任せられます。
まとめ
MongoDB MCPサーバーを本番に繋ぐときは、--readOnly・DBユーザー権限・IPアクセスリストの3層を独立に設定します。--readOnlyはツールの公開範囲を絞るだけで、DBユーザーの権限そのものは変えないため、専用の読み取り専用アカウントを別途用意することが土台になります。Atlas APIを使うなら、サービスアカウントの権限も用途別の最小ロールに絞り、Organization Ownerのような広い権限は避けます。クラスタの作成やスケーリングのようにAtlas側の変更を伴う操作は、readOnlyとは別の接続で行う前提になる点も、運用設計の段階で決めておきます。