1. 📖 Einführung
Im vorherigen Codelab haben Sie gelernt , wie Sie eine multimodale Dateninteraktion im ADK entwerfen. Als Nächstes sehen wir uns an, wie Sie mit dem MCP-Toolset eine multimodale Dateninteraktion mit dem MCP-Server entwerfen. Wir werden die Funktionen des zuvor entwickelten Agents für die Bearbeitung von Produktfotos erweitern, um kurze Videos mit dem Veo-Modell über den Veo-MCP-Server zu generieren.
In diesem Codelab gehen Sie schrittweise so vor:
- Google Cloud-Projekt und Basis-Agent-Verzeichnis vorbereiten
- MCP-Server konfigurieren, für die Dateidaten als Eingabe erforderlich sind
- ADK-Agent für die Verbindung mit dem MCP-Server vorbereiten
- Prompt-Strategie und Callback-Funktion zum Ändern von Funktionsaufrufanfragen an das MCP Toolset entwerfen
- Callback-Funktion für die Verarbeitung multimodaler Datenantworten aus dem MCP Toolset entwerfen
Architekturübersicht
Die gesamte Interaktion in diesem Codelab wird im folgenden Diagramm dargestellt.

Voraussetzungen
- Vertrautheit mit Python
- (Optional) Grundlegende Codelabs zum Agent Development Kit (ADK)
- (Optional) Codelab „ADK Multimodal Tool Part 1“: goo.gle/adk-multimodal-tool-1
Lerninhalte
- Kurzvideos mit Veo 3.1 erstellen – mit Prompt und Bild als Ausgangspunkt
- Multimodalen MCP-Server mit FastMCP entwickeln
- ADK für die Verwendung von MCP-Toolsets einrichten
- Toolaufruf an MCP-Toolset über Tool-Callback ändern
- Tool-Antwort aus dem MCP Toolset über Tool-Callback ändern
Voraussetzungen
- Chrome-Webbrowser
- Ein Gmail-Konto
- Ein Cloud-Projekt mit aktiviertem Abrechnungskonto
In diesem Codelab, das sich an Entwickler aller Erfahrungsstufen (auch Anfänger) richtet, wird Python in der Beispielanwendung verwendet. Python-Kenntnisse sind jedoch nicht erforderlich, um die vorgestellten Konzepte zu verstehen.
2. 🚀 ( Optional) Workshop-Entwicklungsumgebung vorbereiten
Schritt 1: Aktives Projekt in der Cloud Console auswählen
Wählen Sie in der Google Cloud Console auf der Seite zur Projektauswahl ein Google Cloud-Projekt aus oder erstellen Sie eines (siehe oben links in der Console).

Klicken Sie darauf, um eine Liste aller Ihrer Projekte aufzurufen, wie in diesem Beispiel:

Der Wert, der durch das rote Kästchen angegeben wird, ist die PROJEKT-ID. Dieser Wert wird im gesamten Tutorial verwendet.
Die Abrechnung für das Cloud-Projekt muss aktiviert sein. Klicken Sie dazu links oben in der Leiste auf das Dreistrich-Menü ☰, um das Navigationsmenü aufzurufen, und suchen Sie nach dem Abrechnungsmenü.

Wenn Sie unter dem Titel Abrechnung / Übersicht ( oben links in der Cloud Console ) das Google Cloud Platform-Testabrechnungskonto sehen, kann Ihr Projekt für diese Anleitung verwendet werden. Falls nicht, kehren Sie zum Anfang dieses Tutorials zurück und lösen Sie das Abrechnungskonto für den Testzeitraum ein.

Schritt 2: Mit Cloud Shell vertraut machen
Für den Großteil der Anleitungen verwenden Sie Cloud Shell. Klicken Sie dazu oben in der Google Cloud Console auf „Cloud Shell aktivieren“. Wenn Sie zur Autorisierung aufgefordert werden, klicken Sie auf Autorisieren.


Nachdem Sie eine Verbindung zu Cloud Shell hergestellt haben, müssen wir prüfen, ob die Shell ( oder das Terminal) bereits mit Ihrem Konto authentifiziert ist.
gcloud auth list
Wenn Sie Ihr privates Gmail-Konto wie im Beispiel unten sehen, ist alles in Ordnung.
Credentialed Accounts
ACTIVE: *
ACCOUNT: alvinprayuda@gmail.com
To set the active account, run:
$ gcloud config set account `ACCOUNT`
Falls nicht, aktualisieren Sie Ihren Browser und klicken Sie auf Autorisieren, wenn Sie dazu aufgefordert werden. Möglicherweise wurde die Verbindung unterbrochen.
Als Nächstes müssen wir prüfen, ob die Shell bereits für die richtige PROJECT ID konfiguriert ist. Wenn im Terminal vor dem Symbol „$“ ein Wert in Klammern angezeigt wird (im Screenshot unten ist der Wert adk-multimodal-tool), gibt dieser Wert das konfigurierte Projekt für Ihre aktive Shell-Sitzung an.

Wenn der angezeigte Wert bereits korrekt ist, können Sie den nächsten Befehl überspringen. Wenn sie nicht korrekt ist oder fehlt, führen Sie den folgenden Befehl aus:
gcloud config set project <YOUR_PROJECT_ID>
Klonen Sie dann das Arbeitsverzeichnis der Vorlage für dieses Codelab von GitHub, indem Sie den folgenden Befehl ausführen. Das Arbeitsverzeichnis wird im Verzeichnis adk-multimodal-tool erstellt.
git clone https://github.com/alphinside/adk-mcp-multimodal.git adk-multimodal-tool
Schritt 3: Cloud Shell-Editor kennenlernen und Arbeitsverzeichnis der Anwendung einrichten
Jetzt können wir unseren Code-Editor für einige Programmieraufgaben einrichten. Dazu verwenden wir den Cloud Shell-Editor.
Klicken Sie auf die Schaltfläche Editor öffnen, um den Cloud Shell-Editor
zu öffnen.
Klicken Sie dann oben im Cloud Shell-Editor auf Datei > Ordner öffnen, suchen Sie nach dem Verzeichnis Nutzername und dann nach dem Verzeichnis adk-multimodal-tool und klicken Sie auf die Schaltfläche „OK“. Dadurch wird das ausgewählte Verzeichnis zum Hauptarbeitsverzeichnis. In diesem Beispiel ist der Nutzername alvinprayuda. Der Verzeichnispfad wird unten angezeigt.


Ihr Cloud Shell-Editor-Arbeitsverzeichnis sollte nun so aussehen ( im Verzeichnis adk-multimodal-tool):

Öffnen Sie nun das Terminal für den Editor. Klicken Sie dazu in der Menüleiste auf Terminal -> Neues Terminal oder verwenden Sie die Tastenkombination Strg + Umschalt + C. Dadurch wird unten im Browser ein Terminalfenster geöffnet.

Ihr aktuelles aktives Terminal sollte sich im Arbeitsverzeichnis adk-multimodal-tool befinden. In diesem Codelab verwenden wir Python 3.12 und den uv-Python-Projektmanager, um das Erstellen und Verwalten von Python-Versionen und virtuellen Umgebungen zu vereinfachen. Das uv-Paket ist bereits in Cloud Shell vorinstalliert.
Führen Sie diesen Befehl aus, um die erforderlichen Abhängigkeiten in der virtuellen Umgebung im Verzeichnis .venv zu installieren.
uv sync --frozen
Sehen Sie sich die deklarierten Abhängigkeiten für diese Anleitung in der Datei pyproject.toml an. Sie lauten google-adk, and python-dotenv.
Jetzt müssen wir die erforderlichen APIs über den unten gezeigten Befehl aktivieren. Das kann etwas dauern.
gcloud services enable aiplatform.googleapis.com
Bei erfolgreicher Ausführung des Befehls sollte eine Meldung wie die unten gezeigte angezeigt werden:
Operation "operations/..." finished successfully.
Die Vorlagenstruktur für den Agent ist bereits im Verzeichnis part2_starter_agent des geklonten Repositorys enthalten. Für dieses Tutorial müssen wir sie zuerst umbenennen.
mv part1_ckpt_agent product_photo_editor
Kopieren Sie danach die Datei product_photo_editor/.env.example nach product_photo_editor/.env.
cp product_photo_editor/.env.example product_photo_editor/.env
Wenn Sie die Datei product_photo_editor/.env öffnen, sehen Sie Inhalte wie unten dargestellt.
GOOGLE_GENAI_USE_VERTEXAI=1
GOOGLE_CLOUD_PROJECT=your-project-id
GOOGLE_CLOUD_LOCATION=global
Anschließend müssen Sie den Wert your-project-id durch Ihre eigene Projekt-ID ersetzen. Jetzt sind wir bereit für den nächsten Schritt.
3. 🚀 Veo-MCP-Server initialisieren
Erstellen Sie zuerst das MCP-Dienstverzeichnis mit diesem Befehl:
mkdir veo_mcp
Erstellen Sie dann veo_mcp/main.py mit diesem Befehl.
touch veo_mcp/main.py
Kopieren Sie danach den folgenden Code in veo_mcp/main.py.
from fastmcp import FastMCP
from typing import Annotated
from pydantic import Field
import base64
import asyncio
import os
from google import genai
from google.genai import types
from dotenv import load_dotenv
import logging
# Load environment variables from .env file
load_dotenv()
mcp = FastMCP("Veo MCP Server")
@mcp.tool
async def generate_video_with_image(
prompt: Annotated[
str, Field(description="Text description of the video to generate")
],
image_data: Annotated[
str, Field(description="Base64-encoded image data to use as starting frame")
],
negative_prompt: Annotated[
str | None,
Field(description="Things to avoid in the generated video"),
] = None,
) -> dict:
"""Generates a professional product marketing video from text prompt and starting image using Google's Veo API.
This function uses an image as the first frame of the generated video and automatically
enriches your prompt with professional video production quality guidelines to create
high-quality marketing assets suitable for commercial use.
AUTOMATIC ENHANCEMENTS APPLIED:
- 4K cinematic quality with professional color grading
- Smooth, stabilized camera movements
- Professional studio lighting setup
- Shallow depth of field for product focus
- Commercial-grade production quality
- Marketing-focused visual style
PROMPT WRITING TIPS:
Describe what you want to see in the video. Focus on:
- Product actions/movements (e.g., "rotating slowly", "zooming into details")
- Desired camera angles (e.g., "close-up of the product", "wide shot")
- Background/environment (e.g., "minimalist white backdrop", "lifestyle setting")
- Any specific details about the product presentation
The system will automatically enhance your prompt with professional production quality.
Args:
prompt: Description of the video to generate. Focus on the core product presentation
you want. The system will automatically add professional quality enhancements.
image_data: Base64-encoded image data to use as the starting frame
negative_prompt: Optional prompt describing what to avoid in the video
Returns:
dict: A dictionary containing:
- status: 'success' or 'error'
- message: Description of the result
- video_data: Base64-encoded video data (on success only)
"""
try:
# Initialize the Gemini client
client = genai.Client(
vertexai=True,
project=os.getenv("GOOGLE_CLOUD_PROJECT"),
location=os.getenv("GOOGLE_CLOUD_LOCATION"),
)
# Decode the image
image_bytes = base64.b64decode(image_data)
print(f"Successfully decoded image data: {len(image_bytes)} bytes")
# Create image object
image = types.Image(image_bytes=image_bytes, mime_type="image/png")
# Prepare the config
config = types.GenerateVideosConfig(
duration_seconds=8,
number_of_videos=1,
)
if negative_prompt:
config.negative_prompt = negative_prompt
# Enrich the prompt for professional marketing quality
enriched_prompt = enrich_prompt_for_marketing(prompt)
# Generate the video (async operation)
operation = client.models.generate_videos(
model="veo-3.1-generate-preview",
prompt=enriched_prompt,
image=image,
config=config,
)
# Poll until the operation is complete
poll_count = 0
while not operation.done:
poll_count += 1
print(f"Waiting for video generation to complete... (poll {poll_count})")
await asyncio.sleep(5)
operation = client.operations.get(operation)
# Download the video and convert to base64
video = operation.response.generated_videos[0]
# Get video bytes and encode to base64
video_bytes = video.video.video_bytes
video_base64 = base64.b64encode(video_bytes).decode("utf-8")
print(f"Video generated successfully: {len(video_bytes)} bytes")
return {
"status": "success",
"message": f"Video with image generated successfully after {poll_count * 5} seconds",
"complete_prompt": enriched_prompt,
"video_data": video_base64,
}
except Exception as e:
logging.error(e)
return {
"status": "error",
"message": f"Error generating video with image: {str(e)}",
}
def enrich_prompt_for_marketing(user_prompt: str) -> str:
"""Enriches user prompt with professional video production quality enhancements.
Adds cinematic quality, professional lighting, smooth camera work, and marketing-focused
elements to ensure high-quality product marketing videos.
"""
enhancement_prefix = """Create a high-quality, professional product marketing video with the following characteristics:
TECHNICAL SPECIFICATIONS:
- 4K cinematic quality with professional color grading
- Smooth, stabilized camera movements
- Professional studio lighting setup with soft, even illumination
- Shallow depth of field for product focus
- High dynamic range (HDR) for vibrant colors
VISUAL STYLE:
- Clean, minimalist aesthetic suitable for premium brand marketing
- Elegant and sophisticated presentation
- Commercial-grade production quality
- Attention to detail in product showcase
USER'S SPECIFIC REQUIREMENTS:
"""
enhancement_suffix = """
ADDITIONAL QUALITY GUIDELINES:
- Ensure smooth transitions and natural motion
- Maintain consistent lighting throughout
- Keep the product as the clear focal point
- Use professional camera techniques (slow pans, tracking shots, or dolly movements)
- Apply subtle motion blur for cinematic feel
- Ensure brand-appropriate tone and style"""
return f"{enhancement_prefix}{user_prompt}{enhancement_suffix}"
if __name__ == "__main__":
mcp.run()
Der folgende Code führt die folgenden Aktionen aus:
- Erstellt einen FastMCP-Server, der ein Veo 3.1-Tool zur Videogenerierung für ADK-Agents bereitstellt.
- Akzeptiert base64-codierte Bilder, Text-Prompts und negative Prompts als Eingabe.
- Erstellt asynchron 8‑sekündige Videos, indem Anfragen an die Veo 3.1 API gesendet und alle 5 Sekunden abgefragt werden, bis die Erstellung abgeschlossen ist.
- Gibt base64-codierte Videodaten zusammen mit dem angereicherten Prompt zurück
Für dieses Veo MCP-Tool ist dieselbe Umgebungsvariable wie für unseren Agent erforderlich. Wir können die .env-Datei also einfach kopieren und einfügen. Führen Sie dazu den folgenden Befehl aus:
cp product_photo_editor/.env veo_mcp/
Jetzt können wir mit diesem Befehl testen, ob der MCP-Server richtig ausgeführt wird:
uv run veo_mcp/main.py
Das Konsolenlog wird so angezeigt:
╭────────────────────────────────────────────────────────────────────────────╮
│ │
│ _ __ ___ _____ __ __ _____________ ____ ____ │
│ _ __ ___ .'____/___ ______/ /_/ |/ / ____/ __ \ |___ \ / __ \ │
│ _ __ ___ / /_ / __ `/ ___/ __/ /|_/ / / / /_/ / ___/ / / / / / │
│ _ __ ___ / __/ / /_/ (__ ) /_/ / / / /___/ ____/ / __/_/ /_/ / │
│ _ __ ___ /_/ \____/____/\__/_/ /_/\____/_/ /_____(*)____/ │
│ │
│ │
│ FastMCP 2.0 │
│ │
│ │
│ 🖥️ Server name: Veo MCP Server │
│ 📦 Transport: STDIO │
│ │
│ 🏎️ FastMCP version: 2.12.5 │
│ 🤝 MCP SDK version: 1.16.0 │
│ │
│ 📚 Docs: https://gofastmcp.com │
│ 🚀 Deploy: https://fastmcp.cloud │
│ │
╰────────────────────────────────────────────────────────────────────────────╯
[10/22/25 08:28:53] INFO Starting MCP server 'Veo MCP Server' with server.py:1502
transport 'stdio'
Beenden Sie nun den MCP-Dienstprozess mit STRG+C. Dieser Befehl wird später über das ADK MCP Toolset aufgerufen. Wir können mit dem nächsten Schritt fortfahren, damit unser Kundenservicemitarbeiter dieses MCP-Tool verwenden kann.
4. 🚀 Veo-MCP-Server mit ADK-Agent verbinden
Verbinden wir nun den Veo-MCP-Server, damit er von unserem KI-Agenten verwendet werden kann. Erstellen wir zuerst ein anderes Skript, das das Toolset enthält. Führen Sie dazu den folgenden Befehl aus:
touch product_photo_editor/mcp_tools.py
Kopieren Sie dann den folgenden Code in product_photo_editor/mcp_tools.py.
from google.adk.tools.mcp_tool.mcp_toolset import MCPToolset
from google.adk.tools.mcp_tool.mcp_session_manager import StdioConnectionParams
from mcp import StdioServerParameters
mcp_toolset = MCPToolset(
connection_params=StdioConnectionParams(
server_params=StdioServerParameters(
command="uv",
args=[
"run",
"veo_mcp/main.py",
],
),
timeout=120, # seconds
),
)
# Option to connect to remote MCP server
# from google.adk.tools.mcp_tool.mcp_session_manager import StreamableHTTPConnectionParams
# mcp_toolset = MCPToolset(
# connection_params=StreamableHTTPConnectionParams(
# url="http://localhost:8000/mcp",
# timeout=120,
# ),
# )
Der obige Code zeigt, wie wir mit ADK MCPToolset eine Verbindung zu einem MCP-Server herstellen können. In diesem Beispiel stellen wir über den STDIO-Kommunikationskanal eine Verbindung zum MCP-Server her. Im Befehl geben wir an, wie der MCP-Server ausgeführt und der Zeitüberschreitungsparameter festgelegt werden kann.
5. 🚀 Änderung von Tool-Aufrufparametern
In der MCP-Server-Tooldeklaration haben wir das Tool generate_video_with_image entworfen, in dem Base64-String als Tool-Parameter angegeben wird. Wir können das LLM nicht darum bitten, das für uns zu erledigen. Daher müssen wir eine spezielle Strategie dafür entwickeln.
Im vorherigen Lab haben wir das vom Nutzer hochgeladene Bild und das Tool-Antwortbild in before_model_callback verarbeitet, um es als Artefakt zu speichern. Das wird auch in der zuvor vorbereiteten Agent-Vorlage berücksichtigt. Wir werden diese Informationen nutzen und folgende Strategien anwenden:
- Weisen Sie das LLM an, den Wert „artifact_id“ immer zu senden, wenn für bestimmte Tool-Parameter das Senden von Base64-Stringdaten erforderlich ist.
- Fangen Sie den Toolaufruf in
before_tool_callbackab und wandeln Sie den Parameter von der artifact_id in den Byte-Inhalt um, indem Sie das Artefakt laden und die Toolargumente überschreiben.
Das folgende Bild zeigt den Teil, den wir abfangen.

Bereiten Sie zuerst die Funktion before_tool_callback vor. Erstellen Sie dazu mit dem folgenden Befehl eine neue Datei product_photo_editor/tool_callbacks.py.
touch product_photo_editor/tool_callbacks.py
Kopieren Sie dann den folgenden Code in die Datei.
# product_photo_editor/tool_callbacks.py
from google.genai.types import Part
from typing import Any
from google.adk.tools.tool_context import ToolContext
from google.adk.tools.base_tool import BaseTool
from google.adk.tools.mcp_tool.mcp_tool import McpTool
import base64
import logging
import json
from mcp.types import CallToolResult
async def before_tool_modifier(
tool: BaseTool, args: dict[str, Any], tool_context: ToolContext
):
# Identify which tool input should be modified
if isinstance(tool, McpTool) and tool.name == "generate_video_with_image":
logging.info("Modify tool args for artifact: %s", args["image_data"])
# Get the artifact filename from the tool input argument
artifact_filename = args["image_data"]
artifact = await tool_context.load_artifact(filename=artifact_filename)
file_data = artifact.inline_data.data
# Convert byte data to base64 string
base64_data = base64.b64encode(file_data).decode("utf-8")
# Then modify the tool input argument
args["image_data"] = base64_data
Der obige Code zeigt die folgenden Schritte:
- Prüfen Sie, ob das aufgerufene Tool ein McpTool-Objekt ist und ob es sich um den Ziel-Toolaufruf handelt, den wir ändern möchten.
- Rufen Sie den Wert von
image_data-Argumenten ab, wobei das Argument in Base64-Format angefordert wird, aber wir das LLM bitten, die artifact_id dafür zurückzugeben. - Laden Sie das Artefakt über den Artefaktdienst auf
tool_context. image_data-Argumente mit den Base64-Daten überschreiben
Jetzt müssen wir diesen Callback dem Agent hinzufügen und die Anleitung leicht anpassen, damit der Agent die Base64-Tool-Argumente immer mit der Artefakt-ID füllt.
Öffnen Sie product_photo_editor/agent.py und ändern Sie den Inhalt mit dem folgenden Code.
# product_photo_editor/agent.py
from google.adk.agents.llm_agent import Agent
from product_photo_editor.custom_tools import edit_product_asset
from product_photo_editor.mcp_tools import mcp_toolset
from product_photo_editor.model_callbacks import before_model_modifier
from product_photo_editor.tool_callbacks import before_tool_modifier
from product_photo_editor.prompt import AGENT_INSTRUCTION
root_agent = Agent(
model="gemini-2.5-flash",
name="product_photo_editor",
description="""A friendly product photo editor assistant that helps small business
owners edit and enhance their product photos. Perfect for improving photos of handmade
goods, food products, crafts, and small retail items""",
instruction=AGENT_INSTRUCTION
+ """
**IMPORTANT: Base64 Argument Rule on Tool Call**
If you found any tool call arguments that requires base64 data,
ALWAYS provide the artifact_id of the referenced file to
the tool call. NEVER ask user to provide base64 data.
Base64 data encoding process is out of your
responsibility and will be handled in another part of the system.
""",
tools=[
edit_product_asset,
mcp_toolset,
],
before_model_callback=before_model_modifier,
before_tool_callback=before_tool_modifier,
)
Jetzt versuchen wir, mit dem Agent zu interagieren, um diese Änderung zu testen. Führen Sie den folgenden Befehl aus, um die Webentwickler-UI zu starten.
uv run adk web --port 8080
Es wird eine Ausgabe wie im folgenden Beispiel erzeugt. Das bedeutet, dass wir bereits auf die Weboberfläche zugreifen können.
INFO: Started server process [xxxx] INFO: Waiting for application startup. +-----------------------------------------------------------------------------+ | ADK Web Server started | | | | For local testing, access at http://127.0.0.1:8080. | +-----------------------------------------------------------------------------+ INFO: Application startup complete. INFO: Uvicorn running on http://127.0.0.1:8080 (Press CTRL+C to quit)
Um die URL zu prüfen, können Sie Strg+Klicken darauf ausführen oder oben im Cloud Shell Editor auf die Schaltfläche Webvorschau klicken und Vorschau auf Port 8080 auswählen.

Auf der folgenden Webseite können Sie oben links im Drop-down-Menü verfügbare Agents auswählen ( in unserem Fall sollte es product_photo_editor sein) und mit dem Bot interagieren.
Lade dann das folgende Bild hoch und bitte den Kundenservicemitarbeiter, daraus einen Werbeclip zu erstellen.
Generate a slow zoom in and moving from left and right animation

Der folgende Fehler tritt auf:

Warum? Da das Tool die Ergebnisse auch direkt in Form eines Base64-Strings zurückgegeben hat, wird das maximale Token überschritten. Im nächsten Abschnitt wird dieser Fehler behoben.
6. 🚀 Tool-Antworten ändern
In diesem Abschnitt verarbeiten wir die Tool-Antwort aus der MCP-Antwort. Wir werden Folgendes tun:
- Videoantwort des Tools im Artefaktdienst speichern
- Stattdessen die Artefakt-ID an den Agent zurückgeben
Zur Erinnerung: Wir werden uns während der folgenden Laufzeit des Kundenservicemitarbeiters melden.

Implementieren wir zuerst die Callback-Funktion. Öffnen Sie die Datei product_photo_editor/tool_callbacks.py und ändern Sie sie, um after_tool_modifier zu implementieren.
# product_photo_editor/tool_callbacks.py
from google.genai.types import Part
from typing import Any
from google.adk.tools.tool_context import ToolContext
from google.adk.tools.base_tool import BaseTool
from google.adk.tools.mcp_tool.mcp_tool import McpTool
import base64
import logging
import json
from mcp.types import CallToolResult
async def before_tool_modifier(
tool: BaseTool, args: dict[str, Any], tool_context: ToolContext
):
# Identify which tool input should be modified
if isinstance(tool, McpTool) and tool.name == "generate_video_with_image":
logging.info("Modify tool args for artifact: %s", args["image_data"])
# Get the artifact filename from the tool input argument
artifact_filename = args["image_data"]
artifact = await tool_context.load_artifact(filename=artifact_filename)
file_data = artifact.inline_data.data
# Convert byte data to base64 string
base64_data = base64.b64encode(file_data).decode("utf-8")
# Then modify the tool input argument
args["image_data"] = base64_data
async def after_tool_modifier(
tool: BaseTool,
args: dict[str, Any],
tool_context: ToolContext,
tool_response: dict | CallToolResult,
):
if isinstance(tool, McpTool) and tool.name == "generate_video_with_image":
tool_result = json.loads(tool_response.content[0].text)
# Get the expected response field which contains the video data
video_data = tool_result["video_data"]
artifact_filename = f"video_{tool_context.function_call_id}.mp4"
# Convert base64 string to byte data
video_bytes = base64.b64decode(video_data)
# Save the video as artifact
await tool_context.save_artifact(
filename=artifact_filename,
artifact=Part(inline_data={"mime_type": "video/mp4", "data": video_bytes}),
)
# Remove the video data from the tool response
tool_result.pop("video_data")
# Then modify the tool response to include the artifact filename and remove the base64 string
tool_result["video_artifact_id"] = artifact_filename
logging.info(
"Modify tool response for artifact: %s", tool_result["video_artifact_id"]
)
return tool_result
Danach müssen wir unseren Agenten mit dieser Funktion ausstatten. Öffnen Sie product_photo_editor/agent.py und ändern Sie den Code so:
# product_photo_editor/agent.py
from google.adk.agents.llm_agent import Agent
from product_photo_editor.custom_tools import edit_product_asset
from product_photo_editor.mcp_tools import mcp_toolset
from product_photo_editor.model_callbacks import before_model_modifier
from product_photo_editor.tool_callbacks import (
before_tool_modifier,
after_tool_modifier,
)
from product_photo_editor.prompt import AGENT_INSTRUCTION
root_agent = Agent(
model="gemini-2.5-flash",
name="product_photo_editor",
description="""A friendly product photo editor assistant that helps small business
owners edit and enhance their product photos. Perfect for improving photos of handmade
goods, food products, crafts, and small retail items""",
instruction=AGENT_INSTRUCTION
+ """
**IMPORTANT: Base64 Argument Rule on Tool Call**
If you found any tool call arguments that requires base64 data,
ALWAYS provide the artifact_id of the referenced file to
the tool call. NEVER ask user to provide base64 data.
Base64 data encoding process is out of your
responsibility and will be handled in another part of the system.
""",
tools=[
edit_product_asset,
mcp_toolset,
],
before_model_callback=before_model_modifier,
before_tool_callback=before_tool_modifier,
after_tool_callback=after_tool_modifier,
)
Das war's. Jetzt können Sie den Agenten bitten, Ihnen nicht nur beim Bearbeiten des Fotos zu helfen, sondern auch ein Video für Sie zu generieren. Führen Sie den folgenden Befehl noch einmal aus.
uv run adk web --port 8080
Versuche dann, mit diesem Bild ein Video zu erstellen.
Generate a slow zoom in and moving from left and right animation

Das generierte Video wird wie im Beispiel unten angezeigt und bereits als Artefakt gespeichert.

7. ⭐ Zusammenfassung
Sehen wir uns noch einmal an, was wir in diesem Codelab bereits getan haben. Hier ist das Wichtigste:
- Verarbeitung multimodaler Daten (Tool-E/A): Die Strategie zur Verarbeitung multimodaler Daten (z. B. Bilder und Videos) für Tool-Ein- und ‑Ausgabe wurde durch die Verwendung des Artifacts-Dienstes des ADK und spezieller Callbacks anstelle der direkten Übergabe von Rohbytedaten verstärkt.
- Integration des MCP-Toolsets: Ein externer Veo-MCP-Server wurde mit FastMCP über das ADK-MCP-Toolset entwickelt und integriert, um dem Agenten Funktionen zur Videogenerierung hinzuzufügen.
- Änderung der Tool-Eingabe (before_tool_callback): Es wurde ein Callback implementiert, um den Aufruf des Tools „generate_video_with_image“ abzufangen und die vom LLM ausgewählte artifact_id der Datei in die erforderlichen base64-codierten Bilddaten für die Eingabe des MCP-Servers umzuwandeln.
- Änderung der Toolausgabe (after_tool_callback): Es wurde ein Callback implementiert, um die große base64-codierte Videoantwort vom MCP-Server abzufangen, das Video als neues Artefakt zu speichern und eine saubere video_artifact_id-Referenz an das LLM zurückzugeben.
8. 🧹 Bereinigen
So vermeiden Sie, dass Ihrem Google Cloud-Konto die in diesem Codelab verwendeten Ressourcen in Rechnung gestellt werden:
- Wechseln Sie in der Google Cloud Console zur Seite Ressourcen verwalten.
- Wählen Sie in der Projektliste das Projekt aus, das Sie löschen möchten, und klicken Sie auf Löschen.
- Geben Sie im Dialogfeld die Projekt-ID ein und klicken Sie auf Beenden, um das Projekt zu löschen.