自己紹介
NTTドコモ データプラットフォーム部(以下DP部)田中です。DP部ではデータ活用の民主化を目指して社内向けにstreamlitの開発プラットフォームを独自に実装し、運用してから2年以上経過しました。
参考:
一昨年の記事 社員1000人以上が使う、Streamlit in Google Cloudのサーバレスプラットフォームを完全内製してみた
昨年の記事 セキュリティのためのプラットフォームエンジニアリング -認知負荷を軽減するDevSecOps in GoogleCloud
この2年でトレンドも大きく変わり、AIエージェントという言葉を聞かない日がないほど、AIの活用が広く普及してきました。我々のプラットフォームでも、AIエージェントアプリケーションの検討が本格化しており、AIエージェントアプリケーション向けにMCPサーバーをデプロイする仕組みを構築したので、本記事では経緯と共にご紹介させていただきます。 なお、検討・実装についてはNTTデータの支援メンバーである三浦さんに進めてもらっており、該当のセクションは三浦さんに執筆いただいています。
プラットフォームとして目指す姿
先日のCloud Next Tokyoにて、「NTTドコモが実現したデータ民主化と、データ エージェントへの挑戦」というタイトルで本プラットフォームの取り組みを発表しました。 発表の中でも、今後の展望として「より自立的なData Agentへ」というコンセプトを提唱しており、業務の点を補うアプリケーションを横断し、利用者がやりたいことを汲み取って、アプリケーションを組み合わせながら業務を完遂するエージェントを目指すことを掲げています。
エージェントが利用者の望むデータ活用を担うためには、エージェントが高度な判断を行うための手足となるツールが必要です。これらはMCPを介して提供されるべきであり、プラットフォームにはMCPサーバーのデプロイを統制し、エージェントアプリケーションが必要に応じてMCPサーバーを利用できるようにする仕組みが求められます。
本プラットフォームはGoogle Cloud上で構築されており、AIエージェントが活用するアプリケーションはCloud Run Service上にデプロイされています。この環境下でMCPサーバーを運用するために、Google Cloudが提唱するMCPサーバーのデプロイ方法を参考にしながら、我々のプロダクトに最適な構成を模索する必要がありました。
アプローチ
Google Cloudが言及しているMCPサーバーのホスティング先は、Cloud RunやGKEなどです。1
最終的にAIエージェントアプリケーションは、他アプリケーションと同様にCloud Run Service上にホストする想定です。そのためMCPサーバーについても、Cloud Run Service上でデプロイすることを前提に検討を進めました。
次に、Cloud Run上でMCPサーバーをデプロイする方法ですが、こちらも複数の選択肢が案内されています。2
これらを参考に、以下の3つの構成を段階的に検証しました。詳細は後述の章にて説明いたしますが、各方式の特徴と検討した所感を以下の表にまとめます。
| 検証時期 | デプロイ方式 | 検討した所感 |
|---|---|---|
| 試行錯誤期 | アプリケーションコンテナに組み込み | MCPサーバー自体の有効性を検証するなら使っても良い |
| 検証開始期 | サイドカーコンテナを追加 | 特定のアプリ専用のMCPとするなら十分 |
| 試験運用期 | MCPサーバーコンテナごと独立してデプロイ | 汎用性が高いため、実運用を見据えるならこの方式を取って損は無い |
所感だけでは、MCPサーバーコンテナごと独立してデプロイする方式一択に見えてしまうので、それぞれのメリットについても言及していきます。
方式1: アプリコンテナ内にMCPサーバーも組み込んでデプロイ
この方法は、Google Cloudのドキュメント上では記載がありません。具体的には、stdioトランスポートのMCPサーバーを、アプリケーションコンテナ内に組み込んで動作させる方法です。アプリケーションを動かすための資材と、MCPサーバーのための資材を同じコンテナにまとめてしまうという、コンテナの単一責任原則に反する構成となります。

アプリケーションコンテナの中に対象のMCPサーバーが同居し、MCPクライアントとMCPサーバーが標準入出力を介して通信を行います。具体的には、Dockerfileの中でMCPサーバーのインストールを行い、アプリケーション内でMCPサーバーを呼び出すようにします。
この構成の大きなメリットは、アプリケーションとMCPサーバーが同一のコンテナ内で動作するため、MCPサーバー側がアプリケーションの情報を最大限に活用することができる点です。アプリケーションのソースコードや設定情報を使って出力結果の保存先を動的に変更したり、アプリケーションの状態に応じてMCPサーバーの挙動を調整したりすることが可能です。
採用当初はstdioトランスポートによる動的なMCPサーバーの実行で得られる恩恵が大きく、利用範囲も限定的であったため、MCPサーバー自体の有効性を検証する目的であれば、この方法を採用しても良いと考えました。 一方で、長期的な運用を見越して使うには、コンテナの煩雑性が高く、セキュリティの面でも不安が残る構成となるため、推奨されない方法となります。我々のチームでも、MCPサーバーの有効性を確認した後は、より運用に適した構成の検討に移りました。
方式2: サイドカーコンテナによる、MCPサーバーのデプロイ
有効性が確認できたMCPサーバーを実運用に移すため、Cloud Run Service上でMCPサーバーをサイドカーコンテナとして追加する方法を検討しました。下図のように、アプリケーションコンテナとは別にMCPサーバー用のコンテナを用意し、同一のCloud Run Service内で並列に動作させる構成です。MCPサーバーは、アプリケーションコンテナからのHTTPリクエストを介して通信を行うstreamable-httpトランスポートで立ち上げます。

アプリケーションコンテナとMCPサーバーコンテナが分離されることで、MCPサーバーに絞ったメンテナンスやアップデートが容易になり、スケーリングなども個別に設定可能な柔軟性を確保できます。この形式を採用するためには、単独で通信を受け付けることができるstreamable-httpトランスポートを利用する必要があります。
既に立ち上がっているCloud Run ServiceにMCPサーバーをサイドカーコンテナとして追加する場合、Cloud Runのコンソール画面からは設定変更ができないため、gcloudコマンドとYAMLファイルを使って設定を書き換える必要があります。
YAMLファイルには、アプリケーション用の情報とは別に、MCPサーバー用の情報を追記します。以下はその例です。
apiVersion: serving.knative.dev/v1 kind: Service metadata: ... spec: template: metadata: annotations: ... name: target-app spec: ... containers: - name: application-image image: (application-container-image) volumeMounts: - name: mount_dir mountPath: /mnt/mount_dir ... - name: mcp-image image: (mcp-container-image) volumeMounts: - name: output_dir mountPath: /mnt/output_dir ... volumes: - name: output_dir csi: driver: gcsfuse.run.googleapis.com readOnly: false volumeAttributes: bucketName: your-bucket-name ...
streamable-httpトランスポートでMCPサーバーを立ち上げると、動的にサーバーの設定を変更することはできません。そのため、stdioトランスポートでは可能だった、MCPサーバーの出力結果をユーザごとに保存するフォルダを指定する等の動的な処理は実装できない課題に直面します。 この課題に対する工夫点として、それぞれのコンテナにCloud Storageバケットをマウントする設定を追加しました。共有したい資材をバケットに保存することで、両方のコンテナから同じ情報にアクセスできるようにしました。
作成したYAMLファイルを使って、以下のコマンドでCloud Run Serviceを更新し、サイドカーコンテナを新規に追加することができます。
gcloud run services replace service.yaml
単体のアプリケーション向けに提供・活用されるMCPサーバーであれば、この構成で要件は満たしており、独立したMCPサーバーとして管理するよりも運用が楽になる場合があります。しかし、プラットフォームが目指す姿を考えたときに、複数のAIエージェントがMCPサーバーを共有して利用できる状態であるべきで、拡張性を考えた構成を更に検討しました。
方式3: MCPサーバーコンテナを独立してデプロイ
最終的に、MCPサーバーをCloud Run上で独立したサービスとしてデプロイする方法を、本プラットフォームでは実装しました。streamable-httpトランスポートを利用したMCPサーバーが1つのCloud Run Serviceとして動作することで、MCPサーバーの管理をアプリケーション側に依存せず行うことが出来ます。下図のように、アプリケーションとMCPサーバーがCloud Run Service間の通信を行ってやり取りを行います。MCPサーバーが複数のアプリケーションから共有され、前述した目指すべき姿に向けた拡張性を確保できると判断したため、本構成を採用しました。

懸念点としては、MCPサーバーごとにCloud Run Serviceを立てる必要があるため、管理対象となるCloud Run Serviceの数が増え、運用負荷が増える点です。MCPサーバーのライフサイクルなど、運用負荷を軽減するための取り組みはいくつか考えられますが、現在はMCPサーバーの開発・運用に割く時間を最小限に抑えることに注力し、CI/CDの環境を整備しました。

ポイントは2点あり、いずれもMCPサーバーが将来的に急増した際に、開発者・プラットフォームの負荷を抑えられるように配慮した工夫となります。
- 中央集権型のCI/CDパイプライン
Cloud Next Tokyoで発表した構成と同じですが、開発者が触るリポジトリから、プラットフォームの運営チームが管理するMCPサーバー:w600用のリポジトリへ、GitHub Actionsのトリガーを設定しています。これにより、重要なワークフローがプラットフォームチームの管理に寄ることで、開発者が意識しなくても品質の保たれたCI/CDが実行されるようにしています。 - ソースコードデプロイ方式の採用 Cloud Run Serviceのデプロイ方式をソースコードからのデプロイ 3 にすることで、コンテナ管理をGoogleマネージドに寄せることができます。開発者はソースコードの変更だけに集中でき、プラットフォーム運営チーム側もベースイメージが自動更新されるなど、コンテナ管理作業が楽になります。
この構成によって、プラットフォームが多数のMCPサーバーを抱えても効率的に管理できる状態を実現し、AIエージェントを受け入れる体制を整えることができました。
まとめと今後の展望
本記事では、プラットフォームにおけるAIエージェントの活用を目指した、構成検討の過程を共有させていただきました。AIエージェントが常に価値を発揮できるようにするためには、MCPサーバーが継続的にデプロイ・改善される必要があります。今後AIエージェントの利用が拡大し知見が蓄積されることで、既存のアプリケーションを自動でMCPサーバー化する仕組みを確立するなど、より最適化されたプラットフォームへと進化させていきたいと考えています。
また、今回はMCPサーバーに焦点を当てましたが、AIエージェントアプリケーション全体の運用管理やセキュリティの確保も重要なテーマであり、引き続きプラットフォームエンジニアリングの観点から取り組んでいった内容を、機会がございましたら共有できればと思います。