Çok Formatlı Araç Etkileşimi ile ADK : Bölüm 2 ( Araç Geri Çağırmaları ile MCP Araç Seti)

1. 📖 Giriş

Önceki codelab'de ADK'da çok formatlı veri etkileşimi tasarlama hakkında bilgi edindiniz. Şimdi MCP araç setini kullanarak MCP sunucusuyla çok formatlı veri etkileşimi tasarlama konusunda bir adım daha ileri gideceğiz. Veo MCP sunucusunu kullanarak Veo modeliyle kısa videolar oluşturma özelliklerini ekleyerek daha önce geliştirilen ürün fotoğrafı düzenleyici aracının özelliklerini genişleteceğiz.

Bu codelab'de aşağıdaki gibi adım adım bir yaklaşım kullanacaksınız:

  1. Google Cloud projesini ve temel aracı dizinini hazırlama
  2. Dosya verilerinin giriş olarak kullanılmasını gerektiren bir MCP sunucusu yapılandırma
  3. ADK aracını MCP sunucusuna bağlanacak şekilde yapılandırma
  4. İşlev çağrısı isteğini MCP araç setinde değiştirmek için bir istem stratejisi ve geri çağırma işlevi tasarlama
  5. MCP Araç Seti'nden gelen çok formatlı veri yanıtını işlemek için bir geri çağırma işlevi tasarlama

Mimariye Genel Bakış

Bu codelab'deki genel etkileşim aşağıdaki şemada gösterilmektedir.

93fe3107e0946ddd.jpeg

Ön koşullar

  • Python ile rahatça çalışabilme
  • (İsteğe bağlı) Agent Development Kit (ADK) ile ilgili temel codelab'ler
  1. goo.gle/adk-foundation
  2. goo.gle/adk-using-tools

Neler öğreneceksiniz?

  • İstem ve resim başlangıcı ile Veo 3.1 kullanarak kısa video oluşturma
  • FastMCP kullanarak çok formatlı MCP sunucusu geliştirme
  • MCP Araç Seti'ni kullanmak için ADK'yı ayarlama
  • Araç geri çağırma yoluyla araç çağrısını MCP araç setinde değiştirme
  • Araç geri araması aracılığıyla MCP Araç Seti'nden gelen araç yanıtını değiştirme

Gerekenler

  • Chrome web tarayıcısı
  • Gmail hesabı
  • Faturalandırma hesabı etkinleştirilmiş bir Cloud projesi

Her seviyeden geliştirici (yeni başlayanlar dahil) için tasarlanan bu codelab'de örnek uygulamada Python kullanılmaktadır. Ancak sunulan kavramları anlamak için Python bilgisi gerekmez.

2. 🚀 ( İsteğe bağlı) Atölye Geliştirme Kurulumunu Hazırlama

1. adım: Cloud Console'da Etkin Proje'yi seçin

Google Cloud Console'daki proje seçici sayfasında bir Google Cloud projesi seçin veya oluşturun (konsolunuzun sol üst bölümüne bakın).

6069be756af6452b.png

Bu seçeneği tıkladığınızda, örnekteki gibi tüm projelerinizin listesini görürsünüz.

dd8fcf0428ab868f.png

Kırmızı kutuyla belirtilen değer PROJE KİMLİĞİ'dir ve bu değer, eğitim boyunca kullanılacaktır.

Cloud projeniz için faturalandırmanın etkinleştirildiğinden emin olun. Bunu kontrol etmek için sol üst çubuğunuzdaki hamburger simgesini ☰ tıklayarak gezinme menüsünü gösterin ve Faturalandırma menüsünü bulun.

db07810b26fc61d6.png

"Google Cloud Platform Deneme Faturalandırma Hesabı" ifadesini Faturalandırma / Genel Bakış başlığı altında ( Cloud Console'unuzun sol üst bölümü) görüyorsanız projeniz bu eğitimde kullanılmaya hazırdır. Aksi takdirde, bu eğitimin başına dönün ve deneme faturalandırma hesabını kullanın.

45539d4ac57dd995.png

2. adım: Cloud Shell'i tanıyın

Eğitimlerin büyük bir bölümünde Cloud Shell'i kullanacaksınız. Google Cloud Console'un üst kısmındaki Cloud Shell'i Etkinleştir'i tıklayın. Yetkilendirmeniz istenirse Yetkilendir'i tıklayın.

26f20e837ff06119.png

79b06cc89a99f840.png

Cloud Shell'e bağlandıktan sonra, kabuğun ( veya terminalin) hesabımızla kimliğinin doğrulanıp doğrulanmadığını kontrol etmemiz gerekir.

gcloud auth list

Aşağıdaki örnek çıktıda olduğu gibi kişisel Gmail'inizi görüyorsanız her şey yolundadır.

Credentialed Accounts

ACTIVE: *
ACCOUNT: alvinprayuda@gmail.com

To set the active account, run:
    $ gcloud config set account `ACCOUNT`

Aksi takdirde, tarayıcınızı yenilemeyi deneyin ve istendiğinde Yetkilendir'i tıkladığınızdan emin olun ( bağlantı sorunu nedeniyle kesintiye uğrayabilir).

Ardından, kabuğun doğru PROJE KİMLİĞİ ile yapılandırılıp yapılandırılmadığını da kontrol etmemiz gerekir. Terminalde $simgesinden önce ( ) içinde değer görüyorsanız ( aşağıdaki ekran görüntüsünde değer "adk-multimodal-tool") bu değer, etkin kabuk oturumunuz için yapılandırılmış projeyi gösterir.

10a99ff80839b635.png

Gösterilen değer zaten doğruysa sonraki komutu atlayabilirsiniz. Ancak doğru değilse veya eksikse aşağıdaki komutu çalıştırın.

gcloud config set project <YOUR_PROJECT_ID>

Ardından, bu codelab için şablon çalışma dizinini GitHub'dan klonlayın ve aşağıdaki komutu çalıştırın. Çalışma dizini adk-multimodal-tool dizininde oluşturulur.

git clone https://github.com/alphinside/adk-mcp-multimodal.git adk-multimodal-tool

3. adım: Cloud Shell Editor'a alışın ve uygulama çalışma dizinini ayarlayın

Şimdi kod düzenleyicimizi bazı kodlama işlemleri yapacak şekilde ayarlayabiliriz. Bu işlem için Cloud Shell Düzenleyici'yi kullanacağız.

Open Editor (Düzenleyiciyi Aç) düğmesini tıklayın. Bu işlem, Cloud Shell Düzenleyici'yi açar. 168eacea651b086c.png

Ardından, Cloud Shell Düzenleyici'nin üst bölümüne gidip File->Open Folder'ı (Dosya->Klasör Aç) tıklayın,username (kullanıcı adı) dizininizi ve adk-multimodal-tool dizinini bulup Tamam düğmesini tıklayın. Bu işlem, seçilen dizini ana çalışma dizini yapar. Bu örnekte kullanıcı adı alvinprayuda olduğundan dizin yolu aşağıda gösterilmiştir.

8eb3f593141dbcbf.png

a4860f6be228d864.png

Cloud Shell Düzenleyici çalışma dizininiz artık şu şekilde görünmelidir ( adk-multimodal-tool içinde):

aa2edaf29303167f.png

Şimdi düzenleyicinin terminalini açın. Menü çubuğunda Terminal -> New Terminal'ı tıklayarak veya Ctrl + Üst Karakter + C kısayolunu kullanarak yapabilirsiniz. Bu kısayol, tarayıcının alt kısmında bir terminal penceresi açar.

74d314f6ff34965b.png

Mevcut etkin terminaliniz, adk-multimodal-tool çalışma dizininde olmalıdır. Bu codelab'de Python 3.12'yi kullanacağız. Python sürümü ve sanal ortam oluşturma ve yönetme ihtiyacını basitleştirmek için uv python proje yöneticisini kullanacağız. Bu uv paketi, Cloud Shell'e önceden yüklenmiştir.

.venv dizinindeki sanal ortama gerekli bağımlılıkları yüklemek için bu komutu çalıştırın.

uv sync --frozen

Bu eğitim için bildirilen bağımlılıkları (google-adk, and python-dotenv) görmek üzere pyproject.toml dosyasını kontrol edin.

Şimdi de aşağıdaki komutu kullanarak gerekli API'leri etkinleştirmemiz gerekiyor. Bu işlem biraz zaman alabilir.

gcloud services enable aiplatform.googleapis.com

Komut başarıyla yürütüldüğünde aşağıda gösterilene benzer bir mesaj görürsünüz:

Operation "operations/..." finished successfully.

Şablon aracı yapısı, klonlanan depodaki part2_starter_agent dizininde sizin için sağlanmıştır. Şimdi, bu eğitime hazırlanmak için önce yeniden adlandırmamız gerekiyor.

mv part1_ckpt_agent product_photo_editor

Ardından, product_photo_editor/.env.example dosyasını product_photo_editor/.env dosyasına kopyalayın.

cp product_photo_editor/.env.example product_photo_editor/.env

product_photo_editor/.env dosyasını açtığınızda aşağıdaki gibi bir içerik görürsünüz.

GOOGLE_GENAI_USE_VERTEXAI=1
GOOGLE_CLOUD_PROJECT=your-project-id
GOOGLE_CLOUD_LOCATION=global

Ardından, your-project-id değerini kendi proje kimliğinizle güncellemeniz gerekir. Şimdi bir sonraki adıma geçmeye hazırız.

3. 🚀 Veo MCP sunucusunu başlatma

Öncelikle bu komutu kullanarak MCP hizmet dizinini oluşturalım.

mkdir veo_mcp

Ardından, bu komutu kullanarak veo_mcp/main.py dosyasını oluşturun.

touch veo_mcp/main.py

Ardından, aşağıdaki kodu veo_mcp/main.py dosyasına kopyalayın.

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()

Aşağıdaki kod şu işlemleri yapar:

  1. ADK aracılarına Veo 3.1 video üretme aracını sunan bir FastMCP sunucusu oluşturur.
  2. Giriş olarak base64 kodlu resimleri, metin istemlerini ve negatif istemleri kabul eder.
  3. Veo 3.1 API'ye istek göndererek ve tamamlanana kadar her 5 saniyede bir yoklama yaparak 8 saniyelik videoları eşzamansız olarak oluşturur.
  4. Zenginleştirilmiş istemle birlikte Base64 kodlu video verilerini döndürür.

Bu Veo MCP aracı, aracımızla aynı ortam değişkenini gerektirecektir. Bu nedenle, .env dosyasını kopyalayıp yapıştırabiliriz. Bunu yapmak için aşağıdaki komutu çalıştırın:

cp product_photo_editor/.env veo_mcp/

Şimdi bu komutu çalıştırarak MCP sunucusunun doğru şekilde çalışıp çalışmadığını test edebiliriz.

uv run veo_mcp/main.py

Konsol günlüğü şu şekilde gösterilir:

╭────────────────────────────────────────────────────────────────────────────╮
│                                                                            │
│        _ __ ___  _____           __  __  _____________    ____    ____     │
│       _ __ ___ .'____/___ ______/ /_/  |/  / ____/ __ \  |___ \  / __ \    │
│      _ __ ___ / /_  / __ `/ ___/ __/ /|_/ / /   / /_/ /  ___/ / / / / /    │
│     _ __ ___ / __/ / /_/ (__  ) /_/ /  / / /___/ ____/  /  __/_/ /_/ /     │
│    _ __ ___ /_/    \____/____/\__/_/  /_/\____/_/      /_____(*)____/      │
│                                                                            │
│                                                                            │
│                                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'

Şimdi CTRL+C tuşlarını kullanarak MCP hizmeti işlemini sonlandırın. Bu komut daha sonra ADK MCP Toolset'ten çağrılacaktır. Temsilcimizin bu MCP araçlarını kullanmasına izin vermek için bir sonraki adıma geçebiliriz.

4. 🚀 Veo MCP sunucusunu ADK aracısına bağlayın

Şimdi, temsilcimiz tarafından kullanılabilmesi için Veo MCP sunucusunu bağlayalım. Öncelikle, araç setini içerecek farklı bir komut dosyası oluşturalım ve aşağıdaki komutu çalıştıralım.

touch product_photo_editor/mcp_tools.py

Ardından, aşağıdaki kodu product_photo_editor/mcp_tools.py dosyasına kopyalayın.

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,
#     ),
# )

Yukarıdaki kod, ADK MCPToolset'i kullanarak bir MCP sunucusuna nasıl bağlanabileceğimizi gösterir. Bu örnekte, STDIO iletişim kanalını kullanarak MCP sunucusuna bağlanıyoruz. Komutta, MCP sunucusunu nasıl çalıştırabileceğimizi ve zaman aşımı parametresini nasıl ayarlayabileceğimizi belirtiyoruz.

5. 🚀 Tool Call Parameter Modification (Araç Çağrısı Parametre Değişikliği)

MCP sunucusu aracı bildiriminde, araç parametreleri olarak base64 dizesini belirten generate_video_with_image aracını tasarladık. Büyük dil modelinden bunu yapmasını isteyemeyiz. Bu nedenle, bu durumu ele almak için özel bir strateji tasarlamamız gerekir.

Önceki laboratuvarda, kullanıcı tarafından yüklenen ve araç yanıtı olarak verilen resmi, before_model_callback içinde işleyerek yapay nesne olarak kaydedilmesini sağlıyoruz. Bu işlem, daha önce hazırlanmış olan aracı şablonuna da yansıtılıyor. Bu bilgileri kullanarak aşağıdaki stratejileri uygulayacağız:

  1. Belirli bir araç parametresi, base64 dize verilerinin gönderilmesini gerektiriyorsa LLM'ye her zaman artifact_id değerini göndermesini söyleyin.
  2. before_tool_callback içinde araç çağrısı başlatmayı yakalayın ve yapıyı yükleyerek parametreyi artifact_id'den bayt içeriğine dönüştürün ve araç bağımsız değişkenlerinin üzerine yazın.

Kesintiye uğratacağımız bölümün görselleştirilmesi için aşağıdaki resme bakın.

2d6142cf5d96830e.png

Öncelikle before_tool_callback işlevini hazırlayalım. Aşağıdaki komutu çalıştırarak product_photo_editor/tool_callbacks.py adlı yeni bir dosya oluşturun.

touch product_photo_editor/tool_callbacks.py

Ardından, aşağıdaki kodu dosyaya kopyalayın.

# 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

Yukarıdaki kodda aşağıdaki adımlar gösterilmektedir:

  1. Çağrılan aracın bir McpTool nesnesi olup olmadığını ve değiştirmek istediğimiz hedef araç çağrısı olup olmadığını kontrol edin.
  2. Base64 biçiminde istenen ancak LLM'den artifact_id döndürmesi istenen bağımsız değişken olan image_data bağımsız değişkenlerinin değerini alın.
  3. tool_context üzerindeki yapı hizmetini kullanarak yapıyı yükleyin.
  4. image_data bağımsız değişkenlerinin üzerine base64 verilerini yazın.

Şimdi bu geri çağırmayı aracıya eklememiz ve talimatları biraz değiştirerek aracının her zaman base64 araç bağımsız değişkenlerini yapay nesne kimliğiyle doldurmasını sağlamamız gerekiyor.

product_photo_editor/agent.py dosyasını açın ve içeriği aşağıdaki kodla değiştirin.

# 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,
)

Şimdi bu değişikliği test etmek için temsilciyle etkileşime geçmeyi deneyelim. Web geliştirme kullanıcı arayüzünü çalıştırmak için aşağıdaki komutu çalıştırın.

uv run adk web --port 8080

Aşağıdaki örneğe benzer bir çıktı oluşturulur. Bu, web arayüzüne erişebileceğimiz anlamına gelir.

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)

Şimdi bunu kontrol etmek için URL'yi Ctrl + tıklayabilir veya Cloud Shell Düzenleyicinizin üst kısmındaki Web Önizlemesi düğmesini tıklayıp 8080 bağlantı noktasında önizle'yi seçebilirsiniz.

edc73e971b9fc60c.png

Aşağıdaki web sayfasında, sol üstteki açılır düğmeden ( bizim durumumuzda product_photo_editor olmalıdır) kullanılabilir aracıları seçip botla etkileşim kurabilirsiniz.

Ardından aşağıdaki resmi yükleyin ve temsilciden bu resimden tanıtım amaçlı bir klip oluşturmasını isteyin.

Generate a slow zoom in and moving from left and right animation

fede23931847cb7e.png

Aşağıdaki hatayla karşılaşırsınız:

6728902ed0b7cc55.png

Neden? Çünkü araç, sonuçları doğrudan base64 dizesi biçiminde de döndürdüğü için maksimum jeton sayısı aşılacak. Şimdi bu hatayı bir sonraki bölümde ele alalım.

6. 🚀 Araç Yanıtını Değiştirme

Bu bölümde, MCP yanıtından gelen araç yanıtını ele alacağız. Şunları yapacağız:

  1. Aracın video yanıtını yapay nesne hizmetinde saklama
  2. Bunun yerine yapay ürün tanımlayıcısını aracıya döndürün.

Aşağıdaki aracı çalışma zamanında dokunacağımızı hatırlatırız.

2d6142cf5d96830e.png

Öncelikle geri çağırma işlevini uygulayalım. product_photo_editor/tool_callbacks.py dosyasını açın ve after_tool_modifier

# 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

Ardından, aracımızı bu işlevle donatmamız gerekir. product_photo_editor/agent.py dosyasını açın ve aşağıdaki kodla değiştirin.

# 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,
)

İşlem tamamlandı. Artık aracıdan yalnızca fotoğrafı düzenlemenize yardımcı olmasını değil, aynı zamanda sizin için video oluşturmasını da isteyebilirsiniz. Aşağıdaki komutu tekrar çalıştırın.

uv run adk web --port 8080

Ardından, bu resmi kullanarak video oluşturmayı deneyin.

Generate a slow zoom in and moving from left and right animation

fede23931847cb7e.png

Aşağıdaki örnekte gösterildiği gibi oluşturulan ve yapıt olarak kaydedilen videoyu görürsünüz.

29150fa84f85d2fd.png

7. ⭐ Özet

Şimdi bu codelab'de yaptığımız işlemleri tekrar gözden geçirelim. Temel bilgi şu:

  1. Çok Formatlı Veri İşleme (Araç G/Ç): ADK'nın Artifacts hizmetini ve özel geri çağırma işlevlerini kullanarak, ham bayt verilerini doğrudan iletmek yerine araç girişi ve çıkışı için çok formatlı verileri (ör. resimler ve videolar) yönetme stratejisi güçlendirildi.
  2. MCP Araç Seti Entegrasyonu: ADK MCP Araç Seti aracılığıyla FastMCP kullanarak harici bir Veo MCP sunucusu geliştirip entegre ederek aracıya video oluşturma özellikleri ekledi.
  3. Araç Girişini Değiştirme (before_tool_callback): generate_video_with_image araç çağrısını yakalamak için bir geri çağırma işlevi uygulandı. Bu işlev, dosyanın artifact_id'sini (LLM tarafından seçilir) MCP sunucusunun girişi için gerekli base64 kodlu görüntü verilerine dönüştürür.
  4. Araç Çıktısı Değişikliği (after_tool_callback): MCP sunucusundan gelen büyük Base64 kodlu video yanıtını yakalamak, videoyu yeni bir yapıt olarak kaydetmek ve LLM'ye temiz bir video_artifact_id referansı döndürmek için bir geri çağırma işlevi uygulandı.

8. 🧹 Temizleme

Bu codelab'de kullanılan kaynaklar için Google Cloud hesabınızın ücretlendirilmesini istemiyorsanız şu adımları uygulayın:

  1. Google Cloud Console'da Kaynakları yönetin sayfasına gidin.
  2. Proje listesinde silmek istediğiniz projeyi seçin ve Sil'i tıklayın.
  3. İletişim kutusunda proje kimliğini yazın ve projeyi silmek için Kapat'ı tıklayın.