This repository contains the source code for the "Building Scalable AI Agents" playbook. It demonstrates how to build a decoupled, microservices-based AI agent system using the Agent Development Kit (ADK), the Model Context Protocol (MCP), and Google Cloud Run.
The project consists of two main components:
zoo_mcp_server_rust: A secure, private tool server built in Rust that exposes a simple API for getting information about zoo animals.zoo_adk_agent: A public-facing AI agent built with the Python ADK. It uses the Rust MCP server as a tool to answer user questions.
For a deeper dive into the concepts and benefits of building decoupled AI agents with the ADK and MCP, check out the companion blog post:
This article explores the production-grade advantages of implementing agentic Tools in separate, secure MCP servers.
Ready to build your own? The best way to solidify these concepts is to get
hands-on. Follow this step-by-step tutorial to deploy your own secure, remote MCP server on Google Cloud and start building a truly scalable tool ecosystem for your agents.
These instructions will guide you through deploying both services to Cloud Run.
- Google Cloud SDK (
gcloud) installed and authenticated. - Docker installed and running.
- A Google Cloud project with billing enabled.
First, configure your environment with your project ID and preferred region.
export PROJECT_ID=$(gcloud config get-value project)
export REGION="us-central1" # Or your preferred regionEnable the necessary APIs for Cloud Run, Artifact Registry, Cloud Build, and IAM.
gcloud services enable \
run.googleapis.com \
aiplatform.googleapis.com \
iam.googleapis.com \
artifactregistry.googleapis.com \
cloudbuild.googleapis.comThis command builds the Rust server's container image and deploys it as a private Cloud Run service.
gcloud run deploy zoo-mcp-server-rust \
--source ./zoo_mcp_server_rust \
--region=$REGION \
--no-allow-unauthenticatedThe ADK agent needs permission to invoke the private MCP server. This command
grants the agent's default service account the "Cloud Run Invoker" role for the
zoo-mcp-server-rust service.
# Get the default service account for the ADK agent
PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")
AGENT_SA="${PROJECT_NUMBER}-compute@developer.gserviceaccount.com"
# Grant the invoker role
gcloud run services add-iam-policy-binding zoo-mcp-server-rust \
--member="serviceAccount:${AGENT_SA}" \
--role="roles/run.invoker" \
--region=$REGIONThis command builds the Python agent's container and deploys it as a public Cloud Run service. It injects the private MCP server's URL as an environment variable.
# Get the URL of the deployed MCP server
MCP_URL=$(gcloud run services describe zoo-mcp-server-rust --region=$REGION --format="value(status.url)")
# Deploy the agent, passing the MCP server's URL
gcloud run deploy zoo-adk-agent \
--source ./zoo_adk_agent \
--region=$REGION \
--allow-unauthenticated \
--set-env-vars="GOOGLE_CLOUD_PROJECT=$PROJECT_ID,GOOGLE_CLOUD_LOCATION=$REGION,GOOGLE_GENAI_USE_VERTEXAI=TRUE,MCP_SERVER_URL=${MCP_URL}/mcp"Once both services are deployed, you can interact with the agent using curl.
# Get the agent's public URL
AGENT_URL=$(gcloud run services describe zoo-adk-agent --region=$REGION --format="value(status.url)")
# Initialize a session
curl -X POST $AGENT_URL/apps/zoo_tour_guide/users/user_123/sessions/session_abc \
-H "Content-Type: application/json"
# Send a prompt to the agent
curl -X POST $AGENT_URL/run_sse \
-H "Content-Type: application/json" \
-d '{
"app_name": "zoo_tour_guide",
"user_id": "user_123",
"session_id": "session_abc",
"new_message": {
"role": "user",
"parts": [{
"text": "Hello, tell me about the lions."
}]
},
"streaming": false
}'You should receive a JSON response from the agent containing details about lions, which it fetched securely from the Rust MCP server.
To avoid incurring future charges, delete the Cloud Run services.
gcloud run services delete zoo-mcp-server-rust --region=$REGION --quiet
gcloud run services delete zoo-adk-agent --region=$REGION --quiet