1. Introduction
L'utilité des agents d'IA dépend des données auxquelles ils ont accès. La plupart des données réelles se trouvent dans des bases de données. Connecter des agents à des bases de données signifie généralement écrire la gestion des connexions, la logique des requêtes et intégrer des pipelines dans le code de votre agent. Chaque agent ayant besoin d'accéder à la base de données répète cette tâche, et chaque modification de requête nécessite un redéploiement de l'agent.
Cet atelier de programmation présente une approche différente. Vous déclarez vos outils de base de données dans un fichier YAML (requêtes SQL standards, recherche de similarité vectorielle, voire génération automatique d'embeddings), et MCP Toolbox for Databases gère toutes les opérations de base de données en tant que serveur MCP. Votre code d'agent reste minimal : chargez les outils et laissez Gemini décider lequel appeler.
Objectifs de l'atelier
Un assistant intelligent pour les tableaux d'offres d'emploi pour "TechJobs" : un agent ADK optimisé par Gemini qui aide les développeurs à parcourir les offres d'emploi dans le secteur de la technologie à l'aide de filtres standards (rôle, pile technologique) et à découvrir des emplois grâce à des descriptions en langage naturel comme "Je recherche un emploi à distance dans le domaine des chatbots d'IA". L'agent lit et écrit dans une base de données Cloud SQL PostgreSQL entièrement via MCP Toolbox for Databases, qui gère tous les accès à la base de données, y compris la génération automatique d'embeddings pour la recherche vectorielle. À la fin de l'atelier, la boîte à outils et l'agent s'exécutent sur Cloud Run.
Points abordés
- Comment le protocole MCP (Model Context Protocol) standardise l'accès aux outils pour les agents d'IA, et comment MCP Toolbox pour les bases de données l'applique aux opérations de base de données
- Configurer MCP Toolbox for Databases en tant que middleware entre un agent ADK et Cloud SQL PostgreSQL
- Définissez les outils de base de données de manière déclarative dans
tools.yaml: aucun code de base de données dans votre agent - Créer un agent ADK qui charge des outils à partir d'un serveur Toolbox en cours d'exécution à l'aide de
ToolboxToolset - Générez des embeddings vectoriels à l'aide de la fonction
embedding()intégrée de Cloud SQL et activez la recherche sémantique avecpgvector. - Utiliser la fonctionnalité
valueFromParampour l'ingestion automatique de vecteurs lors des opérations d'écriture - Déployer le serveur Toolbox et l'agent ADK sur Cloud Run
Prérequis
- Un compte Google Cloud avec un compte de facturation d'essai
- Connaître les bases de Python et de SQL
- Une expérience préalable avec Cloud Database et l'ADK sera utile.
2. Configurer votre environnement
Cette étape prépare votre environnement Cloud Shell, configure votre projet Google Cloud et clone le dépôt de référence.
Ouvrir Cloud Shell
Ouvrez Cloud Shell dans votre navigateur. Cloud Shell fournit un environnement préconfiguré avec tous les outils dont vous avez besoin pour cet atelier de programmation. Cliquez sur Autoriser lorsque vous y êtes invité.
Cliquez ensuite sur Afficher > Terminal pour ouvrir le terminal.Votre interface devrait ressembler à ceci :

Ce sera notre interface principale, avec l'IDE en haut et le terminal en bas.
Configurer votre répertoire de travail
Créez votre répertoire de travail. Tout le code que vous écrivez dans cet atelier de programmation se trouve ici :
mkdir -p ~/build-agent-adk-toolbox-cloudsql
cloudshell workspace ~/build-agent-adk-toolbox-cloudsql && cd ~/build-agent-adk-toolbox-cloudsql
Ensuite, préparons plusieurs répertoires pour gérer des éléments tels que les scripts de seeding et les journaux.
mkdir -p ~/build-agent-adk-toolbox-cloudsql/scripts
mkdir -p ~/build-agent-adk-toolbox-cloudsql/logs
Configurer un projet Google Cloud
Créez le fichier .env avec les variables de localisation :
# For Vertex AI / Gemini API calls
echo "GOOGLE_CLOUD_LOCATION=global" > .env
# For Cloud SQL, Cloud Run, Artifact Registry
echo "REGION=us-central1" >> .env
Pour simplifier la configuration du projet dans votre terminal, téléchargez ce script de configuration du projet dans votre répertoire de travail :
curl -sL https://raw.githubusercontent.com/alphinside/cloud-trial-project-setup/main/setup_verify_trial_project.sh -o setup_verify_trial_project.sh
Exécutez le script. Il valide votre compte de facturation d'essai, crée un projet (ou en valide un existant), enregistre l'ID de votre projet dans un fichier .env du répertoire actuel et définit le projet actif dans gcloud.
bash setup_verify_trial_project.sh && source .env
Le script va :
- Vérifier que vous disposez d'un compte de facturation d'essai actif
- Recherchez un projet existant dans
.env(le cas échéant). - Créez un projet ou réutilisez-en un existant.
- Associer le compte de facturation d'essai à votre projet
- Enregistrez l'ID du projet dans
.env. - Définir le projet comme projet
gcloudactif
Vérifiez que le projet est correctement défini en examinant le texte jaune à côté de votre répertoire de travail dans l'invite du terminal Cloud Shell. L'ID de votre projet devrait s'afficher.

Activer l'API requise
Ensuite, nous devons activer plusieurs API pour le produit avec lequel nous allons interagir :
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) : votre agent utilise les modèles Gemini, et Toolbox utilise l'API d'embedding pour la recherche vectorielle. - API Cloud SQL Admin (
sqladmin.googleapis.com) : vous provisionnez et gérez une instance PostgreSQL. - API Compute Engine (
compute.googleapis.com) : requise pour créer des instances Cloud SQL. - Cloud Run, Cloud Build, Artifact Registry : utilisés lors de l'étape de déploiement plus loin dans cet atelier
3. Préparer des scripts pour l'initialisation de la base de données
Cette étape lance la création de l'instance Cloud SQL et exécute un script de configuration automatisé qui attend que l'instance soit prête, puis crée la base de données, l'alimente avec des offres d'emploi et génère des embeddings, le tout en une seule opération.
Commençons par ajouter le mot de passe de la base de données à votre fichier .env et à le recharger :
echo "DB_PASSWORD=techjobs-pwd" >> .env
echo "DB_INSTANCE=jobs-instance" >> .env
echo "DB_NAME=jobs_db" >> .env
source .env
Créer un script Bash pour créer une instance et une base de données
Créez ensuite le script scripts/setup_database.sh à l'aide de la commande suivante :
mkdir -p ~/build-agent-adk-toolbox-cloudsql/scripts
cloudshell edit scripts/setup_database.sh
Ensuite, copiez le code suivant dans le fichier 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 ""
Créer un script Python pour l'amorçage des données
Créez ensuite le fichier Python de script d'amorçage scripts/setup_jobs_db.py à l'aide de la commande ci-dessous.
cloudshell edit scripts/setup_jobs_db.py
Ensuite, copiez le code suivant dans le fichier 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()
Passons maintenant à l'étape suivante.
4. Créer et initialiser la base de données
Nos scripts sont maintenant prêts à être exécutés. Nous aurons besoin de Python pour exécuter notre script préparé. Commençons donc par le préparer.
Configurer le projet Python
uv est un gestionnaire de packages et de projets Python rapide écrit en Rust ( documentation uv ). Cet atelier de programmation l'utilise pour la rapidité et la simplicité de la maintenance du projet Python.
Initialisez un projet Python et ajoutez les dépendances requises :
uv init
uv add cloud-sql-python-connector --extra pg8000
uv add python-dotenv
Notez que nous utilisons ici le SDK Python cloud-sql-python-connector pour initialiser une connexion sécurisée avec notre instance de base de données, qui est authentifiée à l'aide des identifiants par défaut de l'application.
Exécuter le script de configuration
Nous pouvons maintenant exécuter le script d'installation en arrière-plan et inspecter la sortie de la console qui sera écrite dans le fichier logs/atabase_setup.log à l'aide de la commande suivante. Vous pouvez passer à la section suivante en attendant la fin de cette opération.
mkdir -p ~/build-agent-adk-toolbox-cloudsql/logs
bash scripts/setup_database.sh > logs/database_setup.log 2>&1 &
Télécharger le fichier binaire de la boîte à outils
Dans ce tutoriel, nous allons utiliser MCP Toolbox. Heureusement, il est fourni avec un fichier binaire prédéfini qui est prêt à être utilisé dans l'environnement Linux. Maintenant, téléchargeons-le en arrière-plan, car cela prendra un certain temps. Exécutez la commande suivante pour télécharger le fichier binaire et inspecter le journal de sortie sur le logs/toolbox_dl.log . Vous pouvez passer à la section suivante en attendant la fin de cette opération.
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 &
Comprendre le script de configuration scripts/setup_database.sh
Essayons maintenant de comprendre le script de configuration que nous avons configuré précédemment. Il effectue les opérations suivantes :
- La toute première commande que nous exécutons est la commande
gcloud sql instances createavec l'option suivante :
db-custom-1-3840est le plus petit niveau Cloud SQL à cœur dédié (1 vCPU, 3,75 Go de RAM) dans l'éditionENTERPRISE. Pour en savoir plus, cliquez ici. Un cœur dédié est requis pour l'intégration Vertex AI ML. Les niveaux à cœur partagé (db-f1-micro,db-g1-small) ne sont pas compatibles.--root-passworddéfinit le mot de passe de l'utilisateurpostgrespar défaut.--enable-google-ml-integrationactive l'intégration intégrée de Cloud SQL à Vertex AI, ce qui vous permet d'appeler des modèles d'embedding directement depuis SQL à l'aide de la fonctionembedding().
- Vérifiez si l'instance est déjà à l'état
RUNNABLE. - Accordez au compte de service de l'instance Cloud SQL l'autorisation d'appeler Vertex AI à l'aide de la commande
gcloud projects add-iam-policy-binding. Cette opération est requise pour la fonctionembedding()intégrée que nous utiliserons lors de l'amorçage de la base de données. - Créer la base de données
- Exécuter le script d'amorçage
setup_jobs_db.py
Comprendre le script d'amorçage scripts/setup_jobs_db.py
Passons maintenant au script de seeding. Il effectue les opérations suivantes :
- Initialiser la connexion à l'instance de base de données
- Installe deux extensions PostgreSQL :
google_ml_integration: fournit la fonction SQLembedding(), qui appelle les modèles d'embedding Vertex AI directement à partir de SQL. Il s'agit d'une extension au niveau de la base de données qui rend les fonctions de ML disponibles dansjobs_db. Le flag au niveau de l'instance (--enable-google-ml-integration) que vous définissez lors de la création de l'instance permet à la VM Cloud SQL d'accéder à Vertex AI. L'extension rend les fonctions SQL disponibles dans cette base de données spécifique.vector(pgvector) : ajoute le type de donnéesvectoret les opérateurs de distance pour stocker et interroger les embeddings.
- Créez la table et notez que la colonne
description_embeddingestvector(3072), c'est-à-dire une colonnepgvectorqui stocke des vecteurs à 3 072 dimensions. - Déplacer les données de tâches initiales
- Générez les données d'embedding à partir du champ
descriptionet remplissezdescription_embeddingà l'aide de l'intégration Vertex intégrée via la fonctionembedding().
embedding('gemini-embedding-001', description): appelle le modèle d'embedding Gemini de Vertex AI directement depuis SQL, en transmettant le textedescriptionde chaque offre d'emploi. Il s'agit de l'extensiongoogle_ml_integrationque vous avez installée dans le script de seed.::vector: convertit le tableau float renvoyé au typevectorde pgvector afin qu'il puisse être stocké et interrogé avec des opérateurs de distance.UPDATEs'exécute sur les 15 lignes, ce qui génère un embedding de dimension 3072 par description de poste.
Cela préparera les données initiales auxquelles notre agent accédera.
5. Configurer MCP Toolbox for Databases
Cette étape présente MCP Toolbox for Databases, le configure pour qu'il se connecte à votre instance Cloud SQL et définit deux outils de requête SQL standards.
Qu'est-ce que MCP et pourquoi utiliser Toolbox ?

Le MCP (Model Context Protocol) est un protocole ouvert qui standardise la façon dont les agents d'IA découvrent les outils externes et interagissent avec eux. Il définit un modèle client-serveur : l'agent héberge un client MCP, et les outils sont exposés par les serveurs MCP. N'importe quel client compatible avec MCP peut utiliser n'importe quel serveur compatible avec MCP. L'agent n'a pas besoin de code d'intégration personnalisé pour chaque outil.

MCP Toolbox for Databases est un serveur MCP Open Source conçu spécifiquement pour l'accès aux bases de données. Sans cela, vous devriez écrire des fonctions Python qui ouvrent des connexions à la base de données, gèrent les pools de connexions, construisent des requêtes paramétrées pour éviter l'injection SQL, gèrent les erreurs et intègrent tout ce code dans votre agent. Chaque agent ayant besoin d'accéder à la base de données répète cette opération. Modifier une requête signifie redéployer l'agent.
Avec Toolbox, vous écrivez un fichier YAML. Chaque outil correspond à une instruction SQL paramétrée. Toolbox gère le regroupement des connexions, les requêtes paramétrées, l'authentification et l'observabilité. Les outils sont dissociés de l'agent. Vous pouvez mettre à jour une requête en modifiant tools.yaml et en redémarrant la boîte à outils, sans toucher au code de l'agent. Les mêmes outils fonctionnent avec ADK, LangGraph, LlamaIndex ou tout framework compatible avec MCP.
Écrire la configuration des outils
Nous devons maintenant créer un fichier nommé tools.yaml dans l'éditeur Cloud Shell pour configurer nos outils.
cloudshell edit tools.yaml
Le fichier utilise le format YAML multidocument : chaque bloc séparé par --- est une ressource autonome. Chaque ressource possède un kind qui déclare ce qu'elle est (sources pour les connexions à la base de données, tools pour les actions appelables par l'agent) et un type qui spécifie le backend (cloud-sql-postgres pour la source, postgres-sql pour les outils basés sur SQL). Un outil fait référence à sa source par name, ce qui permet à Toolbox de savoir quel pool de connexions exécuter. Les variables d'environnement utilisent la syntaxe ${VAR_NAME} et sont résolues au démarrage.
Copions d'abord les scripts suivants dans le fichier 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}
---
Ce script définit la ressource suivante :
- Source (
jobs-db) : indique à Toolbox comment se connecter à votre instance Cloud SQL pour PostgreSQL. Le typecloud-sql-postgresutilise le connecteur Cloud SQL en interne, en gérant automatiquement l'authentification et les connexions sécurisées. Les espaces réservés${GOOGLE_CLOUD_PROJECT},${REGION}et${DB_PASSWORD}sont résolus à partir des variables d'environnement au démarrage.
Ensuite, ajoutez le script suivant sous le symbole --- dans 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)."
---
Ce script définit la ressource suivante :
- Outils 1 et 2 (
search-jobs,get-job-details) : outils de requête SQL standard. Chacun mappe un nom d'outil (ce que l'agent voit) à une instruction SQL paramétrée (ce que la base de données exécute). Les paramètres utilisent des espaces réservés positionnels$1et$2. Toolbox les exécute en tant qu'instructions préparées, ce qui empêche l'injection SQL.
Continuons. Ajoutez le script suivant sous le symbole --- dans 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
---
Ce script définit la ressource suivante :
- Modèle d'embedding (
gemini-embedding) : configure la boîte à outils pour appeler le modèlegemini-embedding-001de Gemini afin de générer des embeddings de texte à 3 072 dimensions. Toolbox utilise les identifiants par défaut de l'application (ADC) pour s'authentifier. Aucune clé API n'est requise dans Cloud Shell ni dans Cloud Run. Note that thisdimensionconfigured here must be the same with previously we config to seed the database
Continuons. Ajoutez le script suivant sous le symbole --- dans 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
---
Ce script définit la ressource suivante :
- Outil 3 (
search-jobs-by-description) : outil de recherche vectorielle. Le paramètresearch_querya la valeurembeddedBy: gemini-embedding, ce qui indique à Toolbox d'intercepter le texte brut, de l'envoyer au modèle d'embedding et d'utiliser le vecteur résultant dans l'instruction SQL. L'opérateur<=>est la distance cosinus de pgvector. Plus les valeurs sont petites, plus les descriptions sont similaires.
Enfin, ajoutez le dernier outil sous le symbole --- dans 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
Ce script définit la ressource suivante :
- Outil 4 (
add-job) : montre l'ingestion de vecteurs. Le paramètredescription_vectorcomporte deux champs spéciaux : valueFromParam: description: la boîte à outils copie la valeur du paramètredescriptiondans celui-ci. Le LLM ne voit jamais ce paramètre.embeddedBy: gemini-embedding: la boîte à outils intègre le texte copié dans un vecteur avant de le transmettre au code SQL.
Résultat : un appel d'outil stocke à la fois le texte de description brut et son embedding vectoriel, sans que l'agent n'ait aucune connaissance des embeddings.
Le format YAML multidocument sépare chaque ressource par ---. Chaque document comporte des champs kind, name et type qui définissent ce qu'il est. En résumé, nous avons déjà configuré tous les éléments suivants :
- Définir la base de données source
- Définissez des outils ( outil 1 et outil 2) pour interroger la base de données avec un filtre standard.
- Définir le modèle d'embedding
- Définir l'outil de recherche vectorielle ( outil 3) pour la base de données
- Définissez l'outil d'ingestion de données vectorielles ( outil 4) dans la base de données.
6. Exécuter le serveur MCP Toolbox
À l'étape précédente, nous avons déjà défini la configuration nécessaire pour notre MCP Toolbox. Nous sommes maintenant prêts à exécuter le serveur.
Vérifier les données d'amorçage
Avant de démarrer Toolbox, vérifions que la configuration de la base de données est terminée. Créez un script Python scripts/verify_database.py à l'aide de la commande suivante :
cloudshell edit scripts/verify_seed.py
Ensuite, copiez le code suivant dans le fichier 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)
Ce script vérifie le nombre de données de fiches de poste et leur intégration. Exécutez le script à l'aide de la commande suivante :
uv run scripts/verify_seed.py
Si le résultat suivant s'affiche dans le terminal, cela signifie que les données sont prêtes.
Jobs: 15/15 Embeddings: 15/15 ✓ Database ready!
Démarrer le serveur de la boîte à outils
Lors de l'étape de configuration précédente, nous avons déjà téléchargé l'exécutable toolbox. Assurez-vous que ce fichier binaire existe et qu'il a été téléchargé correctement. Si ce n'est pas le cas, téléchargez-le et attendez la fin du téléchargement.
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
Nous devrons exposer nos variables .env au processus enfant exécuté par la boîte à outils MCP. Exécutez la commande suivante pour démarrer le serveur de la boîte à outils et consigner la sortie de la console dans le fichier logs/mcp_toolbox.log.
set -a; source .env; set +a
./toolbox --config tools.yaml --enable-api > logs/mcp_toolbox.log 2>&1 &
Dans le fichier logs/mcp_toolbox.log, vous devriez voir un résultat confirmant que le serveur est prêt, comme indiqué ci-dessous :
... 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!"
Vérifier les outils
Interrogez l'API Toolbox pour lister tous les outils enregistrés :
curl -s http://localhost:5000/api/toolset | uv run -m json.tool
Vous devriez voir les outils avec leurs descriptions et leurs paramètres. Comme indiqué ci-dessous
...
"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": []
}
...
Testez directement l'outil 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 réponse doit contenir les deux offres d'emploi d'ingénieur backend issues de vos données de départ.
[
{
"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. Créer l'agent ADK
Nous allons maintenant utiliser ADK en Python pour ce projet. Ajoutons les dépendances requises :
uv add google-adk==1.29.0 toolbox-adk==1.0.0
google-adk: kit de développement d'agents de Google, y compris le SDK Geminitoolbox-adk: intégration ADK pour MCP Toolbox for Databases.
Créer la structure de répertoire de l'agent
L'ADK attend une structure de dossier spécifique : un répertoire nommé d'après votre agent contenant __init__.py, agent.py et .env. Pour vous aider, il dispose d'une commande intégrée permettant d'établir rapidement la structure :
uv run adk create jobs_agent \
--model gemini-2.5-flash \
--project ${GOOGLE_CLOUD_PROJECT} \
--region ${GOOGLE_CLOUD_LOCATION}
Votre répertoire devrait maintenant se présenter comme suit :
build-agent-adk-toolbox-cloudsql/ ├── jobs_agent/ │ ├── __init__.py │ ├── agent.py │ └── .env ├── logs ├── scripts └── ...
Nous devons ensuite intégrer l'agent ADK au serveur Toolbox en cours d'exécution et tester les quatre outils : requêtes standards, recherche sémantique et ingestion de vecteurs. Le code de l'agent est minimal : toute la logique de la base de données se trouve dans tools.yaml.
Configurer l'environnement de l'agent
ADK lit GOOGLE_GENAI_USE_VERTEXAI, GOOGLE_CLOUD_PROJECT et GOOGLE_CLOUD_LOCATION à partir de l'environnement shell, que vous avez déjà défini à l'étape précédente. La seule variable spécifique à l'agent est TOOLBOX_URL. Ajoutez-la au fichier .env de l'agent :
echo -e "\nTOOLBOX_URL=http://127.0.0.1:5000" >> jobs_agent/.env
Mettre à jour le module d'agent
Ouvrez jobs_agent/agent.py dans l'éditeur Cloud Shell.
cloudshell edit jobs_agent/agent.py
et remplacez le contenu par le code suivant :
# 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],
)
Notez qu'il n'y a pas de code de base de données ici : ToolboxToolset se connecte au serveur de la boîte à outils au démarrage et charge tous les outils disponibles. L'agent appelle les outils par leur nom. Toolbox traduit ces appels en requêtes SQL sur Cloud SQL.
La variable d'environnement TOOLBOX_URL est définie par défaut sur http://127.0.0.1:5000 pour le développement local. Lorsque vous déploierez sur Cloud Run ultérieurement, vous remplacerez cette valeur par l'URL Cloud Run du service Toolbox. Aucune modification de code n'est nécessaire.
L'instruction ne fait actuellement référence qu'aux deux outils standards (search-jobs et get-job-details). Vous l'étendrez à l'étape suivante lorsque vous ajouterez des outils d'ingestion et de recherche sémantique.
Tester l'agent
Démarrez l'UI de développement ADK :
cd ~/build-agent-adk-toolbox-cloudsql
uv run adk web --allow_origins "regex:https://.*\.cloudshell\.dev"
Ouvrez l'URL affichée dans le terminal (généralement http://localhost:8000) à l'aide de la fonctionnalité Aperçu sur le Web de Cloud Shell ou en cliquant sur l'URL tout en appuyant sur la touche Ctrl. Sélectionnez jobs_agent dans le menu déroulant des agents en haut à gauche.
Tester les requêtes standards
Essayez ces requêtes pour vérifier les outils SQL standard :
What backend engineering jobs do you have?
Any jobs using Kubernetes?
Tell me about the Cloud Architect position

Tester la recherche sémantique
Essayez des descriptions en langage naturel qui ne correspondent pas à un rôle ou à une pile technologique spécifiques :
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'agent essaiera de choisir le bon outil en fonction du type de requête : les filtres structurés passent par search-jobs, tandis que les descriptions en langage naturel passent par search-jobs-by-description.

Tester l'ingestion de vecteurs
Demandez à l'agent d'ajouter un 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.

Essayez maintenant de le rechercher :
Find me jobs involving autonomous systems and working with physical hardware
L'embedding a été généré automatiquement lors de l'insertion. Aucune étape distincte n'est nécessaire.

Vous disposez désormais d'une application RAG agentique entièrement fonctionnelle utilisant ADK, MCP Toolbox et Cloud SQL. Félicitations ! Allons plus loin et déployons ces applications sur Cloud Run.
Maintenant, arrêtons l'UI de développement en arrêtant le processus en appuyant deux fois sur Ctrl+C avant de continuer.
8. Déployer dans Cloud Run
L'agent et la boîte à outils fonctionnent en local. Cette étape déploie les deux en tant que services Cloud Run afin qu'ils soient accessibles sur Internet. Le service Toolbox s'exécute en tant que serveur MCP sur Cloud Run, auquel se connecte le service d'agent.
Préparer la boîte à outils pour le déploiement
Créez un répertoire de déploiement pour le service Toolbox :
cd ~/build-agent-adk-toolbox-cloudsql
mkdir -p deploy-toolbox
cp toolbox tools.yaml deploy-toolbox/
Créez le fichier Dockerfile pour la boîte à outils. Ouvrez deploy-toolbox/Dockerfile dans l'éditeur Cloud Shell :
cloudshell edit deploy-toolbox/Dockerfile
Copiez-y le script suivant :
# 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"]
Le binaire Toolbox et tools.yaml sont inclus dans une image Debian minimale. Cloud Run achemine le trafic vers le port 8080.
Déployer le service de boîte à outils
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 &
Cette commande envoie la source à Cloud Build, crée une image de conteneur, la transmet à Artifact Registry et la déploie sur Cloud Run. Cela prendra quelques minutes. Nous pouvons inspecter le journal du processus de déploiement dans le fichier logs/deploy_toolbox.log.
Préparer l'agent pour le déploiement
Pendant la compilation de la boîte à outils, configurez les fichiers de déploiement de l'agent.
Créez un fichier Dockerfile à la racine du projet. Ouvrez Dockerfile dans l'éditeur Cloud Shell :
cloudshell edit Dockerfile
Copiez ensuite le contenu suivant :
# 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"]
Ce fichier Dockerfile utilise ghcr.io/astral-sh/uv comme image de base, qui inclut Python et uv préinstallés. Il n'est donc pas nécessaire d'installer uv séparément via pip.
Créez un fichier .dockerignore pour exclure les fichiers inutiles de l'image de conteneur :
cloudshell edit .dockerignore
Copiez ensuite le script suivant dans le fichier.
# .dockerignore
.venv/
__pycache__/
*.pyc
.env
jobs_agent/.env
toolbox
tools.yaml
seed.sql
deploy-toolbox/
Déployer le service d'agent
Attendez la fin du déploiement de Toolbox. Vérifiez à nouveau le processus de déploiement sur logs/deploy_toolbox.log pour le valider. Récupérez ensuite son URL Cloud Run à l'aide de la commande suivante.
TOOLBOX_URL=$(gcloud run services describe toolbox-service \
--region=$REGION \
--format='value(status.url)')
echo "Toolbox URL: $TOOLBOX_URL"
Vous obtiendrez un résultat semblable à celui-ci :
Toolbox URL: https://toolbox-service-xxxxxx-xx.a.run.app
Vérifions ensuite que la boîte à outils déployée fonctionne :
curl -s "$TOOLBOX_URL/api/toolset" | python3 -m json.tool | head -5
Si le résultat est semblable à cet exemple, le déploiement a déjà réussi.
{
"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.",
Ensuite, déployons l'agent en transmettant l'URL de la boîte à outils en tant que variable d'environnement :
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
Le code de l'agent lit TOOLBOX_URL à partir de l'environnement (que vous avez configuré précédemment). Localement, il pointe vers http://127.0.0.1:5000. Sur Cloud Run, il pointe vers l'URL du service Toolbox. Aucune modification de code n'est nécessaire.
Tester l'agent déployé
Récupérez l'URL Cloud Run de l'agent :
AGENT_URL=$(gcloud run services describe jobs-agent \
--region=$REGION \
--format='value(status.url)')
echo "Agent URL: $AGENT_URL"
Ouvrez l'URL dans votre navigateur. L'UI de développement ADK se charge. Il s'agit de la même interface que celle que vous avez utilisée en local, mais elle s'exécute désormais sur Cloud Run.
Sélectionnez jobs_agent dans le menu déroulant, puis testez :
What backend engineering jobs do you have?
I want a remote job working on AI and machine learning
Les deux requêtes fonctionnent via les services déployés : l'agent sur Cloud Run appelle la boîte à outils sur Cloud Run, qui interroge Cloud SQL.
9. Félicitations / Nettoyage
Vous avez créé et déployé un assistant de tableau d'offres d'emploi intelligent qui utilise MCP Toolbox for Databases pour faire le lien entre un agent ADK et Cloud SQL PostgreSQL, à la fois avec des requêtes SQL standards et la recherche vectorielle sémantique.
Connaissances acquises
- Comment MCP standardise l'accès aux outils pour les agents d'IA et comment MCP Toolbox for Databases applique cela spécifiquement aux opérations de base de données, en remplaçant le code de base de données personnalisé par une configuration YAML déclarative
- Configurer Cloud SQL PostgreSQL comme source de données Boîte à outils à l'aide du type de source
cloud-sql-postgres - Définir des outils de requête SQL standard avec des instructions paramétrées qui empêchent l'injection SQL
- Activer la recherche vectorielle à l'aide de pgvector et de
gemini-embedding-001, avec le paramètreembeddedBypour l'embedding automatique des requêtes - Comment
valueFromParampermet l'ingestion automatique de vecteurs : le LLM fournit une description textuelle, et la boîte à outils copie, intègre et stocke silencieusement le vecteur à côté du texte. - Comment
ToolboxToolsetde l'ADK charge les outils à partir d'un serveur Toolbox en cours d'exécution, en gardant le code de l'agent minimal et la logique de la base de données entièrement découplée - Déployer le serveur Toolbox MCP et l'agent ADK sur Cloud Run en tant que services distincts
Nettoyage
Pour éviter que les ressources créées dans cet atelier de programmation ne soient facturées sur votre compte Google Cloud, vous pouvez supprimer les ressources individuelles ou l'intégralité du projet.
Option 1 : Supprimer le projet (recommandé)
Le moyen le plus simple d'effectuer un nettoyage consiste à supprimer le projet. Toutes les ressources associées au projet sont alors supprimées.
gcloud projects delete $GOOGLE_CLOUD_PROJECT
Option 2 : Supprimer des ressources individuelles
Si vous souhaitez conserver le projet, mais supprimer uniquement les ressources créées dans cet atelier de programmation :
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
