はじめに
TL;DR
MCPサーバーをHTTP化してDockerで動かすと、GCP認証情報(GOOGLE_APPLICATION_CREDENTIALS)の扱いで詰まるかと思います。この記事では、HTTPヘッダー経由で認証情報を安全に渡し、一時ファイルとして処理する実装パターンを紹介します。
前回の記事では、tumiki-mcp-httpを使ってstdio形式のMCPサーバーをHTTP化し、Dockerコンテナで動かす方法を紹介しました。今回は、実際のユースケースとしてGoogle Search Console MCPをDockerで動かし、GCP認証情報を安全に扱う方法について解説します。
本記事の構成はローカル検証・PoC用途を想定しています。
GCP認証情報の課題
Google Search Console MCPは、GCPの標準的な認証方式に従い、環境変数GOOGLE_APPLICATION_CREDENTIALSに認証情報JSONファイルのパスを設定することを要求します。しかし、HTTPベースのリモート実行環境では以下の問題が発生します:
- ファイルパスの問題: クライアント側のローカルファイルパスをHTTPヘッダーで渡しても、サーバー側(Dockerコンテナ内)にそのファイルは存在しない
- セキュリティの問題: 認証情報JSONをコンテナイメージに埋め込むのはセキュリティ上好ましくない
- ステートレス性: HTTPアダプター環境では、リクエストごとに認証情報を渡す必要がある
つまり、ファイルパスではなく認証情報JSON自体をHTTPヘッダーで渡し、サーバー側で一時的にファイルとして書き出す必要がありました。
この課題を解決するため、HTTPヘッダー経由でJSON認証情報を受け取り、リクエスト処理時のみ一時ファイルとして書き出す仕組みを実装しました。
GCP認証情報wrapperの仕組み
MCPサーバーとHTTPアダプターの間に位置するwrapperスクリプトが、以下の処理を行います:特にタイトルや冒頭のwhyが弱いです
TLDRを入れるとより最後まで読み切る方が増えます
改善点(最低限ここだけ直すと良い)
① 冒頭に「誰の何の困りごとか」を1〜2行で明示する
今は連載前提の書き出しなので、新規読者が入りにくいです。
改善例
MCPサーバーをHTTP化すると、GCP認証情報の扱いで必ず詰まる。
この記事では、その回避策をDocker前提で整理する。
② 想定用途(PoC / ローカル検証)を明言する
レビュー・実務利用時の誤解を防げます。
どこかに一言でOK
本記事の構成はローカル検証・PoC用途を想定しています。
③ タイトルを「課題ベース」に寄せる
技術名だけだと検索・おすすめで弱い。
改善方向
×「MCPをDockerで動かしてみた」
○「GCP認証で詰まらないMCPサーバーをDockerで動かす」
総括(超短く)
技術内容は十分に良い
「誰向け・何が解決できるか」を最初に出せば完成度が一段上がる
以上です。
- HTTPヘッダー(
X-Credentials)から認証情報を取得 - 一意な名前の一時ファイル(
/tmp/creds-$$-$(date +%s%N)-$RANDOM.json)に書き出し - 環境変数
GOOGLE_APPLICATION_CREDENTIALSに一時ファイルのパスを設定 - MCPサーバーを起動してリクエストを処理
- 処理完了後、trapハンドラーで一時ファイルを自動削除
この方式により、認証情報はメモリとリクエストスコープ内でのみ存在し、永続的にディスクに残ることはありません。また、複数リクエストが並行処理されてもファイル名の衝突が起こらないよう、プロセスID・タイムスタンプ・ランダム値を組み合わせています。
実装
ファイル構成
以下のファイル構成で作業ディレクトリを作成します:
google-search-console-mcp/
├── Dockerfile
└── gcp-credentials-wrapper.sh
まず、作業ディレクトリを作成します:
mkdir google-search-console-mcp
cd google-search-console-mcp
必要なファイル
以下の2つのファイルを作成します。
Dockerfile
# Google Search Console MCP Server with tumiki-mcp-http adapter
# HTTP経由でアクセス可能なGoogle Search Console MCPサーバー
# ===================================
# ビルドステージ
# ===================================
FROM golang:alpine AS builder
WORKDIR /build
# gitをインストール
RUN apk add --no-cache git
# tumiki-mcp-http-adapterをクローン&ビルド
RUN git clone https://github.com/rayven122/tumiki-mcp-http-adapter.git . && \
go build -o tumiki-mcp-http ./cmd/tumiki-mcp-http
# ===================================
# ランタイムステージ
# ===================================
FROM node:20-alpine
WORKDIR /app
# 必要なパッケージをインストール
RUN apk --no-cache add ca-certificates bash
# tumiki-mcp-httpバイナリをコピー
COPY --from=builder /build/tumiki-mcp-http .
RUN chmod +x tumiki-mcp-http
# GCP認証情報wrapperをコピー
COPY gcp-credentials-wrapper.sh /app/gcp-credentials-wrapper.sh
RUN chmod +x /app/gcp-credentials-wrapper.sh
# ポートを公開
EXPOSE 8080
# 環境変数を設定
ENV PORT=8080
# ヘルスチェック
HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
CMD pgrep -x tumiki-mcp-http > /dev/null || exit 1
# コンテナ起動
# HTTPヘッダー経由で認証情報を受け取り、wrapperで処理
CMD ./tumiki-mcp-http --stdio "/app/gcp-credentials-wrapper.sh" \
--header-env "X-Credentials=GOOGLE_APPLICATION_CREDENTIALS_JSON" \
--port ${PORT}
gcp-credentials-wrapper.sh
#!/bin/bash
# Google Cloud認証情報wrapper script
# HTTPヘッダーから受け取った認証情報JSONを一時ファイルに保存し、
# GOOGLE_APPLICATION_CREDENTIALS環境変数で参照できるようにする
set -e
# ユニークな一時ファイル名を生成(プロセスID + ナノ秒タイムスタンプ + ランダム値)
CRED_FILE="/tmp/creds-$$-$(date +%s%N)-$RANDOM.json"
# クリーンアップ関数
cleanup() {
rm -f "$CRED_FILE"
}
# 終了時に必ずクリーンアップ
trap cleanup EXIT INT TERM
# 環境変数の確認
if [ -z "$GOOGLE_APPLICATION_CREDENTIALS_JSON" ]; then
echo "Error: GOOGLE_APPLICATION_CREDENTIALS_JSON not set" >&2
exit 1
fi
# JSONを一時ファイルに保存
echo "$GOOGLE_APPLICATION_CREDENTIALS_JSON" > "$CRED_FILE"
# ファイルパスを環境変数に設定
export GOOGLE_APPLICATION_CREDENTIALS="$CRED_FILE"
# MCPサーバーを起動
exec npx -y mcp-server-gsc
ビルドと起動
Dockerイメージのビルドと起動は以下のコマンドで行います:
# イメージをビルド
docker build -t google-search-console-mcp .
# コンテナの起動
docker run -d -p 8080:8080 -e PORT=8080 --name search-console-mcp google-search-console-mcp
動作確認
tumiki-mcp-httpアダプターは/mcpエンドポイントでJSON-RPC 2.0形式のリクエストを受け付けます。
1. tools/listの取得(認証情報不要)
まず、利用可能なツール一覧を取得してみます。tools/listは認証情報がなくても取得できます:
# ダミーの認証情報で動作確認(空のJSONオブジェクト)
curl -X POST http://localhost:8080/mcp \
-H "X-Credentials: {}" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'
2. 実際のデータ取得(GCP認証情報が必要)
実際のGoogle Search Consoleデータを取得する場合は、GCP認証情報をPlain JSON形式で渡します:
# GCP認証情報をPlain JSON形式で読み込み(改行を削除)
# jqを使う場合
CREDS=$(cat /path/to/service-account.json | jq -c)
# またはPythonを使う場合
CREDS=$(python -c "import json; print(json.dumps(json.load(open('/path/to/service-account.json'))))")
# 実際のツールを呼び出し(例:サイト一覧取得)
curl -X POST http://localhost:8080/mcp \
-H "X-Credentials: $CREDS" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc":"2.0",
"id":1,
"method":"tools/call",
"params":{
"name":"list_sites",
"arguments":{}
}
}'
正常に動作すると、Google Search Consoleの利用可能なツール一覧が返ってきます:
{
"jsonrpc":"2.0",
"id":1,
"result":{
"tools":[
{
"name":"list_sites",
"description":"List all sites in Google Search Console",
"inputSchema":{
"type":"object",
"properties":{},
"required":[]
}
},
{
"name":"search_analytics",
"description":"Get search performance data from Google Search Console",
"inputSchema":{
"type":"object",
"properties":{
"siteUrl":{"type":"string","description":"The site URL"},
"startDate":{"type":"string","description":"Start date (YYYY-MM-DD)"},
"endDate":{"type":"string","description":"End date (YYYY-MM-DD)"},
"dimensions":{"type":"string","description":"Comma-separated list of dimensions"}
},
"required":["siteUrl","startDate","endDate"]
}
}
]
}
}
トラブルシューティング
コンテナが起動しない場合
ログを確認します:
docker logs search-console-mcp
認証エラーが発生する場合
- サービスアカウントに適切な権限が付与されているか確認
- Google Search Console APIが有効になっているか確認
- 認証情報JSONが正しい形式か確認
# 認証情報の確認(正しいJSON形式か検証)
echo "$CREDS" | jq .
# 元のファイルを確認
cat /path/to/service-account.json | jq .
まとめ
HTTPヘッダー経由での認証情報の受け渡しと、一時ファイルを使った安全な処理により、GCP認証が必要なMCPサーバーをDockerでローカル検証できるようになりました。この仕組みは汎用的で、Google Analytics、Google Driveなど他のGCPサービスにも同様に適用できます。
この記事で紹介した方法を使えば、以下のメリットがあります:
- セキュリティ: 認証情報がコンテナイメージに埋め込まれない
- 柔軟性: HTTPヘッダーで認証情報を動的に切り替え可能
- 再現性: Dockerfileとwrapperスクリプトだけで環境を再現できる
ローカルで動作確認できたら、同じDockerイメージをCloud Runにデプロイすることで、スケーラブルなリモートMCP環境を構築できます。