MCP Server and Google ADK Multi-Tool System について
このプロジェクトは、TypeScript/Express製のMCPサーバーとPython製のGoogle ADKエージェントを組み合わせています。ツールを使うエージェントシステム向けに、セッション管理やWebhookによる振り分け、ツール追加の手順を備えています。
主な機能
- 01ファイル操作ツール
- 02API呼び出しツール
- 03セッションデータ管理
- 04天気情報ツール
- 05Webhookによるツール振り分け
- 06Server-Sent Eventsによる更新
活用シーン
- 01MCPツールを使うGoogle ADKエージェントの構築
- 02エージェントの要求をファイルやAPI操作へ振り分け
- 03システムへのツール追加
MCP 対応
MCPサーバーは、ファイル操作、API呼び出し、セッションデータ、天気情報のツールを提供します。Google ADKエージェントはWebhookインターフェース経由で接続します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
このサーバーのパッケージやリモートエンドポイントはまだ取得できていません。プロジェクトの README の手順に従ってください。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
MCP サーバーと Google ADK のマルチツールシステム
システムの概要
このシステムは、次の 2 つの主要なコンポーネントで構成されています。
- MCP サーバー:ファイル操作、API 呼び出し、セッションデータ管理、天気情報のツールを提供する TypeScript/Express サーバーです。
- Google ADK エージェント:MCP サーバーに接続し、Webhook インターフェースを通じてそのツールを使用する Python エージェントです。
通信の流れは次のとおりです。
- Google ADK エージェントがユーザーリクエストを受け取ります
- エージェントが使用するツールを判断します
- エージェントが MCP サーバーの Webhook エンドポイントにリクエストを送信します
- MCP サーバーがリクエストを処理し、操作を実行します
- MCP サーバーが結果をエージェントに返します
- エージェントがユーザー向けにレスポンスを整えます
すべてのコンポーネントの実行
このガイドでは、新しいツールをシステムに追加する方法も含めて、MCP サーバーと Google ADK エージェントシステムのセットアップと実行方法を説明します。
前提条件
- MCP サーバー用の Node.js(v16+)
- Google ADK エージェント用の Python(v3.9+)
- Google ADK SDK がインストールされていること(
pip install google-adk) - Vertex AI が有効になっている Google プロジェクト
- Google ADK エージェントが Vertex AI にアクセスするための IAM 権限
- リポジトリにアクセスするための、MCP サーバー用 GitHub または Gitlab アクセストークンを環境変数として設定していること
環境のセットアップ
-
MCP サーバーと Google ADK エージェントをセットアップする:
# run this from the root directory of the project to setup the MCP server and the Google ADK agent ./scripts/setup.sh gcloud auth application-default login -
環境変数を設定する:
- MCP サーバーについては、mcp/ の
.envに以下が含まれていることを確認してください。# Server Configuration PORT=9000 BASE_DIR=./data # Repository Access Tokens, allows the MCP server to access private repositories GITHUB_ACCESS_TOKEN=your_github_token_here GITLAB_ACCESS_TOKEN=your_gitlab_token_here # Optional Configuration REPO_DIR=./repos MAX_EVENT_LISTENERS=100 - Google ADK エージェントについては、mcp_agent/ の
.envに以下が含まれていることを確認してください。GOOGLE_CLOUD_PROJECT="your-google-project-id" GOOGLE_CLOUD_LOCATION="us-central1" GOOGLE_GENAI_USE_VERTEXAI="True" MCP_SERVER_URL=http://localhost:9000
- MCP サーバーについては、mcp/ の
-
MCP サーバーを実行する:
# run this from the root directory of the project to start both the MCP server and the Google ADK agent ./scripts/run-mcp.sh -
Google ADK エージェントを実行する:
# run this from the root directory of this repository to start the Google ADK agent # will start this in web mode ./scripts/run-agent.sh web # will start this in terminal mode ./scripts/run-agent.sh run -
Web インターフェースを開き、mcp_agent を選択する:
- ブラウザーで
http://localhost:8000にアクセスします - ドロップダウンから
mcp_agentを選択します - エージェントとチャットして、正常に動作していることを確認します
- ブラウザーで
-
既存のツールをテストする:
Kubernetes での Google ADK エージェントの実行
Kubernetes で Google ADK エージェントを実行するには、次の手順に従ってください。
- Docker イメージをビルドする:
docker build -t mcp-agent:latest -f mcp_agent/Dockerfile . - イメージを Google Artifact Registry にプッシュする:
# Build and tag the image
gcloud builds submit
--tag $GOOGLE_CLOUD_LOCATION-docker.pkg.dev/$GOOGLE_CLOUD_PROJECT/mcp-agent-repo/mcp-agent:latest
--project=$GOOGLE_CLOUD_PROJECT
.
Verify the image was pushed
gcloud artifacts docker images list
$GOOGLE_CLOUD_LOCATION-docker.pkg.dev/$GOOGLE_CLOUD_PROJECT/mcp-agent-repo
--project=$GOOGLE_CLOUD_PROJECT
--format=json
3. **Kubernetes デプロイメントを作成する**:
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: mcp-agent
spec:
replicas: 1
selector:
matchLabels:
app: mcp-agent
template:
metadata:
labels:
app: mcp-agent
spec:
serviceAccount: mcp-agent-sa
containers:
- name: mcp-agent
imagePullPolicy: Always
image: us-central1-docker.pkg.dev/your-gar-registry/mcp-agent-repo/mcp-agent:latest
resources:
limits:
memory: "512Mi"
cpu: "500m"
ephemeral-storage: "1Gi"
requests:
memory: "256Mi"
cpu: "250m"
ephemeral-storage: "512Mi"
ports:
- containerPort: 8000
env:
- name: PORT
value: "8000"
- name: GOOGLE_CLOUD_PROJECT
value: "your-google-project-id"
- name: GOOGLE_CLOUD_LOCATION
value: "us-central1"
- name: GOOGLE_GENAI_USE_VERTEXAI
value: "True"
# Use a service name or an external access method for the MCP server
- name: MCP_SERVER_URL
value: "http://mcp-server-service:9000"
volumeMounts:
- name: credentials
mountPath: "/app/credentials"
readOnly: true
volumes:
- name: credentials
secret:
secretName: mcp-agent-credentials
---
apiVersion: v1
kind: Service
metadata:
name: mcp-agent
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 8000
selector:
app: mcp-agent
MCP サーバーと Google ADK エージェントシステムへの新しいツールの追加
この手順ガイドでは、MCP サーバーに新しいツールを追加し、Google ADK エージェントから利用できるようにするまでの全工程を説明します。以下では、画像生成ツールを例として使用します。
3. MCP サーバーへの新しいツールの追加
MCP サーバーに画像生成ツールを追加しましょう。必要な変更をすべて、手順に沿って説明します。
ステップ 1:MCP サーバーにツールの実装を作成する
まず、MCP サーバーに画像生成の中核となる機能を追加します。mcp/app.ts の app.ts ファイルに、次の内容を追加してください。
// 1. Add new type for ImageGeneration operation
type ImageGenerationOptions = {
prompt: string;
width?: number;
height?: number;
style?: string;
format?: 'png' | 'jpeg' | 'webp';
negativePrompt?: string;
};
// 2. Add the image generation tool implementation
const imageGenerationTool = async (options: ImageGenerationOptions): Promise<{success: boolean; data?: any; error?: string}> => {
try {
// Validate parameters
if (!options.prompt) {
return { success: false, error: 'Image prompt is required' };
}
// Set defaults for missing options
const width = options.width || 512;
const height = options.height || 512;
const format = options.format || 'png';
const style = options.style || 'photorealistic';
console.log(`Generating image for prompt: "${options.prompt}" with style: ${style}, dimensions: ${width}x${height}`);
// For this example, we'll just mock the image generation
// In a real implementation, you would call an API like Stable Diffusion or DALL-E
const mockImageData = {
prompt: options.prompt,
imageUrl: `https://example.com/generated_images/${Date.now()}.${format}`,
width,
height,
style,
format,
generatedAt: new Date().toISOString()
};
// In a real implementation, you might store the image file
// For mock purposes, write a metadata file
const metadataPath = validatePath(`images/metadata_${Date.now()}.json`);
const dir = path.dirname(metadataPath);
await fs.mkdir(dir, { recursive: true });
await fs.writeFile(metadataPath, JSON.stringify(mockImageData, null, 2), 'utf-8');
return {
success: true,
data: mockImageData
};
} catch (error: any) {
console.error('Image generation error:', error);
return {
success: false,
error: error.message || 'Unknown error during image generation'
};
}
};
ステップ 2:Google ADK Webhook 用のハンドラー関数を追加する
Google ADK エージェントからのリクエストを処理するため、このハンドラー関数を MCP サーバーに追加してください。
// Add this to the handler functions section
async function handleImageGenerationTool(parameters: any, sessionId: string) {
// Validate required parameters
if (!parameters.prompt) {
return {
success: false,
error: 'Missing required parameter: prompt'
};
}
// Create options object for the image generation tool
const options: ImageGenerationOptions = {
prompt: parameters.prompt,
width: parameters.width || 512,
height: parameters.height || 512,
style: parameters.style || 'photorealistic',
format: parameters.format || 'png',
negativePrompt: parameters.negativePrompt
};
return await imageGenerationTool(options);
}
ステップ 3:ADK Webhook の Switch 文を更新する
次に、/api/adk-webhook ルートハンドラーの Switch 文に、新しい case を追加します。
// Find the switch statement in app.post('/api/adk-webhook', ...)
switch (toolName) {
case 'file_system':
result = await handleFileSystemTool(parameters, mcpSessionId);
break;
case 'api_call':
result = await handleApiTool(parameters, mcpSessionId);
break;
case 'session_data':
result = await handleSessionDataTool(parameters, mcpSessionId);
break;
case 'weather':
result = await handleWeatherTool(parameters, mcpSessionId);
break;
// Add the new case for image generation
case 'image_generation':
result = await handleImageGenerationTool(parameters, mcpSessionId);
break;
default:
result = {
success: false,
error: `Unknown tool name: ${toolName}`
};
}
ステップ 4:直接アクセス用のエンドポイントを追加する
画像生成ツールに直接アクセスするための専用エンドポイントを追加します。
// Add this route to the app
app.post('/api/session/:sessionId/image', async (req, res) => {
const { sessionId } = req.params;
const session = getSessionAndUpdate(sessionId);
if (!session) {
return res.status(404).json({
success: false,
error: 'Session not found'
});
}
const options: ImageGenerationOptions = req.body;
if (!options.prompt) {
return res.status(400).json({
success: false,
error: 'Image prompt is required'
});
}
const result = await imageGenerationTool(options);
if (result.success) {
// Emit an event for SSE clients
emitEvent(sessionId, 'image-generation', {
imageUrl: result.data.imageUrl,
prompt: options.prompt,
timestamp: new Date().toISOString()
});
res.status(200).json(result);
} else {
res.status(400).json(result);
}
});
ステップ 5:API ドキュメントを更新する
/api/help エンドポイントの API ドキュメントに、新しいツールを追加します。
// Find the endpoints array in the helpDocs object
endpoints: [
// Add these new entries
{
path: "/api/session/{sessionId}/image",
method: "POST",
description: "Generate an image from a text prompt",
parameters: [
{
name: "sessionId",
in: "path",
required: true,
description: "Session identifier"
}
],
requestBodyExample: {
prompt: "A beautiful sunset over mountains",
width: 512,
height: 512,
style: "photorealistic",
format: "png",
negativePrompt: "blur, low quality"
},
responseExample: {
success: true,
data: {
prompt: "A beautiful sunset over mountains",
imageUrl: "https://example.com/generated_images/1717451623456.png",
width: 512,
height: 512,
style: "photorealistic",
format: "png",
generatedAt: "2025-06-03T12:00:00.000Z"
}
},
curlExample: `curl -X POST ${baseUrl}/api/session/{sessionId}/image \\
-H "Content-Type: application/json" \\
-d '{"prompt": "A beautiful sunset over mountains", "style": "photorealistic"}'`
},
// Add the Google ADK webhook documentation for image_generation tool
{
path: "/api/adk-webhook",
method: "POST",
description: "Webhook for Google ADK image generation",
requestBodyExample: {
session_id: "google-adk-session-123",
tool_name: "image_generation",
parameters: {
prompt: "A beautiful sunset over mountains",
width: 512,
height: 512,
style: "photorealistic"
},
request_id: "request-123"
},
responseExample: {
success: true,
data: {
prompt: "A beautiful sunset over mountains",
imageUrl: "https://example.com/generated_images/1717451623456.png",
width: 512,
height: 512,
style: "photorealistic",
format: "png",
generatedAt: "2025-06-03T12:00:00.000Z"
},
mcp_session_id: "550e8400-e29b-41d4-a716-446655440000",
request_id: "request-123"
},
notes: "This endpoint is used by the Google ADK agent to generate images."
}
],
4. Google ADK エージェントにツールのサポートを追加する
次に、mcp_agent にある Google ADK エージェントに、画像生成ツールを追加しましょう。
ステップ 1:MCPToolkit クラスにメソッドを追加する
まず、画像生成ツールを利用するための新しいメソッドを mcp_agent/mcp_toolkit.py ファイルに追加します。
# Add this method to the MCPToolkit class in mcp_toolkit.py
def generate_image(self, prompt: str, width: int = 512, height: int = 512,
style: str = "photorealistic", format: str = "png",
negative_prompt: str = None) -> Dict:
"""Generate an image from a text prompt using the MCP server"""
params = {
"prompt": prompt,
"width": width,
"height": height,
"style": style,
"format": format
}
if negative_prompt:
params["negativePrompt"] = negative_prompt
return self.execute_tool("image_generation", params)
ステップ 2:tools.py にツール関数を追加する
ADK エージェントに公開する新しいツール関数を tools.py に作成します。
# Add this to the tools.py file
def mcp_generate_image(prompt: str, style: str = "photorealistic", width: int = 512, height: int = 512) -> dict:
"""Generates an image from a text prompt.
Args:
prompt: Text description of the image to generate
style: Style for the image (e.g., photorealistic, cartoon, sketch)
width: Width of the output image in pixels
height: Height of the output image in pixels
Returns:
dict: A dictionary with status ('success' or 'error') and either image info or error message
"""
try:
result = mcp_toolkit.generate_image(
prompt=prompt,
style=style,
width=width,
height=height
)
if result.get("success"):
image_data = result.get("data", {})
return {
"status": "success",
"image_url": image_data.get("imageUrl"),
"message": f"Generated image for prompt: '{prompt}' in {style} style."
}
else:
return {
"status": "error",
"error_message": result.get("error", "Unknown error generating image")
}
except Exception as e:
logger.error(f"Error in mcp_generate_image: {str(e)}")
return {
"status": "error",
"error_message": f"Exception: {str(e)}"
}
ステップ 3:エージェントにツールを登録する
新しいツールを含めるため、agent.py ファイルを更新します。
# Add to the imports in agent.py
from .tools import (
mcp_read_file,
mcp_write_file,
mcp_list_files,
mcp_delete_file,
mcp_get_weather,
mcp_call_api,
mcp_store_data,
mcp_store_number,
mcp_store_boolean,
mcp_retrieve_data,
mcp_generate_image # Add this import
)
# Update the agent definition
agent = Agent(
name="mcp_agent",
model="gemini-2.0-flash",
description="Agent that can handle weather, time, and interact with a Model Control Protocol server",
instruction="""I can help you with various tasks through my integration with the MCP server.
I can:
- Get current time in different cities
- Check weather conditions in locations
- Read, write, list, and delete files
- Make API calls to external services
- Store and retrieve data in a session (text, numbers, or boolean values)
- Generate images from text descriptions
When you ask me about files, I'll use the appropriate file operation tools.
When you ask me about weather, I'll look up the latest conditions.
When you want to store information for later, I'll use session storage.
When you ask me to create an image, I'll generate one based on your description.
""",
tools=[
# MCP file system tools
mcp_read_file,
mcp_write_file,
mcp_list_files,
mcp_delete_file,
# MCP API tools
mcp_call_api,
mcp_get_weather,
# MCP session tools
mcp_store_data,
mcp_store_number,
mcp_store_boolean,
mcp_retrieve_data,
# New image generation tool
mcp_generate_image # Add this tool
]
)
5. テストとデバッグ
cURL でツールを直接テストする
cURL を使用して、画像生成エンドポイントを直接テストします。
# First create a session
export SESSION=$(curl -X POST http://localhost:8080/api/session | jq -r '.sessionId')
# Then call the image generation endpoint
curl -X POST http://localhost:8080/api/session/$SESSION/image \
-H "Content-Type: application/json" \
-d '{
"prompt": "A beautiful sunset over mountains",
"style": "photorealistic"
}'
ADK Webhook 経由でテストする
ADK Webhook 経由で画像生成をテストします。
curl -X POST http://localhost:8080/api/adk-webhook \
-H "Content-Type: application/json" \
-d '{
"session_id": "test-session-123",
"tool_name": "image_generation",
"parameters": {
"prompt": "A beautiful sunset over mountains",
"style": "photorealistic"
},
"request_id": "test-request-1"
}'
エージェントを実行してツールをテストする
エージェントを実行し、プロンプトを使って画像生成ツールをテストします。
cd /mcp-server-google-adk-multi-tool-system
python -m mcp_agent.main
エージェントの実行中に、次を試してください。
You: Generate an image of a cat playing piano
6. 現在の統合の仕組み
システム内の既存の統合の仕組みを確認しましょう。
MCP サーバーのコンポーネント
-
セッション管理:
- 各クライアントに一意のセッション ID が割り当てられます
- セッションにはユーザーデータが保存され、有効期限は 30 分です
- セッションはメモリ内の Map を使って管理されます
-
ツールの実装:
- 各ツール(fileSystemTool、apiTool など)は、非同期関数として実装されます
- ツールは検証、処理、エラー処理を行います
- ツールは、
success、data、および任意のerrorフィールドを含む標準化されたレスポンスオブジェクトを返します
-
エンドポイント:
- 各ツールには専用のエンドポイントがあります(例:
/api/session/:sessionId/filesystem) - 中央の Webhook エンドポイント(
/api/adk-webhook)が Google ADK からのリクエストを処理します - Webhook エンドポイントは、
tool_nameに基づいてリクエストを適切なハンドラー関数に振り分けます
- 各ツールには専用のエンドポイントがあります(例:
-
Server-Sent Events(SSE):
/api/sse/:sessionIdエンドポイントはリアルタイム更新を可能にしますemitEvent関数は接続中のクライアントにイベントを送信します- クライアントは EventSource 接続を通じてイベントを受信できます
Google ADK エージェントのコンポーネント
-
MCPToolkit クラス:
- MCP サーバーとの通信を管理します
- セッションの作成と管理を行います
- 各ツール操作のメソッドを提供します
- リアルタイム更新のための SSE 接続を維持します
-
ツール関数:
- 各ツール関数(mcp_read_file、mcp_get_weather など)は、MCPToolkit のメソッドをラップします
- 関数は、適切なドキュメントと型ヒントを備えた Google ADK 形式に従います
- 関数は、
statusと追加フィールドを含む標準化されたレスポンスオブジェクトを返します
-
エージェントの定義:
- Google ADK SDK の Agent クラスがエージェントの機能を定義します
- エージェントはツール関数を登録し、指示を提供します
- エージェントはユーザー入力の NLU(自然言語理解)を処理します
-
メインランナー:
- エージェントとツールキットを初期化します
- イベントリスナーを設定します
- 会話ループを管理します
- エラー処理とクリーンアップを行います
コンポーネント間のデータフロー
-
ユーザーリクエストのフロー:
- ユーザーがエージェントにテキストクエリを送信します
- エージェントがクエリを処理し、適切なツールを判断します
- エージェントが抽出したパラメーターを使ってツール関数を呼び出します
- ツール関数が MCPToolkit メソッドを呼び出します
- MCPToolkit が MCP サーバーの Webhook にリクエストを送信します
- MCP サーバーがリクエストを処理し、結果を返します
- 結果は同じ経路を逆方向にたどって返されます
-
Server-Sent Events のフロー:
- MCP サーバーが操作を処理します
- サーバーが
emitEventを使ってイベントを送信します - SSE 接続がイベントをクライアントに伝送します
- MCPToolkit が
_sse_workerスレッドでイベントを受信します - イベントコールバックがイベントを処理します
概要
MCP サーバーと Google ADK エージェントに新しいツールを追加するには、次の主要な手順を実行します。
-
MCP サーバー:
- ツールの実装関数を作成します
- Webhook のハンドラー関数を追加します
- Webhook の switch 文を更新します
- 必要に応じて専用のエンドポイントを追加します
- API ドキュメントを更新します
-
Google ADK エージェント:
- MCPToolkit クラスにメソッドを追加します
- tools.py にツール関数を作成します
- エージェントにツールを登録します
- エージェントの指示を更新します
このガイドに従えば、MCP サーバーと Google ADK エージェントを新しいツールや機能で簡単に拡張できます。モジュール設計により、一貫したインターフェースとエラー処理の方針を維持しながら、新機能を簡単に追加できます。
著者:Andrew Milam [email protected]
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。