1. Introduzione
L'utilità degli agenti AI dipende dalla qualità dei dati a cui possono accedere. La maggior parte dei dati reali si trova nei database e il collegamento degli agenti ai database in genere comporta la scrittura della gestione delle connessioni, della logica delle query e delle pipeline di incorporamento all'interno del codice dell'agente. Ogni agente che ha bisogno dell'accesso al database ripete questo lavoro e ogni modifica della query richiede il redeploy dell'agente.
Questo codelab mostra un approccio diverso. Dichiari gli strumenti di database in un file YAML, incluse query SQL standard, ricerca di somiglianza vettoriale e persino generazione automatica di embedding, e MCP Toolbox for Databases gestisce tutte le operazioni del database come server MCP. Il codice dell'agente rimane minimale: carica gli strumenti e lascia che Gemini decida quale chiamare.
Cosa creerai
Un assistente per bacheche di lavoro intelligenti per "TechJobs", un agente ADK basato su Gemini che aiuta gli sviluppatori a sfogliare gli annunci di lavoro nel settore tecnologico utilizzando filtri standard (ruolo, stack tecnologico) e a scoprire lavori tramite descrizioni in linguaggio naturale come "Voglio un lavoro da remoto che mi permetta di lavorare su chatbot AI". L'agente legge e scrive in un database Cloud SQL PostgreSQL interamente tramite MCP Toolbox for Databases, che gestisce tutto l'accesso al database, inclusa la generazione automatica di embedding per la ricerca vettoriale. Alla fine, sia Toolbox che l'agente vengono eseguiti su Cloud Run.
Cosa imparerai a fare
- In che modo lo standard MCP (Model Context Protocol) standardizza l'accesso agli strumenti per gli agenti AI e in che modo MCP Toolbox for Databases lo applica alle operazioni del database
- Configura MCP Toolbox for Databases come middleware tra un agente ADK e Cloud SQL PostgreSQL
- Definisci gli strumenti di database in modo dichiarativo in
tools.yaml: nessun codice di database nell'agente - Crea un agente ADK che carica gli strumenti da un server Toolbox in esecuzione utilizzando
ToolboxToolset - Genera vector embedding utilizzando la funzione
embedding()integrata di Cloud SQL e abilita la ricerca semantica conpgvector - Utilizza la funzionalità
valueFromParamper l'importazione automatica di vettori nelle operazioni di scrittura - Esegui il deployment del server Toolbox e dell'agente ADK su Cloud Run
Prerequisiti
- Un account Google Cloud con un account di fatturazione di prova
- Conoscenza di base di Python e SQL
- L'esperienza pregressa con Cloud Database e ADK sarà utile
2. Configura l'ambiente
Questo passaggio prepara l'ambiente Cloud Shell, configura il progetto Google Cloud e clona il repository di riferimento.
Apri Cloud Shell
Apri Cloud Shell nel browser. Cloud Shell fornisce un ambiente preconfigurato con tutti gli strumenti necessari per questo codelab. Quando richiesto, fai clic su Autorizza.
Poi fai clic su "Visualizza" -> "Terminale" per aprire il terminale.L'interfaccia dovrebbe avere un aspetto simile a questo

Questa sarà la nostra interfaccia principale, con l'IDE in alto e il terminale in basso.
Configurare la directory di lavoro
Crea la directory di lavoro. Tutto il codice che scrivi in questo codelab si trova qui:
mkdir -p ~/build-agent-adk-toolbox-cloudsql
cloudshell workspace ~/build-agent-adk-toolbox-cloudsql && cd ~/build-agent-adk-toolbox-cloudsql
Dopodiché, prepariamo diverse directory per gestire elementi come script di seeding e log.
mkdir -p ~/build-agent-adk-toolbox-cloudsql/scripts
mkdir -p ~/build-agent-adk-toolbox-cloudsql/logs
Configura il progetto Google Cloud
Crea il file .env con le variabili di località:
# For Vertex AI / Gemini API calls
echo "GOOGLE_CLOUD_LOCATION=global" > .env
# For Cloud SQL, Cloud Run, Artifact Registry
echo "REGION=us-central1" >> .env
Per semplificare la configurazione del progetto nel terminale, scarica questo script di configurazione del progetto nella tua directory di lavoro:
curl -sL https://raw.githubusercontent.com/alphinside/cloud-trial-project-setup/main/setup_verify_trial_project.sh -o setup_verify_trial_project.sh
Esegui lo script. Verifica il tuo account di fatturazione di prova, crea un nuovo progetto (o ne convalida uno esistente), salva l'ID progetto in un file .env nella directory corrente e imposta il progetto attivo in gcloud.
bash setup_verify_trial_project.sh && source .env
Lo script:
- Verificare di avere un account di fatturazione di prova attivo
- Controlla se esiste un progetto in
.env(se presente) - Crea un nuovo progetto o riutilizza quello esistente
- Collega l'account di fatturazione di prova al tuo progetto
- Salva l'ID progetto in
.env - Imposta il progetto come progetto
gcloudattivo
Verifica che il progetto sia impostato correttamente controllando il testo giallo accanto alla directory di lavoro nel prompt del terminale Cloud Shell. Dovrebbe essere visualizzato l'ID progetto.

Attiva l'API richiesta
Successivamente, dobbiamo abilitare diverse API per il prodotto con cui interagiremo:
gcloud services enable \
aiplatform.googleapis.com \
sqladmin.googleapis.com \
compute.googleapis.com \
run.googleapis.com \
cloudbuild.googleapis.com \
artifactregistry.googleapis.com
- API Vertex AI (
aiplatform.googleapis.com): l'agente utilizza i modelli Gemini e Toolbox utilizza l'API Embedding per la ricerca vettoriale. - API Cloud SQL Admin (
sqladmin.googleapis.com): esegui il provisioning e la gestione di un'istanza PostgreSQL. - API Compute Engine (
compute.googleapis.com): necessaria per creare istanze Cloud SQL. - Cloud Run, Cloud Build, Artifact Registry: utilizzati nel passaggio di deployment più avanti in questo codelab
3. Preparazione degli script per l'inizializzazione del database
Questo passaggio avvia la creazione dell'istanza Cloud SQL ed esegue uno script di configurazione automatizzato che attende che l'istanza sia pronta, quindi crea il database, lo inizializza con le offerte di lavoro e genera gli incorporamenti, tutto in un'unica operazione.
Innanzitutto, aggiungiamo la password del database al file .env e ricarichiamolo:
echo "DB_PASSWORD=techjobs-pwd" >> .env
echo "DB_INSTANCE=jobs-instance" >> .env
echo "DB_NAME=jobs_db" >> .env
source .env
Creazione dello script Bash per la creazione dell'istanza e del database
Quindi, crea lo script scripts/setup_database.sh con il seguente comando
mkdir -p ~/build-agent-adk-toolbox-cloudsql/scripts
cloudshell edit scripts/setup_database.sh
Quindi, copia il seguente codice nel file 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 ""
Creazione dello script Python per il seeding dei dati
Dopodiché, crea il file Python dello script di seeding scripts/setup_jobs_db.py utilizzando il comando riportato di seguito.
cloudshell edit scripts/setup_jobs_db.py
Quindi, copia il seguente codice nel file 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()
Ora passiamo al passaggio successivo.
4. Crea e inizializza il database
Ora gli script sono pronti per essere eseguiti. Avremo bisogno di Python per eseguire lo script preparato, quindi prepariamolo prima.
Configurare il progetto Python
uv è un gestore di progetti e pacchetti Python veloce scritto in Rust ( documentazione di uv). Questo codelab lo utilizza per la velocità e la semplicità di manutenzione del progetto Python
Inizializza un progetto Python e aggiungi le dipendenze richieste:
uv init
uv add cloud-sql-python-connector --extra pg8000
uv add python-dotenv
Tieni presente che qui utilizziamo l'SDK Python cloud-sql-python-connector per inizializzare una connessione sicura con la nostra istanza di database, autenticata utilizzando le credenziali predefinite dell'applicazione.
Esegui lo script di configurazione
Ora possiamo eseguire lo script di configurazione in background e controllare l'output della console che verrà scritto nel file logs/atabase_setup.log utilizzando il comando seguente. Puoi continuare con la sezione successiva mentre aspetti che l'operazione venga completata.
mkdir -p ~/build-agent-adk-toolbox-cloudsql/logs
bash scripts/setup_database.sh > logs/database_setup.log 2>&1 &
Scarica il binario di Toolbox
In questo tutorial utilizzeremo MCP Toolbox, che fortunatamente include un binario precompilato pronto per essere utilizzato nell'ambiente Linux. Ora scarichiamolo in background, perché ci vuole un po'. Esegui questo comando per scaricare il file binario ed esaminare il log di output su logs/toolbox_dl.log . Puoi continuare con la sezione successiva mentre aspetti che l'operazione venga completata.
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 &
Informazioni sullo script di configurazione scripts/setup_database.sh
Ora proviamo a capire lo script di configurazione che abbiamo configurato in precedenza. Esegue la seguente procedura
- Il primo comando che eseguiamo è
gcloud sql instances createcon il seguente flag
db-custom-1-3840è il livello Cloud SQL con core dedicati più piccolo (1 vCPU, 3,75 GB di RAM) nella versioneENTERPRISE. Puoi leggere maggiori dettagli qui. Per l'integrazione di Vertex AI ML è necessario un core dedicato. I livelli con core condiviso (db-f1-micro,db-g1-small) non lo supportano.--root-passwordimposta la password per l'utentepostgrespredefinito.--enable-google-ml-integrationabilita l'integrazione integrata di Cloud SQL con Vertex AI, che consente di chiamare i modelli di embedding direttamente da SQL utilizzando la funzioneembedding().
- Verifica se l'istanza è già nello stato
RUNNABLE - Concedi al service account dell'istanza Cloud SQL l'autorizzazione per chiamare Vertex AI utilizzando il comando
gcloud projects add-iam-policy-binding. Questo è necessario per la funzioneembedding()integrata che utilizzeremo per inizializzare il database - Creazione del database
- Esecuzione dello script di seeding
setup_jobs_db.py
Informazioni sullo script seed scripts/setup_jobs_db.py
Ora, passando allo script di seeding, questo script esegue le seguenti operazioni:
- Inizializza la connessione all'istanza di database.
- Installa due estensioni PostgreSQL:
google_ml_integration: fornisce la funzione SQLembedding(), che chiama i modelli di incorporamento di Vertex AI direttamente da SQL. Si tratta di un'estensione a livello di database che rende disponibili le funzioni di ML all'interno dijobs_db. Il flag a livello di istanza (--enable-google-ml-integration) che imposti durante la creazione dell'istanza consente alla VM Cloud SQL di raggiungere Vertex AI. L'estensione rende disponibili le funzioni SQL all'interno di questo database specifico.vector(pgvector): aggiunge il tipo di dativectore gli operatori di distanza per archiviare ed eseguire query sugli incorporamenti.
- Crea la tabella, nota che la colonna
description_embeddingèvector(3072), ovvero una colonnapgvectorche memorizza vettori a 3072 dimensioni. - Inserisci i dati iniziali dei job
- Genera i dati di embedding dal campo
descriptione compiladescription_embeddingutilizzando l'integrazione Vertex integrata tramite la funzioneembedding()
embedding('gemini-embedding-001', description): chiama il modello di embedding Gemini di Vertex AI direttamente da SQL, passando il testodescriptiondi ogni annuncio di lavoro. Questa è l'estensionegoogle_ml_integrationche hai installato nello script seed.::vector: esegue il cast dell'array float restituito al tipovectordi pgvector in modo che possa essere archiviato ed eseguito query con operatori di distanza.UPDATEviene eseguito su tutte le 15 righe, generando un embedding a 3072 dimensioni per ogni descrizione del lavoro.
In questo modo verranno preparati i dati iniziali a cui accederà il nostro agente
5. Configura MCP Toolbox for Databases
Questo passaggio introduce MCP Toolbox for Databases, lo configura per la connessione all'istanza Cloud SQL e definisce due strumenti di query SQL standard.
Che cos'è MCP e perché utilizzare Toolbox?

MCP (Model Context Protocol) è un protocollo aperto che standardizza il modo in cui gli agenti AI scoprono e interagiscono con strumenti esterni. Definisce un modello client-server: l'agente ospita un client MCP e gli strumenti vengono esposti dai server MCP. Qualsiasi client compatibile con MCP può utilizzare qualsiasi server compatibile con MCP. L'agente non ha bisogno di codice di integrazione personalizzato per ogni strumento.

MCP Toolbox for Databases è un server MCP open source creato appositamente per l'accesso al database. Senza, dovresti scrivere funzioni Python che aprono connessioni al database, gestiscono i pool di connessioni, creano query con parametri per impedire l'SQL injection, gestiscono gli errori e incorporano tutto questo codice all'interno dell'agente. Ogni agente che ha bisogno dell'accesso al database ripete questa operazione. La modifica di una query comporta il nuovo deployment dell'agente.
Con Toolbox, scrivi un file YAML. Ogni strumento viene mappato a un'istruzione SQL con parametri. Toolbox gestisce il pool di connessioni, le query parametrizzate, l'autenticazione e l'osservabilità. Gli strumenti sono separati dall'agente: aggiorna una query modificando tools.yaml e riavviando Toolbox, senza toccare il codice dell'agente. Gli stessi strumenti funzionano con ADK, LangGraph, LlamaIndex o qualsiasi framework compatibile con MCP.
Scrivere la configurazione degli strumenti
Ora dobbiamo creare un file denominato tools.yaml nell'editor di Cloud Shell per configurare gli strumenti.
cloudshell edit tools.yaml
Il file utilizza YAML multi-documento: ogni blocco separato da --- è una risorsa autonoma. Ogni risorsa ha un kind che dichiara di cosa si tratta (sources per le connessioni al database, tools per le azioni chiamabili dall'agente) e un type che specifica il backend (cloud-sql-postgres per l'origine, postgres-sql per gli strumenti basati su SQL). Uno strumento fa riferimento alla sua origine tramite name, in modo che Toolbox sappia quale pool di connessioni eseguire. Le variabili di ambiente utilizzano la sintassi ${VAR_NAME} e vengono risolte all'avvio.
Ora, copia prima i seguenti script nel file 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}
---
Questo script definisce la seguente risorsa:
- Origine (
jobs-db): indica a Toolbox come connettersi all'istanza Cloud SQL PostgreSQL. Il tipocloud-sql-postgresutilizza internamente il connettore Cloud SQL, gestendo automaticamente l'autenticazione e le connessioni sicure. I segnaposto${GOOGLE_CLOUD_PROJECT},${REGION}e${DB_PASSWORD}vengono risolti dalle variabili di ambiente all'avvio.
Successivamente, aggiungi il seguente script sotto il simbolo --- nel file 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)."
---
Questo script definisce la seguente risorsa:
- Strumenti 1 e 2 (
search-jobs,get-job-details): strumenti di query SQL standard. Ognuna mappa un nome di strumento (ciò che vede l'agente) a un'istruzione SQL parametrizzata (ciò che esegue il database). I parametri utilizzano i segnaposto posizionali$1e$2. Toolbox li esegue come istruzioni preparate, il che impedisce l'SQL injection.
Continuiamo aggiungendo il seguente script sotto il simbolo --- nel file 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
---
Questo script definisce la seguente risorsa:
- Modello di embedding (
gemini-embedding): configura Toolbox per chiamare il modellogemini-embedding-001di Gemini per generare embedding di testo a 3072 dimensioni. Toolbox utilizza le Credenziali predefinite dell'applicazione (ADC) per l'autenticazione. Non è necessaria alcuna chiave API in Cloud Shell o Cloud Run. Tieni presente che questodimensionconfigurato qui deve essere lo stesso di quello configurato in precedenza per inizializzare il database
Continuiamo aggiungendo il seguente script sotto il simbolo --- nel file 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
---
Questo script definisce la seguente risorsa:
- Strumento 3 (
search-jobs-by-description): uno strumento di ricerca vettoriale. Il parametrosearch_queryhaembeddedBy: gemini-embedding, che indica a Strumenti amministrativi di intercettare il testo non elaborato, inviarlo al modello di embedding e utilizzare il vettore risultante nell'istruzione SQL. L'operatore<=>è la distanza del coseno di pgvector: valori più piccoli indicano descrizioni più simili.
Infine, aggiungi l'ultimo strumento sotto il simbolo --- nel file 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
Questo script definisce la seguente risorsa:
- Tool 4 (
add-job): mostra l'importazione di vettori. Il parametrodescription_vectorha due campi speciali: valueFromParam: description: Toolbox copia il valore dal parametrodescriptionin questo. Il LLM non vede mai questo parametro.embeddedBy: gemini-embedding: Toolbox incorpora il testo copiato in un vettore prima di passarlo a SQL.
Il risultato è che una chiamata allo strumento memorizza sia il testo della descrizione non elaborato sia il suo incorporamento vettoriale, senza che l'agente sappia nulla degli incorporamenti.
Il formato YAML multi-documento separa ogni risorsa con ---. Ogni documento ha campi kind, name e type che ne definiscono il contenuto. In sintesi, abbiamo già configurato tutti gli elementi seguenti:
- Definisci il database di origine
- Definisci gli strumenti ( strumento 1 e 2) per eseguire query sul database con il filtro standard
- Definisci il modello di embedding
- Definisci lo strumento per eseguire la ricerca vettoriale ( strumento 3) nel database
- Definisci lo strumento per l'importazione dei dati vettoriali ( strumento 4) nel database
6. Esecuzione del server MCP Toolbox
Nel passaggio precedente, abbiamo già impostato la configurazione necessaria per la nostra casella degli strumenti MCP. Ora siamo pronti per eseguire il server.
Verificare i dati iniziali
Prima di avviare Toolbox, verifichiamo che la configurazione del database sia stata completata. Crea uno script Python scripts/verify_database.py utilizzando il seguente comando
cloudshell edit scripts/verify_seed.py
Quindi, copia il seguente codice nel file 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)
Questo script controllerà il numero di dati dei post di lavoro e la loro incorporazione. Esegui lo script utilizzando questo comando
uv run scripts/verify_seed.py
Se vedi il seguente output del terminale, significa che i dati sono pronti
Jobs: 15/15 Embeddings: 15/15 ✓ Database ready!
Avviare il server di Strumenti
Nel passaggio di configurazione precedente, abbiamo già scaricato l'eseguibile toolbox. Assicurati che questo file binario esista e sia stato scaricato correttamente. In caso contrario, scaricalo e attendi il completamento.
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
Dovremo esporre le nostre variabili .env al processo secondario eseguito dalla casella degli strumenti MCP. Esegui il comando seguente per avviare il server della toolbox e registrare l'output della console nel file logs/mcp_toolbox.log
set -a; source .env; set +a
./toolbox --config tools.yaml --enable-api > logs/mcp_toolbox.log 2>&1 &
Dovresti vedere un output nel file logs/mcp_toolbox.log che conferma che il server è pronto, come mostrato di seguito:
... 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!"
Verificare gli strumenti
Esegui una query sull'API Toolbox per elencare tutti gli strumenti registrati:
curl -s http://localhost:5000/api/toolset | uv run -m json.tool
Dovresti visualizzare gli strumenti con le relative descrizioni e i parametri. Come mostrato di seguito
...
"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": []
}
...
Testa direttamente lo strumento search-jobs:
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 risposta deve contenere i due lavori di ingegneria backend dei dati iniziali.
[
{
"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. Crea l'agente ADK
Ora utilizzeremo ADK in Python per questo progetto. Aggiungiamo le dipendenze richieste:
uv add google-adk==1.29.0 toolbox-adk==1.0.0
google-adk: Agent Development Kit di Google, incluso l'SDK Geminitoolbox-adk: integrazione di ADK per MCP Toolbox for Databases.
Creare la struttura di directory dell'agente
L'ADK prevede un layout di cartelle specifico: una directory denominata come l'agente contenente __init__.py, agent.py e .env. Per facilitare questa operazione, è stato integrato un comando per stabilire rapidamente la struttura:
uv run adk create jobs_agent \
--model gemini-2.5-flash \
--project ${GOOGLE_CLOUD_PROJECT} \
--region ${GOOGLE_CLOUD_LOCATION}
La directory dovrebbe ora avere il seguente aspetto:
build-agent-adk-toolbox-cloudsql/ ├── jobs_agent/ │ ├── __init__.py │ ├── agent.py │ └── .env ├── logs ├── scripts └── ...
Successivamente, dovremo integrare l'agente ADK nel server Toolbox in esecuzione e testare tutti e quattro gli strumenti: query standard, ricerca semantica e importazione vettoriale. Il codice dell'agente è minimo: tutta la logica del database si trova in tools.yaml.
Configurare l'ambiente dell'agente
ADK legge GOOGLE_GENAI_USE_VERTEXAI, GOOGLE_CLOUD_PROJECT e GOOGLE_CLOUD_LOCATION dall'ambiente shell, che hai già impostato nel passaggio precedente. L'unica variabile specifica dell'agente è TOOLBOX_URL. Aggiungila al file .env dell'agente:
echo -e "\nTOOLBOX_URL=http://127.0.0.1:5000" >> jobs_agent/.env
Aggiornare il modulo dell'agente
Apri jobs_agent/agent.py nell'editor di Cloud Shell
cloudshell edit jobs_agent/agent.py
e sovrascrivi i contenuti con il seguente codice:
# 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],
)
Tieni presente che qui non è presente alcun codice di database: ToolboxToolset si connette al server Toolbox all'avvio e carica tutti gli strumenti disponibili. L'agente chiama gli strumenti per nome; Toolbox traduce queste chiamate in query SQL su Cloud SQL.
La variabile di ambiente TOOLBOX_URL è impostata su http://127.0.0.1:5000 per lo sviluppo locale. Quando esegui il deployment su Cloud Run in un secondo momento, esegui l'override con l'URL Cloud Run del servizio Toolbox, senza bisogno di modifiche al codice.
L'istruzione attualmente fa riferimento solo ai due strumenti standard (search-jobs e get-job-details). La espanderai nel passaggio successivo quando aggiungerai gli strumenti di ricerca semantica e importazione.
Testare l'agente
Avvia l'interfaccia utente di sviluppo ADK:
cd ~/build-agent-adk-toolbox-cloudsql
uv run adk web --allow_origins "regex:https://.*\.cloudshell\.dev"
Apri l'URL mostrato nel terminale (in genere http://localhost:8000) utilizzando la funzionalità Anteprima web di Cloud Shell o Ctrl + clic sull'URL mostrato nel terminale. Seleziona jobs_agent dal menu a discesa degli agenti nell'angolo in alto a sinistra.
Testare le query standard
Prova questi prompt per verificare gli strumenti SQL standard:
What backend engineering jobs do you have?
Any jobs using Kubernetes?
Tell me about the Cloud Architect position

Testare la ricerca semantica
Prova descrizioni in linguaggio naturale che non corrispondono a un ruolo o a uno stack tecnologico specifico:
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
L'agente cercherà di scegliere lo strumento giusto in base al tipo di query: i filtri strutturati vengono elaborati tramite search-jobs, mentre le descrizioni in linguaggio naturale tramite search-jobs-by-description.

Testare l'importazione di vettori
Chiedi all'agente di aggiungere un nuovo job:
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.

Ora prova a cercarlo:
Find me jobs involving autonomous systems and working with physical hardware
L'incorporamento è stato generato automaticamente durante l'inserimento, senza bisogno di un passaggio separato.

Ora hai già un'applicazione RAG agentica completamente funzionante che utilizza ADK, MCP Toolbox e CloudSQL. Complimenti! Facciamo un ulteriore passo avanti per eseguire il deployment di queste app su Cloud Run.
Ora, interrompiamo l'interfaccia utente per sviluppatori terminando il processo premendo Ctrl+C due volte prima di procedere.
8. Esegui il deployment in Cloud Run
L'agente e Toolbox funzionano localmente. Questo passaggio esegue il deployment di entrambi come servizi Cloud Run, in modo che siano accessibili su internet. Il servizio Toolbox viene eseguito come server MCP su Cloud Run e il servizio agente si connette a questo server.
Preparare la cassetta degli attrezzi per il deployment
Crea una directory di deployment per il servizio Toolbox:
cd ~/build-agent-adk-toolbox-cloudsql
mkdir -p deploy-toolbox
cp toolbox tools.yaml deploy-toolbox/
Crea il Dockerfile per la toolbox. Apri deploy-toolbox/Dockerfile nell'editor di Cloud Shell:
cloudshell edit deploy-toolbox/Dockerfile
e copia il seguente script
# 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"]
Il binario Toolbox e tools.yaml sono inclusi in un'immagine Debian minima. Cloud Run instrada il traffico alla porta 8080.
Esegui il deployment del servizio Strumenti
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 &
Questo comando invia l'origine a Cloud Build, crea un'immagine container, la invia ad Artifact Registry ed esegue il deployment su Cloud Run. Ci vorranno alcuni minuti. Possiamo esaminare il log del processo di deployment nel file logs/deploy_toolbox.log.
Preparare l'agente per il deployment
Mentre viene creata la casella degli strumenti, configura i file di deployment dell'agente.
Crea un Dockerfile nella radice del progetto. Apri Dockerfile nell'editor di Cloud Shell:
cloudshell edit Dockerfile
Quindi, copia i seguenti contenuti
# 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"]
Questo Dockerfile utilizza ghcr.io/astral-sh/uv come immagine di base, che include sia Python sia uv preinstallati. Non è necessario installare uv separatamente tramite pip.
Crea un file .dockerignore per escludere i file non necessari dall'immagine container:
cloudshell edit .dockerignore
Poi copia il seguente script
# .dockerignore
.venv/
__pycache__/
*.pyc
.env
jobs_agent/.env
toolbox
tools.yaml
seed.sql
deploy-toolbox/
Esegui il deployment del servizio agente
Attendi il completamento del deployment di Toolbox. Controlla di nuovo la procedura di deployment su logs/deploy_toolbox.log per verificarla. Quindi, recupera il relativo URL Cloud Run utilizzando il comando seguente
TOOLBOX_URL=$(gcloud run services describe toolbox-service \
--region=$REGION \
--format='value(status.url)')
echo "Toolbox URL: $TOOLBOX_URL"
Vedrai un output simile a questo
Toolbox URL: https://toolbox-service-xxxxxx-xx.a.run.app
Quindi, verifichiamo che Toolbox di cui è stato eseguito il deployment funzioni:
curl -s "$TOOLBOX_URL/api/toolset" | python3 -m json.tool | head -5
Se l'output viene visualizzato come in questo esempio, il deployment è già riuscito
{
"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.",
Ora eseguiamo il deployment dell'agente, passando l'URL di Toolbox come variabile di ambiente:
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
Il codice dell'agente legge TOOLBOX_URL dall'ambiente (che hai configurato in precedenza). A livello locale punta a http://127.0.0.1:5000; su Cloud Run punta all'URL del servizio Toolbox. Non sono necessarie modifiche al codice.
Testare l'agente di cui è stato eseguito il deployment
Recupera l'URL Cloud Run dell'agente:
AGENT_URL=$(gcloud run services describe jobs-agent \
--region=$REGION \
--format='value(status.url)')
echo "Agent URL: $AGENT_URL"
Apri l'URL nel browser. Viene caricata l'interfaccia utente di sviluppo dell'ADK, la stessa che hai utilizzato localmente, ora in esecuzione su Cloud Run.
Seleziona jobs_agent dal menu a discesa e testa:
What backend engineering jobs do you have?
I want a remote job working on AI and machine learning
Entrambe le query funzionano tramite i servizi di cui è stato eseguito il deployment: l'agente su Cloud Run chiama Toolbox su Cloud Run, che esegue query su Cloud SQL.
9. Congratulazioni / Pulizia
Hai creato e implementato un assistente per bacheche intelligenti di annunci di lavoro che utilizza MCP Toolbox for Databases per collegare un agente ADK e Cloud SQL PostgreSQL, sia con query SQL standard sia con la ricerca semantica di vettori.
Che cosa hai imparato
- In che modo MCP standardizza l'accesso agli strumenti per gli agenti AI e in che modo MCP Toolbox for Databases lo applica in modo specifico alle operazioni di database, sostituendo il codice di database personalizzato con la configurazione YAML dichiarativa
- Come configurare Cloud SQL PostgreSQL come origine dati di Toolbox utilizzando il tipo di origine
cloud-sql-postgres - Come definire strumenti di query SQL standard con istruzioni parametrizzate che impediscono SQL injection
- Come attivare la ricerca vettoriale utilizzando pgvector e
gemini-embedding-001, con il parametroembeddedByper l'embedding automatico delle query - In che modo
valueFromParamconsente l'inserimento automatico di vettori: il modello LLM fornisce una descrizione testuale e Toolbox copia, incorpora e archivia il vettore insieme al testo in modo invisibile - In che modo
ToolboxToolsetdi ADK carica gli strumenti da un server Toolbox in esecuzione, mantenendo il codice dell'agente minimo e la logica del database completamente disaccoppiata - Come eseguire il deployment del server Toolbox MCP e dell'agente ADK su Cloud Run come servizi separati
Pulizia
Per evitare che al tuo account Google Cloud vengano addebitati costi relativi alle risorse create in questo codelab, puoi eliminare le singole risorse o l'intero progetto.
Opzione 1: elimina il progetto (consigliata)
Il modo più semplice per liberare spazio è eliminare il progetto. Vengono rimosse tutte le risorse associate al progetto.
gcloud projects delete $GOOGLE_CLOUD_PROJECT
Opzione 2: elimina singole risorse
Se vuoi conservare il progetto, ma rimuovere solo le risorse create in questo codelab:
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
