Claude Media
MongoDB MCPを本番で使うときの読み取り専用設定

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の認証情報が必要です。

書き込み系ツールをそもそも登録させない

MongoDB MCPサーバーのツールには、操作の種類(operation type)が付いています。readOnlyを有効にすると、種類が「read」「connect」「metadata」以外のツールは起動時に登録されません。insert-many・update-many・delete-many・drop-collection・drop-databaseなどはClaudeから見て存在しないツールになります。サーバーのログには、登録を見送ったツールの一覧が出ます。

使い分けは、止めたい範囲で決まります。

くらべる

readOnlyとdisabledToolsの違い

まとめて止める

--readOnly

書き込み系の種類を一括で外します。止め忘れが起きにくく、本番接続の既定にしやすい方法です。

選んで止める

--disabledTools

ツール名・操作の種類(create update delete read metadata connect)・カテゴリ(atlas mongodb)で指定します。データベース操作だけを使うならatlasカテゴリごと外せます。

環境変数ではMDB_MCP_DISABLED_TOOLS="create,update,delete,atlas"のようにカンマ区切り、コマンドライン引数では--disabledTools create update delete atlasのように空白区切りで書きます。

チームで共有する.mcp.jsonに入れる

Claude Codeに登録するときは、接続文字列そのものを設定に書かず、環境変数の参照にします。claude mcp add-jsonの--scopeの既定はlocalで、チームで共有する.mcp.jsonに書き出すのはprojectを指定したときです。実行すると次のようになります。

claude mcp add-json mongodb \
  '{"command":"npx","args":["-y","mongodb-mcp-server@latest","--readOnly"],"env":{"MDB_MCP_CONNECTION_STRING":"${MDB_MCP_CONNECTION_STRING}"}}' \
  -s project
Added stdio MCP server mongodb to project config

生成された.mcp.jsonです。

{
  "mcpServers": {
    "mongodb": {
      "command": "npx",
      "args": ["-y", "mongodb-mcp-server@latest", "--readOnly"],
      "env": {
        "MDB_MCP_CONNECTION_STRING": "${MDB_MCP_CONNECTION_STRING}"
      }
    }
  }
}

JSON全体をシングルクォートで囲んでいるので、${...}はシェルに展開されず、文字列のままファイルに入ります。Claude Codeは.mcp.jsonのenvでも${VAR}を展開するため、接続文字列は各自のシェルの環境変数に置き、リポジトリにはパスワードを残さずに済みます。変数が未設定でデフォルトも無いときは、claude mcp listに警告が出て、${VAR}の文字列がそのまま使われます。

プロジェクトスコープのサーバーは、対話セッションで承認するまで使われません。優先順位は、コマンドライン引数、環境変数、設定ファイルの順に高いので、--readOnlyとMDB_MCP_READ_ONLY=falseのように食い違う指定を同居させないようにします。

aggregateはreadOnlyでも登録される

aggregateとaggregate-dbは、操作の種類が「read」のツールです。readOnlyを有効にしても外れません。パイプラインに$outや$mergeが含まれる場合、この2つのツールはconfirmationRequiredToolsの設定にかかわらず、実行前に確認を求めます。READMEによると$outは対象コレクションの内容を丸ごと置き換えるステージで、確認メッセージには対象のコレクション名と処理内容が入ります。

ただしこの確認はelicitationという仕組みに依存します。elicitationに対応していないクライアントでは、確認プロンプト自体が出ず、ツールはそのまま実行されます。readOnlyに確認プロンプトを足しても、パイプライン内の書き込みを最後に止めるのはDBユーザーの権限です。次の節の専用ユーザーが土台になります。

IPアクセスリストで接続元を絞る

Atlasでは、接続元のIPをアクセスリストで制限できます。MCPサーバーを動かすマシンのIPがアクセスリストに登録済みか、Atlasの管理コンソールで先に確認します。

Atlas APIサービスアカウントで接続している場合は、atlas-inspect-access-listで現在の登録状況をClaudeに見せ、atlas-create-access-listで追加できます。atlas-create-access-listは既定のconfirmationRequiredToolsに含まれるので、elicitationに対応したクライアントでは実行前に確認が入ります。CIやヘッドレス実行のように確認プロンプトを挟めない場面では、事前にAtlas管理コンソールから手動で登録しておくほうが確実です。

IPの許可先は2種類あります。READMEのサービスアカウント作成手順では、Client IDとClient Secretを発行したあとで、自分のIPを「API access list」に追加します。これはAtlas APIを呼べる接続元の制限です。クラスタへの接続を許可するatlas-create-access-listの対象は、このAPI access listとは別に設定します。

DBユーザーの権限を絞る

--readOnlyはMCPサーバー内部でのツールの公開範囲を絞るだけで、接続文字列に含まれるDBユーザーの権限そのものは変えません。管理者権限のユーザーを接続文字列にそのまま渡していれば、MCPサーバーの設定に穴があったとき、DB側では書き込みが通る状態が残ります。

Atlasでは、データベースユーザーを作成するときに、読み取りだけを許すビルトインロールを割り当てます。セルフホストのMongoDBでも、読み取り権限だけを持つ専用ユーザーを作り、MCPサーバー専用の接続文字列に使います。管理者アカウントの使い回しは避けます。

Atlas APIを使うなら、サービスアカウントのロールも絞る

Atlas API経由でクラスタ一覧やパフォーマンスアドバイザーを使う場合は、サービスアカウントに付けるロールも用途に応じて最小限にします。READMEが示す、用途別に最も安全なロールは次のとおりです。

やりたいこと割り当てるロール(スコープ)
組織・プロジェクトの一覧を見る割り当てるロール(スコープ)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(プロジェクト)

READMEはプロジェクト単位のロールを優先し、必要なプロジェクトにだけ割り当てることを勧めています。Organization Ownerは、組織内の全プロジェクトと設定を管理する必要がある場合を除き、避けるよう警告しています。

1回のクエリで返す量に上限をかける

--readOnlyは書き込み系ツールを止めるだけで、読み取り系ツールが返す量は別の設定で制限します。本番のコレクションを相手にするときに効く既定値は、次のとおりです。

数字

取得量まわりの既定値

  • maxDocumentsPerQuery

    100件

    findまたはaggregateが返せる件数の上限

  • maxBytesPerQuery

    16MB

    結果サイズの上限(16777216バイト)

  • maxTimeMS

    未設定

    設定すると読み取り操作に実行時間の上限がかかる

  • queryCountMaxTimeMsCap

    10秒

    findの件数カウント段階の上限(10000ms)

すべて設定で変更できます

findツールでは、maxDocumentsPerQueryとツール自身のlimitパラメーターのうち小さいほうが実効上限になります。maxBytesPerQueryはresponseBytesLimitパラメーターの上限として働きます。aggregateのカウント段階には別の上限aggregationCountMaxTimeMsCap(既定60000ミリ秒)があります。本番のプライマリに重いaggregateを向けたくないなら、設定ファイルで次のように絞ります。

{
  "maxDocumentsPerQuery": 50,
  "maxBytesPerQuery": 5242880,
  "maxTimeMS": 10000
}

サーバーサイドJSと全件スキャンを塞ぐ

disableServerSideJsは既定がtrueで、$where・$function・$accumulatorといったサーバーサイドJavaScriptの演算子を、クエリのフィルターとaggregationパイプラインの両方で禁止します。readOnlyとは独立に最初から効いているので、意図して無効にしない限り追加の設定は要りません。

インデックスを使わない全件スキャンを止めたいときは、indexCheckを有効にします。環境変数ならMDB_MCP_INDEX_CHECK=true、引数なら--indexCheckです。コレクションスキャンを伴うクエリは拒否され、エラーメッセージが返ります。

ディスクに残るものを管理する

本番データを扱うと、MCPサーバーを動かすマシンのディスクにもデータの痕跡が残ります。置き場所は3か所です。

  • エクスポート: exportツールが出力したデータはexportsPathに一時ファイルとして置かれます。既定はmacOS・Linuxで~/.mongodb/mongodb-mcp/exports、Windowsで%LOCALAPPDATA%\mongodb\mongodb-mcp\exportsです。5分で期限切れになり、2分間隔のクリーンアップで削除されます
  • ログ: 既定のロガーはdisk,mcpで、ログがディスクに書かれます。macOS・Linuxの既定先は~/.mongodb/mongodb-mcp/.app-logsで、logPathで変えられます。ディスクに残したくない場合は、--loggers mcp stderrのようにロガーを選びます
  • 設定ファイル: MDB_MCP_CONFIGで読み込むJSONには、接続文字列やAPIシークレットが入りえます

READMEは、exportsPathとlogPathについて、実行ユーザーが読み書きできる状態にしたうえで、権限を適切に絞るよう求めています。設定ファイルについても、所有者を実行ユーザーだけに限る例が載っています。

chmod 600 /path/to/config.json
chown your-username /path/to/config.json

同じサーバーに複数のユーザーがいる環境では、この権限が緩いと、DBユーザーのパスワードやAtlasのAPIシークレットが他のユーザーから読めます。READMEは、機密性の高い項目を--config引数や設定ファイルの本文より、環境変数で渡すことを勧めています。コマンドライン引数はプロセス一覧に見えるためです。

最後に、Atlas API経由でクラスタに接続すると、MCPサーバーが一時的なデータベースユーザーを作ります。atlasTemporaryDatabaseUserLifetimeMsがその生存時間で、既定は4時間(14400000ミリ秒)です。時間が過ぎると自動で削除されます。外部へのテレメトリ送信を止めたい場合は、MDB_MCP_TELEMETRY=disabledまたはDO_NOT_TRACK=1を設定します。

5つの層の抜け穴を見比べる

ここまでの設定は、どれも「書き込みを止める」ように見えて、効く階層が違います。1つが漏れても他の層で被害を抑えられる構成にしておきます。

防御層

層ごとの止め方と抜け穴

  • --readOnly

    MCPサーバーが登録するツール自体を絞ります。抜け穴は、フラグの設定漏れと優先順位の取り違えです。

  • DBユーザー権限

    データベース側での書き込み実行を止めます。抜け穴は、管理者アカウントの使い回しです。

  • IPアクセスリスト

    未許可のネットワークからの接続を止めます。抜け穴は、開発時に開けた0.0.0.0/0の放置です。

  • confirmationRequiredTools

    削除系ツールの無確認実行を止めます。抜け穴は、elicitationに未対応のクライアントです。

  • 取得量の上限と indexCheck

    過大な取得と全件スキャンを止めます。抜け穴は、上限を既定値のまま放置することです。

さらに細かくツール単位で許可・要確認を分けたいときは、Claude Code側のpermissions設定も重ねられます。書き方はClaude Code MCP設定ガイドにあります。

よくあるつまずき

  • readOnlyを有効にしたのにAtlasクラスタの作成が失敗する: 想定どおりの挙動です。クラスタの作成・更新にあたるツールは書き込み系の操作と考えられ、readOnlyの接続では登録されません
  • 接続元IPが変わって突然繋がらなくなる: 動的IPの回線からMCPサーバーを動かしている場合に起きます。固定IPの環境に寄せるか、アクセスリストに現在のIPを登録し直します
  • confirmationRequiredToolsが効かない: elicitationに対応していないMCPクライアントでは、確認プロンプトが出ず、対象ツールはそのまま実行されます。クライアントの対応状況を先に見ておきます
  • .mcp.jsonに書いたサーバーが動かない: プロジェクトスコープのサーバーは、対話セッションで承認するまで使われません。承認の選択をやり直すときはclaude mcp reset-project-choicesを使います
  • 開発用の広い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)は初期値で、カンマ区切りの文字列を上書きすれば、確認を挟みたい任意のツールを足せます。aggregateを加えると、すべての呼び出しが実行前の確認の対象になり、$outや$mergeだけの個別確認は重ねて出ません。

Dockerで動かす場合も同じ読み取り専用設定が使えますか

使えます。READMEのDocker例では、docker run --rm -i -e MDB_MCP_CONNECTION_STRING -e MDB_MCP_READ_ONLY="true" mongodb/mongodb-mcp-server:latestのように、環境変数で同じ設定を渡します。接続文字列は事前にシェルへexportしておき、値を書かずに-eで引き継ぎます。

まとめ

本番に繋ぐ土台は、読み取り専用のDBユーザーです。--readOnlyは公開するツールを絞るだけで、aggregateのような読み取り系ツールは残るので、書き込みの最後の歯止めはDB側の権限が担います。Atlasのクラスタ作成やスケーリングを任せたい場合は、読み取り専用とは別の接続を用意する前提で設計します。

この記事を共有:XはてブLinkedIn