1. Introducción
Los agentes de IA solo son tan útiles como los datos a los que pueden acceder. La mayoría de los datos del mundo real se encuentran en bases de datos, y conectar agentes a bases de datos suele significar escribir la administración de conexiones, la lógica de consultas y las canalizaciones de incorporación dentro del código del agente. Cada agente que necesita acceso a la base de datos repite este trabajo, y cada cambio en la consulta requiere que se vuelva a implementar el agente.
En este codelab, se muestra un enfoque diferente. Declaras tus herramientas de bases de datos en un archivo YAML (consultas en SQL estándar, búsqueda de similitud de vectores y hasta generación automática de embeddings), y MCP Toolbox for Databases controla todas las operaciones de la base de datos como un servidor de MCP. El código del agente sigue siendo mínimo: carga las herramientas y deja que Gemini decida a cuál llamar.
Qué compilarás
Un asistente inteligente para la bolsa de trabajo de "TechJobs", un agente del ADK potenciado por Gemini que ayuda a los desarrolladores a explorar las ofertas de empleo en tecnología con filtros estándar (rol, pila de tecnología) y a descubrir trabajos a través de descripciones en lenguaje natural, como "Quiero un trabajo remoto en chatbots de IA". El agente lee y escribe en una base de datos de Cloud SQL PostgreSQL completamente a través de MCP Toolbox for Databases, que controla todo el acceso a la base de datos, incluida la generación automática de embeddings para la búsqueda de vectores. Al final, tanto la Toolbox como el agente se ejecutarán en Cloud Run.
Qué aprenderás
- Cómo el MCP (Protocolo de contexto del modelo) estandariza el acceso a las herramientas para los agentes de IA y cómo MCP Toolbox para bases de datos aplica esto a las operaciones de bases de datos
- Configura MCP Toolbox for Databases como middleware entre un agente de ADK y Cloud SQL PostgreSQL
- Define herramientas de bases de datos de forma declarativa en
tools.yaml: no hay código de base de datos en tu agente - Cómo compilar un agente del ADK que carga herramientas desde un servidor de Toolbox en ejecución con
ToolboxToolset - Genera embeddings de vectores con la función
embedding()integrada de Cloud SQL y habilita la búsqueda semántica conpgvector - Usa la función
valueFromParampara la incorporación automática de vectores en las operaciones de escritura - Implementa el servidor de Toolbox y el agente de ADK en Cloud Run
Requisitos previos
- Una cuenta de Google Cloud con una cuenta de facturación de prueba
- Conocimientos básicos de Python y SQL
- Será útil tener experiencia previa con Cloud Database y el ADK.
2. Configura tu entorno
En este paso, se prepara tu entorno de Cloud Shell, se configura tu proyecto de Google Cloud y se clona el repositorio de referencia.
Abra Cloud Shell
Abre Cloud Shell en tu navegador. Cloud Shell proporciona un entorno preconfigurado con todas las herramientas que necesitas para este codelab. Haz clic en Autorizar cuando se te solicite
Luego, haz clic en "Ver" -> "Terminal" para abrir la terminal.Tu interfaz debería verse similar a esta:

Esta será nuestra interfaz principal, con el IDE en la parte superior y la terminal en la parte inferior.
Configura tu directorio de trabajo
Crea tu directorio de trabajo. Todo el código que escribas en este codelab se encontrará aquí:
mkdir -p ~/build-agent-adk-toolbox-cloudsql
cloudshell workspace ~/build-agent-adk-toolbox-cloudsql && cd ~/build-agent-adk-toolbox-cloudsql
Luego, preparemos varios directorios para administrar elementos como los registros y las secuencias de comandos de inicialización.
mkdir -p ~/build-agent-adk-toolbox-cloudsql/scripts
mkdir -p ~/build-agent-adk-toolbox-cloudsql/logs
Configura el proyecto de Google Cloud
Crea el archivo .env con las variables de ubicación:
# For Vertex AI / Gemini API calls
echo "GOOGLE_CLOUD_LOCATION=global" > .env
# For Cloud SQL, Cloud Run, Artifact Registry
echo "REGION=us-central1" >> .env
Para simplificar la configuración del proyecto en tu terminal, descarga esta secuencia de comandos de configuración del proyecto en tu directorio de trabajo:
curl -sL https://raw.githubusercontent.com/alphinside/cloud-trial-project-setup/main/setup_verify_trial_project.sh -o setup_verify_trial_project.sh
Ejecuta la secuencia de comandos. Verifica tu cuenta de facturación de prueba, crea un proyecto nuevo (o valida uno existente), guarda el ID del proyecto en un archivo .env en el directorio actual y establece el proyecto activo en gcloud.
bash setup_verify_trial_project.sh && source .env
La secuencia de comandos hará lo siguiente:
- Verifica que tengas una cuenta de facturación de prueba activa
- Verifica si existe un proyecto en
.env(si corresponde) - Crea un proyecto nuevo o reutiliza el existente
- Vincula la cuenta de facturación de prueba a tu proyecto
- Guarda el ID del proyecto en
.env. - Configura el proyecto como el proyecto
gcloudactivo
Verifica que el proyecto esté configurado correctamente. Para ello, consulta el texto amarillo junto a tu directorio de trabajo en el mensaje de la terminal de Cloud Shell. Debería mostrar el ID de tu proyecto.

Activa la API requerida
A continuación, debemos habilitar varias APIs para el producto con el que interactuaremos:
gcloud services enable \
aiplatform.googleapis.com \
sqladmin.googleapis.com \
compute.googleapis.com \
run.googleapis.com \
cloudbuild.googleapis.com \
artifactregistry.googleapis.com
- API de Vertex AI (
aiplatform.googleapis.com): Tu agente usa modelos de Gemini, y Toolbox usa la API de Embedding para la búsqueda vectorial. - API de Cloud SQL Admin (
sqladmin.googleapis.com): Aprovisionas y administras una instancia de PostgreSQL. - API de Compute Engine (
compute.googleapis.com): Se requiere para crear instancias de Cloud SQL. - Cloud Run, Cloud Build y Artifact Registry: Se usan en el paso de implementación más adelante en este codelab.
3. Preparación de secuencias de comandos para la inicialización de la base de datos
En este paso, se inicia la creación de la instancia de Cloud SQL y se ejecuta una secuencia de comandos de configuración automatizada que espera a que la instancia esté lista, luego crea la base de datos, la inicializa con ofertas de empleo y genera incorporaciones, todo en una sola operación.
Primero, agreguemos la contraseña de la base de datos a tu archivo .env y vuelve a cargarlo:
echo "DB_PASSWORD=techjobs-pwd" >> .env
echo "DB_INSTANCE=jobs-instance" >> .env
echo "DB_NAME=jobs_db" >> .env
source .env
Crea una secuencia de comandos de Bash para la creación de instancias y bases de datos
Luego, crea el script scripts/setup_database.sh con el siguiente comando:
mkdir -p ~/build-agent-adk-toolbox-cloudsql/scripts
cloudshell edit scripts/setup_database.sh
Luego, copia el siguiente código en el archivo scripts/setup_database.sh.
#!/bin/bash
set -e
source .env
echo "================================================"
echo "Database Setup"
echo "================================================"
echo ""
# Step 1: Create Cloud SQL instance
echo "[1/5] Creating Cloud SQL instance..."
# Check if instance already exists
if gcloud sql instances describe "$DB_INSTANCE" --quiet >/dev/null 2>&1; then
echo " Instance already exists"
else
echo " Creating instance (takes 5-10 minutes)..."
gcloud sql instances create "$DB_INSTANCE" \
--database-version=POSTGRES_17 \
--tier=db-custom-1-3840 \
--edition=ENTERPRISE \
--region="$REGION" \
--root-password="$DB_PASSWORD" \
--enable-google-ml-integration \
--database-flags cloudsql.enable_google_ml_integration=on \
--quiet
fi
echo " ✓ Instance ready"
echo ""
# Step 2: Verify instance is ready
echo "[2/5] Verifying instance state..."
STATE=$(gcloud sql instances describe "$DB_INSTANCE" --format='value(state)')
if [ "$STATE" != "RUNNABLE" ]; then
echo "ERROR: Instance not ready (state: $STATE)"
exit 1
fi
echo " ✓ Instance is RUNNABLE"
echo ""
# Step 3: Grant IAM permissions
echo "[3/5] Granting Vertex AI permissions..."
SERVICE_ACCOUNT=$(gcloud sql instances describe "$DB_INSTANCE" \
--format='value(serviceAccountEmailAddress)')
if [ -z "$SERVICE_ACCOUNT" ]; then
echo "ERROR: Could not retrieve service account"
exit 1
fi
gcloud projects add-iam-policy-binding "$GOOGLE_CLOUD_PROJECT" \
--member="serviceAccount:$SERVICE_ACCOUNT" \
--role="roles/aiplatform.user" \
--quiet
echo " ✓ Permissions granted"
echo ""
# Step 4: Create database
echo "[4/5] Creating database..."
# Check if database already exists
if gcloud sql databases describe "$DB_NAME" \
--instance="$DB_INSTANCE" --quiet >/dev/null 2>&1; then
echo " Database already exists"
else
gcloud sql databases create "$DB_NAME" \
--instance="$DB_INSTANCE" \
--quiet
fi
echo " ✓ Database '$DB_NAME' ready"
echo ""
# Step 5: Seed database and generate embeddings
echo "[5/5] Seeding database and generating embeddings..."
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SETUP_SCRIPT="${SCRIPT_DIR}/setup_jobs_db.py"
if [ ! -f "$SETUP_SCRIPT" ]; then
echo "ERROR: Setup script not found: $SETUP_SCRIPT"
exit 1
fi
uv run "$SETUP_SCRIPT"
echo ""
echo "================================================"
echo "Setup complete!"
echo "================================================"
echo ""
Cómo crear una secuencia de comandos de Python para la inicialización de datos
Después de eso, crea el archivo de Python de la secuencia de comandos de inicialización scripts/setup_jobs_db.py con el siguiente comando.
cloudshell edit scripts/setup_jobs_db.py
Luego, copia el siguiente código en el archivo scripts/setup_jobs_db.py.
import os
import sys
from pathlib import Path
from dotenv import load_dotenv
from google.cloud.sql.connector import Connector
import pg8000
import time
# Load environment variables from .env file
env_path = Path(__file__).parent.parent / '.env'
load_dotenv(env_path)
EMBEDDING_MODEL='gemini-embedding-001'
# Verify required environment variables
required_vars = ['GOOGLE_CLOUD_PROJECT', 'REGION', 'DB_PASSWORD']
missing_vars = [var for var in required_vars if not os.environ.get(var)]
if missing_vars:
print(f"ERROR: Missing required environment variables: {', '.join(missing_vars)}", file=sys.stderr)
print(f"", file=sys.stderr)
print(f"Expected .env file location: {env_path}", file=sys.stderr)
if not env_path.exists():
print(f"✗ File not found at that location", file=sys.stderr)
else:
print(f"✓ File exists but is missing the variables above", file=sys.stderr)
print(f"", file=sys.stderr)
print(f"Make sure your .env file contains:", file=sys.stderr)
for var in missing_vars:
print(f" {var}=<value>", file=sys.stderr)
sys.exit(1)
# Job listings data (fictional, for tutorial purposes only)
JOBS = [
("Senior Backend Engineer", "Stripe", "Backend", "Go, PostgreSQL, gRPC, Kubernetes", "$180-250K/year", "San Francisco, Hybrid", 3,
"Design and build high-throughput microservices powering payment infrastructure for millions of businesses. Optimize Go services for sub-100ms latency at scale, work with PostgreSQL and Redis for data persistence, and deploy on Kubernetes clusters handling billions of API calls."),
("Machine Learning Engineer", "Spotify", "Data/AI", "Python, TensorFlow, BigQuery, Vertex AI", "$170-230K/year", "Stockholm, Remote", 2,
"Build and deploy ML models for music recommendation and personalization systems serving hundreds of millions of listeners. Design feature pipelines in BigQuery, train models using distributed computing, and serve predictions through real-time APIs processing thousands of requests per second."),
("Frontend Engineer", "Vercel", "Frontend", "React, TypeScript, Next.js", "$140-190K/year", "Remote", 4,
"Build developer-facing dashboard interfaces and deployment tools used by millions of developers worldwide. Create responsive, accessible React components for project management, analytics, and real-time deployment monitoring with a focus on developer experience."),
("DevOps Engineer", "Datadog", "DevOps", "Terraform, GCP, Docker, Kubernetes, ArgoCD", "$160-220K/year", "New York, Hybrid", 2,
"Manage cloud infrastructure powering an observability platform used by thousands of engineering teams. Automate deployment pipelines with ArgoCD, manage multi-cloud Kubernetes clusters, and implement infrastructure-as-code with Terraform across production environments."),
("Mobile Engineer (Android)", "Grab", "Mobile", "Kotlin, Jetpack Compose, GraphQL", "$120-170K/year", "Singapore, Hybrid", 3,
"Develop features for a super-app serving millions of users across Southeast Asia. Build modern Android UIs with Jetpack Compose, integrate GraphQL APIs, and optimize app performance for diverse device capabilities and network conditions."),
("Data Engineer", "Airbnb", "Data", "Python, Apache Spark, Airflow, BigQuery", "$160-210K/year", "San Francisco, Hybrid", 2,
"Build data pipelines that process booking, search, and pricing data for a global travel marketplace. Design ETL workflows with Apache Spark and Airflow, maintain data warehouses in BigQuery, and ensure data quality for analytics and machine learning teams."),
("Full Stack Engineer", "Revolut", "Full Stack", "TypeScript, Node.js, React, PostgreSQL", "$130-180K/year", "London, Remote", 5,
"Build the next generation of financial products making banking accessible to millions of users across 35 countries. Develop real-time trading interfaces with React and WebSockets, build Node.js APIs handling market data streams, and design PostgreSQL schemas for financial transactions."),
("Site Reliability Engineer", "Cloudflare", "SRE", "Go, Prometheus, Grafana, GCP, Terraform", "$170-230K/year", "Austin, Hybrid", 2,
"Ensure 99.99% uptime for a global network handling millions of requests per second. Define SLOs, build monitoring dashboards with Prometheus and Grafana, manage incident response, and automate infrastructure scaling across 300+ data centers worldwide."),
("Cloud Architect", "Google Cloud", "Cloud", "GCP, Terraform, Kubernetes, Python", "$200-280K/year", "Seattle, Hybrid", 1,
"Help enterprises modernize their infrastructure on Google Cloud. Design multi-region architectures, lead migration projects from on-premises to GKE, and build reference implementations using Terraform and Cloud Foundation Toolkit."),
("Backend Engineer (Payments)", "Square", "Backend", "Java, Spring Boot, PostgreSQL, Kafka", "$160-220K/year", "San Francisco, Hybrid", 3,
"Build payment processing systems handling millions of transactions for businesses of all sizes. Design event-driven architectures using Kafka, implement idempotent payment flows with Spring Boot, and ensure PCI-DSS compliance across all services."),
("AI Engineer", "Hugging Face", "Data/AI", "Python, LangChain, Vertex AI, FastAPI, PostgreSQL", "$150-210K/year", "Paris, Remote", 2,
"Build AI-powered tools for the largest open-source ML community. Develop RAG pipelines that index and search model documentation, create conversational agents using LangChain, and deploy AI services with FastAPI on cloud infrastructure."),
("Platform Engineer", "Coinbase", "Platform", "Rust, Kubernetes, AWS, Terraform", "$180-250K/year", "Remote", 0,
"Build the infrastructure platform for a leading cryptocurrency exchange. Develop high-performance matching engines in Rust, manage Kubernetes clusters for microservices, and design CI/CD pipelines that enable rapid feature deployment with zero downtime."),
("QA Automation Engineer", "Shopify", "QA", "Python, Selenium, Cypress, Jenkins", "$110-160K/year", "Toronto, Hybrid", 3,
"Design and maintain automated test suites for a commerce platform powering millions of merchants. Build end-to-end test frameworks with Cypress and Selenium, integrate tests into Jenkins CI pipelines, and establish quality gates that prevent regressions in checkout and payment flows."),
("Security Engineer", "CrowdStrike", "Security", "Python, SIEM, Kubernetes, Penetration Testing", "$170-240K/year", "Austin, On-site", 1,
"Protect enterprise customers from cyber threats on a leading endpoint security platform. Conduct penetration testing, design security monitoring with SIEM tools, implement zero-trust networking in Kubernetes environments, and lead incident response for security events."),
("Product Engineer", "GitLab", "Full Stack", "Go, React, PostgreSQL, Redis, GCP", "$140-200K/year", "Remote", 4,
"Own features end-to-end for an all-in-one DevSecOps platform used by millions of developers. Build Go microservices for CI/CD pipelines, create React frontends for code review and project management, and collaborate with product managers to iterate on user-facing features using data-driven development."),
]
def get_connection():
"""Create a connection to Cloud SQL using the connector."""
project = os.environ['GOOGLE_CLOUD_PROJECT']
region = os.environ['REGION']
password = os.environ['DB_PASSWORD']
instance = os.environ['DB_INSTANCE']
database = os.environ['DB_NAME']
connector = Connector()
conn = connector.connect(
f"{project}:{region}:{instance}",
"pg8000",
user="postgres",
password=password,
db=database
)
return conn, connector
def create_schema(cursor):
"""Create extensions and jobs table."""
cursor.execute("CREATE EXTENSION IF NOT EXISTS google_ml_integration")
cursor.execute("CREATE EXTENSION IF NOT EXISTS vector")
cursor.execute("""
CREATE TABLE IF NOT EXISTS jobs (
id SERIAL PRIMARY KEY,
title VARCHAR NOT NULL,
company VARCHAR NOT NULL,
role VARCHAR NOT NULL,
tech_stack VARCHAR NOT NULL,
salary_range VARCHAR NOT NULL,
location VARCHAR NOT NULL,
openings INTEGER NOT NULL,
description TEXT NOT NULL,
description_embedding vector(3072)
)
""")
def seed_jobs(cursor, conn):
"""Insert job listings."""
cursor.execute("SELECT COUNT(*) FROM jobs")
existing_count = cursor.fetchone()[0]
if existing_count > 0:
print(f" {existing_count} jobs already exist, skipping seed")
return 0
cursor.executemany("""
INSERT INTO jobs (title, company, role, tech_stack, salary_range, location, openings, description)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
""", JOBS)
conn.commit()
return len(JOBS)
def generate_embeddings(cursor, conn):
"""Generate embeddings using Cloud SQL's embedding() function."""
cursor.execute("SELECT COUNT(*) FROM jobs WHERE description_embedding IS NULL")
null_count = cursor.fetchone()[0]
if null_count == 0:
print(" All jobs already have embeddings")
return 0
cursor.execute(f"""
UPDATE jobs
SET description_embedding = embedding('{EMBEDDING_MODEL}', description)::vector
WHERE description_embedding IS NULL
""")
rows_updated = cursor.rowcount
conn.commit()
return rows_updated
def main():
conn, connector = get_connection()
cursor = conn.cursor()
try:
create_schema(cursor)
conn.commit()
seeded = seed_jobs(cursor, conn)
if seeded > 0:
print(f" ✓ Inserted {seeded} jobs")
# Waiting for vertex role propagation
time.sleep(60)
embedded = generate_embeddings(cursor, conn)
if embedded > 0:
print(f" ✓ Generated {embedded} embeddings")
except Exception as e:
print(f"ERROR: {e}", file=sys.stderr)
sys.exit(1)
finally:
cursor.close()
conn.close()
connector.close()
if __name__ == "__main__":
main()
Ahora, pasemos al siguiente paso.
4. Crea e inicializa la base de datos
Ahora nuestros secuencias de comandos están listos para ejecutarse. Necesitaremos Python para ejecutar nuestra secuencia de comandos preparada, así que primero prepararemos eso.
Configura el proyecto de Python
uv es un administrador de proyectos y paquetes de Python rápido escrito en Rust ( documentación de uv). Este codelab lo usa para mantener el proyecto de Python de forma rápida y sencilla.
Inicializa un proyecto de Python y agrega las dependencias necesarias:
uv init
uv add cloud-sql-python-connector --extra pg8000
uv add python-dotenv
Ten en cuenta que aquí usamos el SDK de Python de cloud-sql-python-connector para inicializar una conexión segura con nuestra instancia de base de datos, que se autentica con las credenciales predeterminadas de la aplicación.
Ejecuta la secuencia de comandos de configuración
Ahora, podemos ejecutar la secuencia de comandos de configuración en segundo plano y, luego, inspeccionar el resultado de la consola que se escribirá en el archivo logs/atabase_setup.log con el siguiente comando. Puedes continuar con la siguiente sección mientras esperas que finalice este proceso.
mkdir -p ~/build-agent-adk-toolbox-cloudsql/logs
bash scripts/setup_database.sh > logs/database_setup.log 2>&1 &
Descarga el objeto binario de Toolbox
En este instructivo, utilizaremos MCP Toolbox, que, afortunadamente, incluye un objeto binario compilado previamente que está listo para usarse en el entorno de Linux. Ahora, descarguémoslo en segundo plano, ya que tardará un poco. Ejecuta el siguiente comando para descargar el objeto binario y, luego, inspecciona el registro de salida en logs/toolbox_dl.log . Puedes continuar con la siguiente sección mientras esperas que finalice este proceso.
cd ~/build-agent-adk-toolbox-cloudsql
curl -O https://storage.googleapis.com/mcp-toolbox-for-databases/v1.0.0/linux/amd64/toolbox > logs/toolbox_dl.log 2>&1 &
Información sobre la secuencia de comandos de configuración scripts/setup_database.sh
Ahora, intentemos comprender la secuencia de comandos de configuración que configuramos anteriormente. Realiza el siguiente proceso:
- El primer comando que ejecutamos allí es el comando
gcloud sql instances createcon la siguiente marca
db-custom-1-3840es el nivel de Cloud SQL de núcleos dedicados más pequeño (1 CPU virtual, 3.75 GB de RAM) en la ediciónENTERPRISE. Puedes obtener más información aquí. Se requiere un núcleo dedicado para la integración de AA de Vertex AI. Los niveles de núcleos compartidos (db-f1-micro,db-g1-small) no son compatibles con esta integración.--root-passwordestablece la contraseña para el usuariopostgrespredeterminado.--enable-google-ml-integrationhabilita la integración integrada de Cloud SQL con Vertex AI, lo que te permite llamar a modelos de embedding directamente desde SQL con la funciónembedding().
- Verifica si la instancia ya está en estado
RUNNABLE. - Otorga permiso a la cuenta de servicio de la instancia de Cloud SQL para llamar a Vertex AI con el comando
gcloud projects add-iam-policy-binding. Esto es necesario para la funciónembedding()integrada que usaremos cuando inicialicemos la base de datos. - Crea la base de datos
- Ejecuta la secuencia de comandos de inicialización
setup_jobs_db.py
Información sobre la secuencia de comandos de inicialización scripts/setup_jobs_db.py
Ahora, pasando a la secuencia de comandos de inicialización, esta secuencia de comandos hace lo siguiente:
- Inicializa la conexión a la instancia de la base de datos
- Instala dos extensiones de PostgreSQL:
google_ml_integration: Proporciona la funciónembedding()SQL, que llama a los modelos de incorporación de Vertex AI directamente desde SQL. Esta es una extensión a nivel de la base de datos que hace que las funciones de AA estén disponibles dentro dejobs_db. La marca a nivel de la instancia (--enable-google-ml-integration) que estableces durante la creación de la instancia permite que la VM de Cloud SQL llegue a Vertex AI. La extensión hace que las funciones de SQL estén disponibles dentro de esta base de datos específica.vector(pgvector): Agrega el tipo de datosvectory los operadores de distancia para almacenar y consultar incorporaciones.
- Crea la tabla y observa que la columna
description_embeddingesvector(3072), una columnapgvectorque almacena vectores de 3,072 dimensiones. - Propaga los datos de los trabajos iniciales
- Genera los datos de incorporación del campo
descriptiony completa el campodescription_embeddingcon la integración de Vertex integrada a través de la funciónembedding().
embedding('gemini-embedding-001', description): Llama al modelo de embedding de Gemini de Vertex AI directamente desde SQL y pasa el textodescriptionde cada trabajo. Esta es la extensióngoogle_ml_integrationque instalaste en la secuencia de comandos inicial.::vector: Convierte el array de números de punto flotante devuelto al tipovectorde pgvector para que se pueda almacenar y consultar con operadores de distancia.- El
UPDATEse ejecuta en las 15 filas y genera una incorporación de 3, 072 dimensiones por descripción del empleo.
Esto preparará los datos iniciales a los que accederá nuestro agente.
5. Configura MCP Toolbox para bases de datos
En este paso, se presenta MCP Toolbox for Databases, se configura para que se conecte a tu instancia de Cloud SQL y se definen dos herramientas de consultas SQL estándar.
¿Qué es el MCP y por qué usar Toolbox?

El MCP (Protocolo de contexto del modelo) es un protocolo abierto que estandariza la forma en que los agentes de IA descubren herramientas externas y cómo interactúan con ellas. Define un modelo cliente-servidor: el agente aloja un cliente de MCP y los servidores de MCP exponen las herramientas. Cualquier cliente compatible con MCP puede usar cualquier servidor compatible con MCP. El agente no necesita código de integración personalizado para cada herramienta.

MCP Toolbox for Databases es un servidor de MCP de código abierto creado específicamente para el acceso a bases de datos. Sin él, escribirías funciones de Python que abren conexiones de bases de datos, administran grupos de conexiones, construyen consultas parametrizadas para evitar la inyección de SQL, controlan errores y, luego, incorporan todo ese código dentro de tu agente. Cada agente que necesita acceso a la base de datos repite este trabajo. Cambiar una pregunta significa volver a implementar el agente.
Con Toolbox, escribes un archivo YAML. Cada herramienta se asigna a una instrucción de SQL con parámetros. Toolbox controla la reducción de conexiones, las consultas parametrizadas, la autenticación y la observabilidad. Las herramientas están desacopladas del agente: actualiza una búsqueda editando tools.yaml y reiniciando Toolbox, sin tocar el código del agente. Las mismas herramientas funcionan en ADK, LangGraph, LlamaIndex o cualquier framework compatible con MCP.
Escribe la configuración de las herramientas
Ahora, debemos crear un archivo llamado tools.yaml en el editor de Cloud Shell para configurar nuestras herramientas.
cloudshell edit tools.yaml
El archivo usa YAML de varios documentos: cada bloque separado por --- es un recurso independiente. Cada recurso tiene un kind que declara lo que es (sources para las conexiones de bases de datos, tools para las acciones que puede llamar el agente) y un type que especifica el backend (cloud-sql-postgres para la fuente, postgres-sql para las herramientas basadas en SQL). Una herramienta hace referencia a su fuente por medio de name, que es la forma en que Toolbox sabe con qué grupo de conexiones debe ejecutar la herramienta. Las variables de entorno usan la sintaxis de ${VAR_NAME} y se resuelven en el inicio.
Ahora, primero copiemos las siguientes secuencias de comandos en el archivo tools.yaml.
# tools.yaml
# --- Data Source ---
kind: source
name: jobs-db
type: cloud-sql-postgres
project: ${GOOGLE_CLOUD_PROJECT}
region: ${REGION}
instance: ${DB_INSTANCE}
database: ${DB_NAME}
user: postgres
password: ${DB_PASSWORD}
---
Esta secuencia de comandos define el siguiente recurso:
- Fuente (
jobs-db): Indica a Toolbox cómo conectarse a tu instancia de Cloud SQL para PostgreSQL. El tipocloud-sql-postgresusa el conector de Cloud SQL de forma interna, lo que controla la autenticación y las conexiones seguras de forma automática. Los marcadores de posición${GOOGLE_CLOUD_PROJECT},${REGION}y${DB_PASSWORD}se resuelven a partir de las variables de entorno en el inicio.
A continuación, agrega la siguiente secuencia de comandos debajo del símbolo --- en tools.yaml.
# --- Tool 1: Search jobs by role and/or tech stack ---
kind: tool
name: search-jobs
type: postgres-sql
source: jobs-db
description: >-
Search for job listings by role category and/or tech stack.
Use this tool when the developer wants to browse listings
by role (e.g., Backend, Frontend, Data) or find jobs
using a specific technology. Both parameters accept an
empty string to match all values.
statement: |
SELECT title, company, role, tech_stack, salary_range, location, openings
FROM jobs
WHERE ($1 = '' OR LOWER(role) = LOWER($1))
AND ($2 = '' OR LOWER(tech_stack) LIKE '%' || LOWER($2) || '%')
ORDER BY title
LIMIT 10
parameters:
- name: role
type: string
description: "The role category to filter by (e.g., 'Backend', 'Frontend', 'Data/AI', 'DevOps'). Use empty string for all roles."
- name: tech_stack
type: string
description: "A technology to search for in the tech stack (partial match, e.g., 'Python', 'Kubernetes'). Use empty string for all tech stacks."
---
# --- Tool 2: Get full details for a specific job ---
kind: tool
name: get-job-details
type: postgres-sql
source: jobs-db
description: >-
Get full details for a specific job listing including its description,
salary range, location, and number of openings. Use this tool when the
developer asks about a particular job by title or company.
statement: |
SELECT title, company, role, tech_stack, salary_range, location, openings, description
FROM jobs
WHERE LOWER(title) LIKE '%' || LOWER($1) || '%'
OR LOWER(company) LIKE '%' || LOWER($1) || '%'
parameters:
- name: search_term
type: string
description: "The job title or company name to look up (partial match supported)."
---
Esta secuencia de comandos define el siguiente recurso:
- Herramientas 1 y 2 (
search-jobs,get-job-details): Herramientas de consultas de SQL estándar. Cada uno asigna un nombre de herramienta (lo que ve el agente) a una instrucción SQL parametrizada (lo que ejecuta la base de datos). Los parámetros usan marcadores de posición posicionales$1y$2. Toolbox ejecuta estas instrucciones como instrucciones preparadas, lo que evita la inyección de SQL.
Continuemos. Agrega la siguiente secuencia de comandos debajo del símbolo --- en tools.yaml.
# --- Embedding Model ---
kind: embeddingModel
name: gemini-embedding
type: gemini
model: gemini-embedding-001
project: ${GOOGLE_CLOUD_PROJECT}
location: ${GOOGLE_CLOUD_LOCATION}
dimension: 3072
---
Esta secuencia de comandos define el siguiente recurso:
- Modelo de embedding (
gemini-embedding): Configura Toolbox para llamar al modelogemini-embedding-001de Gemini y generar embeddings de texto de 3,072 dimensiones. Toolbox usa las credenciales predeterminadas de la aplicación (ADC) para la autenticación. No se necesita una clave de API en Cloud Shell ni en Cloud Run. Indica que estedimensionconfigurado aquí debe ser el mismo que configuramos anteriormente para inicializar la base de datos.
Continuemos. Agrega la siguiente secuencia de comandos debajo del símbolo --- en tools.yaml.
# --- Tool 3: Semantic search by description ---
kind: tool
name: search-jobs-by-description
type: postgres-sql
source: jobs-db
description: >-
Find jobs that match a natural language description of what the developer
is looking for. Use this tool when the developer describes their ideal job
using interests, work style, career goals, or project type rather than a
specific role or tech stack. Examples: "I want to work on AI chatbots,"
"a remote job at a fintech startup," "something involving infrastructure
and reliability."
statement: |
SELECT title, company, role, tech_stack, salary_range, location, description
FROM jobs
WHERE description_embedding IS NOT NULL
ORDER BY description_embedding <=> $1
LIMIT 5
parameters:
- name: search_query
type: string
description: "A natural language description of the kind of job the developer is looking for."
embeddedBy: gemini-embedding
---
Esta secuencia de comandos define el siguiente recurso:
- Herramienta 3 (
search-jobs-by-description): Es una herramienta de búsqueda de vectores. El parámetrosearch_querytieneembeddedBy: gemini-embedding, que le indica a Toolbox que intercepte el texto sin procesar, lo envíe al modelo de embedding y use el vector resultante en la sentencia SQL. El operador<=>es la distancia de coseno de pgvector. Los valores más pequeños significan descripciones más similares.
Por último, agrega la última herramienta debajo del símbolo --- en tools.yaml.
# --- Tool 4: Add a new job listing with automatic embedding ---
kind: tool
name: add-job
type: postgres-sql
source: jobs-db
description: >-
Add a new job listing to the platform. Use this tool when a user asks
to post a job that is not currently listed.
statement: |
INSERT INTO jobs (title, company, role, tech_stack, salary_range, location, openings, description, description_embedding)
VALUES ($1, $2, $3, $4, $5, $6, CAST($7 AS INTEGER), $8, $9)
RETURNING title, company
parameters:
- name: title
type: string
description: "The job title (e.g., 'Senior Backend Engineer')."
- name: company
type: string
description: "The company name (e.g., 'Stripe', 'Spotify')."
- name: role
type: string
description: "The role category (e.g., 'Backend', 'Frontend', 'Data/AI', 'DevOps')."
- name: tech_stack
type: string
description: "Comma-separated list of technologies (e.g., 'Python, FastAPI, GCP')."
- name: salary_range
type: string
description: "The salary range (e.g., '$150-200K/year')."
- name: location
type: string
description: "Work location and arrangement (e.g., 'Remote')."
- name: openings
type: string
description: "The number of open positions."
- name: description
type: string
description: "A short description of the job (2-3 sentences)."
- name: description_vector
type: string
description: "Auto-generated embedding vector for the job description."
valueFromParam: description
embeddedBy: gemini-embedding
Esta secuencia de comandos define el siguiente recurso:
- Tool 4 (
add-job): Demuestra la transferencia de vectores. El parámetrodescription_vectortiene dos campos especiales: valueFromParam: description: Toolbox copia el valor del parámetrodescriptionen este. El LLM nunca ve este parámetro.embeddedBy: gemini-embedding: La Caja de herramientas incorpora el texto copiado en un vector antes de pasarlo a SQL.
El resultado es que una llamada a la herramienta almacena tanto el texto de la descripción sin procesar como su incorporación vectorial, sin que el agente sepa nada sobre las incorporaciones.
El formato YAML de varios documentos separa cada recurso con ---. Cada documento tiene campos kind, name y type que definen qué es. En resumen, ya configuramos todo lo siguiente:
- Define la base de datos de origen
- Define herramientas ( herramienta 1 y 2) para consultar la base de datos con un filtro estándar
- Define el modelo de embedding
- Define la herramienta para realizar la búsqueda de vectores ( herramienta 3) en la base de datos.
- Define la herramienta para transferir datos vectoriales ( herramienta 4) a la base de datos
6. Ejecuta el servidor de MCP Toolbox
En el paso anterior, ya establecimos la configuración necesaria para nuestra MCP Toolbox. Ahora, ya podemos ejecutar el servidor.
Verifica los datos iniciales
Antes de iniciar Toolbox, confirmemos que se completó la configuración de la base de datos. Crea una secuencia de comandos de Python scripts/verify_database.py con el siguiente comando:
cloudshell edit scripts/verify_seed.py
Luego, copia el siguiente código en el archivo scripts/verify_seed.py.
#!/usr/bin/env python3
"""Verify the database has 15 jobs with embeddings."""
import os
import sys
from pathlib import Path
from dotenv import load_dotenv
from google.cloud.sql.connector import Connector
import pg8000
# Load environment variables
env_path = Path(__file__).parent.parent / '.env'
load_dotenv(env_path)
# Verify required environment variables
required_vars = ['GOOGLE_CLOUD_PROJECT', 'REGION', 'DB_PASSWORD', 'DB_INSTANCE', 'DB_NAME']
missing_vars = [var for var in required_vars if not os.environ.get(var)]
if missing_vars:
print(f"ERROR: Missing environment variables: {', '.join(missing_vars)}", file=sys.stderr)
sys.exit(1)
def verify_database():
"""Check that 15 jobs exist with embeddings."""
connector = Connector()
try:
project = os.environ['GOOGLE_CLOUD_PROJECT']
region = os.environ['REGION']
password = os.environ['DB_PASSWORD']
instance = os.environ['DB_INSTANCE']
database = os.environ['DB_NAME']
conn = connector.connect(
f"{project}:{region}:{instance}",
"pg8000",
user="postgres",
password=password,
db=database
)
cursor = conn.cursor()
# Count jobs and embeddings
cursor.execute("SELECT COUNT(*) FROM jobs")
job_count = cursor.fetchone()[0]
cursor.execute("SELECT COUNT(*) FROM jobs WHERE description_embedding IS NOT NULL")
embedding_count = cursor.fetchone()[0]
print(f"Jobs: {job_count}/15")
print(f"Embeddings: {embedding_count}/15")
cursor.close()
conn.close()
if job_count == 15 and embedding_count == 15:
print("\n✓ Database ready!")
return True
else:
print("\n✗ Database not ready")
return False
except Exception as e:
print(f"\nERROR: {e}", file=sys.stderr)
return False
finally:
connector.close()
if __name__ == "__main__":
success = verify_database()
sys.exit(0 if success else 1)
Esta secuencia de comandos verificará la cantidad de datos de las publicaciones de empleo y su incorporación. Ejecuta la secuencia de comandos con el siguiente comando
uv run scripts/verify_seed.py
Si ves el siguiente resultado en la terminal, significa que los datos están listos.
Jobs: 15/15 Embeddings: 15/15 ✓ Database ready!
Inicia el servidor de Toolbox
En el paso de configuración anterior, ya descargamos el ejecutable toolbox. Asegúrate de que este archivo binario exista y se haya descargado correctamente. Si no es así, descárgalo y espera a que finalice el proceso.
cd ~/build-agent-adk-toolbox-cloudsql
if [ ! -f toolbox ]; then
curl -O https://storage.googleapis.com/mcp-toolbox-for-databases/v1.0.0/linux/amd64/toolbox
fi
chmod +x toolbox
Tendremos que exponer nuestras variables .env al proceso secundario que ejecuta la caja de herramientas de MCP. Ejecuta el siguiente comando para iniciar el servidor de la caja de herramientas y registrar su salida de la consola en el archivo logs/mcp_toolbox.log.
set -a; source .env; set +a
./toolbox --config tools.yaml --enable-api > logs/mcp_toolbox.log 2>&1 &
Deberías ver un resultado en el archivo logs/mcp_toolbox.log que confirme que el servidor está listo, como se muestra a continuación:
... INFO "Initialized 1 sources: jobs-db" ... INFO "Initialized 0 authServices: " ... INFO "Using Vertex AI backend for Gemini embedding" ... INFO "Initialized 1 embeddingModels: gemini-embedding" ... INFO "Initialized 4 tools: add-job, search-jobs, get-job-details, search-jobs-by-description" ... ... INFO "Server ready to serve!"
Verifica las herramientas
Consulta la API de Toolbox para enumerar todas las herramientas registradas:
curl -s http://localhost:5000/api/toolset | uv run -m json.tool
Deberías ver las herramientas con sus descripciones y parámetros. Como se muestra a continuación
...
"search-jobs-by-description": {
"description": "Find jobs that match a natural language description of what the developer is looking for. Use this tool when the developer describes their ideal job using interests, work style, career goals, or project type rather than a specific role or tech stack. Examples: \"I want to work on AI chatbots,\" \"a remote job at a fintech startup,\" \"something involving infrastructure and reliability.\"",
"parameters": [
{
"name": "search_query",
"type": "string",
"required": true,
"description": "A natural language description of the kind of job the developer is looking for.",
"authSources": []
}
],
"authRequired": []
}
...
Prueba la herramienta de search-jobs directamente:
curl -s -X POST http://localhost:5000/api/tool/search-jobs/invoke \
-H "Content-Type: application/json" \
-d '{"role": "Backend", "tech_stack": ""}' | jq '.result | fromjson'
La respuesta debe contener los dos trabajos de ingeniería de backend de tus datos iniciales.
[
{
"title": "Backend Engineer (Payments)",
"company": "Square",
"role": "Backend",
"tech_stack": "Java, Spring Boot, PostgreSQL, Kafka",
"salary_range": "$160-220K/year",
"location": "San Francisco, Hybrid",
"openings": 3
},
{
"title": "Senior Backend Engineer",
"company": "Stripe",
"role": "Backend",
"tech_stack": "Go, PostgreSQL, gRPC, Kubernetes",
"salary_range": "$180-250K/year",
"location": "San Francisco, Hybrid",
"openings": 3
}
]
7. Compila el agente del ADK
Ahora utilizaremos el ADK en Python para este proyecto. Agreguemos las dependencias necesarias:
uv add google-adk==1.29.0 toolbox-adk==1.0.0
google-adk: Kit de desarrollo de agentes de Google, incluido el SDK de Geminitoolbox-adk: Integración del ADK para MCP Toolbox for Databases.
Crea la estructura de directorios del agente
El ADK espera un diseño de carpeta específico: un directorio con el nombre de tu agente que contenga __init__.py, agent.py y .env. Para ayudarte con esto, tiene un comando integrado para establecer rápidamente la estructura:
uv run adk create jobs_agent \
--model gemini-2.5-flash \
--project ${GOOGLE_CLOUD_PROJECT} \
--region ${GOOGLE_CLOUD_LOCATION}
Ahora, tu directorio debería verse así:
build-agent-adk-toolbox-cloudsql/ ├── jobs_agent/ │ ├── __init__.py │ ├── agent.py │ └── .env ├── logs ├── scripts └── ...
A continuación, deberemos integrar el agente del ADK al servidor de Toolbox en ejecución y probar las cuatro herramientas: consultas estándar, búsqueda semántica y transferencia de vectores. El código del agente es mínimo: toda la lógica de la base de datos reside en tools.yaml.
Configura el entorno del agente
El ADK lee GOOGLE_GENAI_USE_VERTEXAI, GOOGLE_CLOUD_PROJECT y GOOGLE_CLOUD_LOCATION del entorno de shell, que ya configuraste en el paso anterior. La única variable específica del agente es TOOLBOX_URL. Agrégala al archivo .env del agente:
echo -e "\nTOOLBOX_URL=http://127.0.0.1:5000" >> jobs_agent/.env
Actualiza el módulo del agente
Abre jobs_agent/agent.py en el editor de Cloud Shell.
cloudshell edit jobs_agent/agent.py
y reemplaza el contenido con el siguiente código:
# jobs_agent/agent.py
import os
from google.adk.agents import LlmAgent
from toolbox_adk import ToolboxToolset
TOOLBOX_URL = os.environ.get("TOOLBOX_URL", "http://127.0.0.1:5000")
toolbox = ToolboxToolset(TOOLBOX_URL)
root_agent = LlmAgent(
name="jobs_agent",
model="gemini-2.5-flash",
instruction="""You are a helpful assistant at "TechJobs," a tech job listing platform.
Your job:
- Help developers browse job listings by role or tech stack.
- Provide full details about specific positions, including salary range and number of openings.
- Recommend jobs based on natural language descriptions of what the developer is looking for.
- Add new job listings to the platform when asked.
When a developer asks about a specific job by title or company, use the get-job-details tool.
When a developer asks for a specific role category or tech stack, use the search-jobs tool.
When a developer describes what kind of job they want — by interest area, work style,
career goals, or project type — use the search-jobs-by-description tool for semantic search.
When in doubt between search-jobs and search-jobs-by-description, prefer
search-jobs-by-description — it searches job descriptions and finds more relevant matches.
If a position has no openings (openings is 0), let the developer know
and suggest similar alternatives from the search results.
Be conversational, knowledgeable, and concise.""",
tools=[toolbox],
)
Ten en cuenta que aquí no hay código de base de datos: ToolboxToolset se conecta al servidor de Toolbox en el inicio y carga todas las herramientas disponibles. El agente llama a las herramientas por su nombre. Toolbox traduce esas llamadas en consultas SQL contra Cloud SQL.
La variable de entorno TOOLBOX_URL tiene el valor predeterminado http://127.0.0.1:5000 para el desarrollo local. Cuando realices la implementación en Cloud Run más adelante, anularás este valor con la URL de Cloud Run del servicio de Toolbox. No se necesitan cambios en el código.
Actualmente, la instrucción solo hace referencia a las dos herramientas estándar (search-jobs y get-job-details). La expandirás en el siguiente paso cuando agregues herramientas de búsqueda semántica y de transferencia.
Prueba el agente
Inicia la IU de desarrollo del ADK:
cd ~/build-agent-adk-toolbox-cloudsql
uv run adk web --allow_origins "regex:https://.*\.cloudshell\.dev"
Abre la URL que se muestra en la terminal (por lo general, http://localhost:8000) con la función Vista previa web de Cloud Shell o Ctrl + clic en la URL que se muestra en la terminal. Selecciona jobs_agent en el menú desplegable de agentes en la esquina superior izquierda.
Prueba búsquedas estándar
Prueba estas instrucciones para verificar las herramientas de SQL estándar:
What backend engineering jobs do you have?
Any jobs using Kubernetes?
Tell me about the Cloud Architect position

Cómo probar la búsqueda semántica
Prueba con descripciones en lenguaje natural que no se asignen a un rol o pila de tecnología específicos:
I want a remote job where I can work on AI and machine learning
Find me something in fintech with good work-life balance
I'm interested in infrastructure and reliability engineering
El agente intentará elegir la herramienta adecuada según el tipo de búsqueda: los filtros estructurados pasan por search-jobs y las descripciones en lenguaje natural pasan por search-jobs-by-description.

Transferencia de vectores de prueba
Pídele al agente que agregue un trabajo nuevo:
Add a new job: 'Robotics Software Engineer' at Boston Dynamics, role Robotics, tech stack: Python, C++, ROS, Computer Vision, salary $160-230K/year, location Waltham MA, Hybrid, 2 openings. Description: Design and implement autonomous navigation and manipulation algorithms for next-generation robots. Work on perception pipelines using computer vision and lidar, develop motion planning software in C++ and Python, and test systems on real hardware in warehouse and logistics environments.

Ahora intenta buscarlo:
Find me jobs involving autonomous systems and working with physical hardware
La incorporación se generó automáticamente durante la operación INSERT, por lo que no se necesita ningún paso independiente.

Ahora ya tienes una aplicación de RAG basada en agentes que funciona por completo y que utiliza ADK, MCP Toolbox y Cloud SQL. ¡Felicitaciones! Demos un paso más y, luego, implementemos estas apps en Cloud Run.
Ahora, detengamos la IU de desarrollo. Para ello, presiona Ctrl + C dos veces antes de continuar.
8. Implementa en Cloud Run
El agente y la Caja de herramientas funcionan de forma local. En este paso, se implementan ambos como servicios de Cloud Run para que sean accesibles a través de Internet. El servicio de Toolbox se ejecuta como un servidor de MCP en Cloud Run, y el servicio del agente se conecta a él.
Prepara la caja de herramientas para la implementación
Crea un directorio de implementación para el servicio de Toolbox:
cd ~/build-agent-adk-toolbox-cloudsql
mkdir -p deploy-toolbox
cp toolbox tools.yaml deploy-toolbox/
Crea el Dockerfile para la caja de herramientas. Abre deploy-toolbox/Dockerfile en el editor de Cloud Shell:
cloudshell edit deploy-toolbox/Dockerfile
Copia la siguiente secuencia de comandos en él
# deploy-toolbox/Dockerfile
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY toolbox tools.yaml ./
RUN chmod +x toolbox
EXPOSE 8080
CMD ["./toolbox", "--config", "tools.yaml", "--enable-api", "--address", "0.0.0.0", "--port", "8080"]
El ejecutable de Toolbox y tools.yaml se empaquetan en una imagen mínima de Debian. Cloud Run enruta el tráfico al puerto 8080.
Implementa el servicio de Toolbox
cd ~/build-agent-adk-toolbox-cloudsql
gcloud run deploy toolbox-service \
--source deploy-toolbox/ \
--region $REGION \
--set-env-vars "DB_PASSWORD=$DB_PASSWORD,DB_INSTANCE=$DB_INSTANCE,DB_NAME=$DB_NAME,GOOGLE_CLOUD_PROJECT=$GOOGLE_CLOUD_PROJECT,REGION=$REGION,GOOGLE_CLOUD_LOCATION=$GOOGLE_CLOUD_LOCATION" \
--allow-unauthenticated \
--quiet > logs/deploy_toolbox.log 2>&1 &
Este comando envía el código fuente a Cloud Build, compila una imagen de contenedor, la envía a Artifact Registry y la implementa en Cloud Run. Tardará unos minutos. Podemos inspeccionar el registro del proceso de implementación en el archivo logs/deploy_toolbox.log.
Prepara el agente para la implementación
Mientras se compila Toolbox, configura los archivos de implementación del agente.
Crea un Dockerfile en la raíz del proyecto. Abre Dockerfile en el editor de Cloud Shell:
cloudshell edit Dockerfile
Luego, copia el siguiente contenido
# Dockerfile
FROM ghcr.io/astral-sh/uv:python3.12-trixie-slim
WORKDIR /app
COPY pyproject.toml ./
COPY uv.lock ./
RUN uv sync --no-dev
COPY jobs_agent/ jobs_agent/
EXPOSE 8080
CMD ["uv", "run", "adk", "web", "--host", "0.0.0.0", "--port", "8080"]
Este Dockerfile usa ghcr.io/astral-sh/uv como imagen base, que incluye Python y uv preinstalados. No es necesario instalar uv por separado a través de pip.
Crea un archivo .dockerignore para excluir los archivos innecesarios de la imagen de contenedor:
cloudshell edit .dockerignore
Luego, copia la siguiente secuencia de comandos en él.
# .dockerignore
.venv/
__pycache__/
*.pyc
.env
jobs_agent/.env
toolbox
tools.yaml
seed.sql
deploy-toolbox/
Implementa el servicio del agente
Espera a que se complete la implementación de la Caja de herramientas. Vuelve a verificar el proceso de implementación en logs/deploy_toolbox.log para verificar el proceso. Luego, r ecupera su URL de Cloud Run con el siguiente comando
TOOLBOX_URL=$(gcloud run services describe toolbox-service \
--region=$REGION \
--format='value(status.url)')
echo "Toolbox URL: $TOOLBOX_URL"
Verás un resultado similar al siguiente:
Toolbox URL: https://toolbox-service-xxxxxx-xx.a.run.app
Luego, verifiquemos que la Caja de herramientas implementada funcione:
curl -s "$TOOLBOX_URL/api/toolset" | python3 -m json.tool | head -5
Si el resultado se muestra como en este ejemplo, la implementación ya se realizó correctamente.
{
"serverVersion": "1.0.0+binary.linux.amd64.c5524d3",
"tools": {
"add-job": {
"description": "Add a new job listing to the platform. Use this tool when a user asks to post a job that is not currently listed.",
A continuación, implementemos el agente y pasemos la URL de Toolbox como una variable de entorno:
cd ~/build-agent-adk-toolbox-cloudsql
gcloud run deploy jobs-agent \
--source . \
--region $REGION \
--set-env-vars "TOOLBOX_URL=$TOOLBOX_URL,GOOGLE_CLOUD_PROJECT=$GOOGLE_CLOUD_PROJECT,GOOGLE_CLOUD_LOCATION=$GOOGLE_CLOUD_LOCATION,GOOGLE_GENAI_USE_VERTEXAI=TRUE" \
--allow-unauthenticated \
--quiet
El código del agente lee TOOLBOX_URL del entorno (lo configuraste anteriormente). De forma local, apunta a http://127.0.0.1:5000; en Cloud Run, apunta a la URL del servicio de Toolbox. No es necesario realizar cambios en el código.
Prueba el agente implementado
Recupera la URL de Cloud Run del agente:
AGENT_URL=$(gcloud run services describe jobs-agent \
--region=$REGION \
--format='value(status.url)')
echo "Agent URL: $AGENT_URL"
Abre la URL en tu navegador. Se carga la IU para desarrolladores del ADK, la misma interfaz que usaste de forma local, pero ahora se ejecuta en Cloud Run.
Selecciona jobs_agent en el menú desplegable y realiza la prueba:
What backend engineering jobs do you have?
I want a remote job working on AI and machine learning
Ambas consultas funcionan a través de los servicios implementados: el agente en Cloud Run llama a la Caja de herramientas en Cloud Run, que consulta Cloud SQL.
9. Felicitaciones / Limpieza
Compilaste y, luego, implementaste un asistente de bolsa de trabajo inteligente que usa el kit de herramientas de MCP para bases de datos para conectar un agente de ADK y Cloud SQL PostgreSQL, tanto con consultas de SQL estándar como con búsquedas semánticas de vectores.
Qué aprendiste
- Cómo MCP estandariza el acceso a las herramientas para los agentes de IA y cómo MCP Toolbox para bases de datos aplica esto específicamente a las operaciones de bases de datos, reemplazando el código de bases de datos personalizado por una configuración declarativa de YAML
- Cómo configurar Cloud SQL PostgreSQL como fuente de datos de Toolbox con el tipo de fuente
cloud-sql-postgres - Cómo definir herramientas de consultas en SQL estándar con instrucciones parametrizadas que evitan la inyección de SQL
- Cómo habilitar la búsqueda de vectores con pgvector y
gemini-embedding-001, con el parámetroembeddedBypara la incorporación automática de consultas - Cómo
valueFromParampermite la incorporación automática de vectores: El LLM proporciona una descripción de texto y Toolbox copia, incorpora y almacena el vector junto con el texto de forma silenciosa. - Cómo el
ToolboxToolsetdel ADK carga herramientas desde un servidor de Toolbox en ejecución, lo que mantiene el código del agente al mínimo y la lógica de la base de datos completamente desacoplada - Cómo implementar el servidor de MCP de Toolbox y el agente de ADK en Cloud Run como servicios independientes
Realiza una limpieza
Para evitar que se apliquen cargos a tu cuenta de Google Cloud por los recursos creados en este codelab, puedes borrar los recursos individuales o todo el proyecto.
Opción 1: Borra el proyecto (recomendada)
La manera más fácil de realizar una limpieza es borrar el proyecto. Esto quita todos los recursos asociados con el proyecto.
gcloud projects delete $GOOGLE_CLOUD_PROJECT
Opción 2: Borra los recursos individuales
Si deseas conservar el proyecto, pero quitar solo los recursos creados en este codelab, haz lo siguiente:
gcloud run services delete jobs-agent --region=$REGION --quiet
gcloud run services delete toolbox-service --region=$REGION --quiet
gcloud sql instances delete jobs-instance --quiet
gcloud artifacts repositories delete cloud-run-source-deploy --location=$REGION --quiet 2>/dev/null
