১. 📖 ভূমিকা
পূর্ববর্তী কোডল্যাবে , আপনারা ADK-তে কীভাবে একটি মাল্টিমোডাল ডেটা ইন্টারঅ্যাকশন ডিজাইন করতে হয়, সে সম্পর্কে শিখেছেন। এখন আমরা MCP টুলসেট ব্যবহার করে MCP সার্ভারের সাথে কীভাবে একটি মাল্টিমোডাল ডেটা ইন্টারঅ্যাকশন ডিজাইন করা যায়, সে বিষয়ে আরও এক ধাপ এগিয়ে যাব। আমরা Veo MCP সার্ভার ব্যবহার করে Veo মডেলের সাহায্যে শর্ট ভিডিও তৈরি করার সক্ষমতা দিয়ে পূর্বে তৈরি করা প্রোডাক্ট ফটো এডিটর এজেন্টের কার্যকারিতা আরও প্রসারিত করব।
কোডল্যাবের মাধ্যমে, আপনি নিম্নলিখিত ধাপে ধাপে পদ্ধতিটি অনুসরণ করবেন:
- গুগল ক্লাউড প্রজেক্ট এবং বেস এজেন্ট ডিরেক্টরি প্রস্তুত করুন
- এমন একটি এমসিপি সার্ভার কনফিগার করুন যেটির ইনপুট হিসেবে ফাইল ডেটা প্রয়োজন।
- MCP সার্ভারের সাথে সংযোগ করার জন্য ADK এজেন্টকে প্রস্তুত করা
- MCP টুলসেটে ফাংশন কল অনুরোধ পরিবর্তন করার জন্য একটি প্রম্পট স্ট্র্যাটেজি এবং কলব্যাক ফাংশন ডিজাইন করুন।
- MCP টুলসেট থেকে প্রাপ্ত মাল্টিমোডাল ডেটা রেসপন্স হ্যান্ডেল করার জন্য একটি কলব্যাক ফাংশন ডিজাইন করুন।
স্থাপত্যের সংক্ষিপ্ত বিবরণ
এই কোডল্যাবের সামগ্রিক মিথস্ক্রিয়া নিম্নলিখিত ডায়াগ্রামে দেখানো হয়েছে।

পূর্বশর্ত
- পাইথন নিয়ে কাজ করতে স্বাচ্ছন্দ্যবোধ করি।
- (ঐচ্ছিক) এজেন্ট ডেভেলপমেন্ট কিট (ADK) সম্পর্কিত মৌলিক কোডল্যাব
- (ঐচ্ছিক) এডিকে মাল্টিমোডাল টুল পার্ট ১ কোডল্যাব : goo.gle/adk-multimodal-tool-1
আপনি যা শিখবেন
- প্রম্পট এবং ইমেজ স্টার্টার ব্যবহার করে Veo 3.1 দিয়ে কীভাবে ছোট ভিডিও তৈরি করবেন
- FastMCP ব্যবহার করে কীভাবে মাল্টিমোডাল এমসিপি সার্ভার তৈরি করবেন
- MCP টুলসেট ব্যবহার করার জন্য ADK কীভাবে সেটআপ করবেন
- টুল কলব্যাকের মাধ্যমে এমসিপি টুলসেটে টুল কল কীভাবে পরিবর্তন করবেন
- টুল কলব্যাকের মাধ্যমে এমসিপি টুলসেট থেকে টুলের প্রতিক্রিয়া কীভাবে পরিবর্তন করবেন
আপনার যা যা লাগবে
- ক্রোম ওয়েব ব্রাউজার
- একটি জিমেইল অ্যাকাউন্ট
- বিলিং অ্যাকাউন্ট সক্রিয় করা একটি ক্লাউড প্রজেক্ট
সকল স্তরের (শিক্ষানবিশ সহ) ডেভেলপারদের জন্য ডিজাইন করা এই কোডল্যাবটির নমুনা অ্যাপ্লিকেশনে পাইথন ব্যবহার করা হয়েছে। তবে, এখানে উপস্থাপিত ধারণাগুলো বোঝার জন্য পাইথন জ্ঞানের প্রয়োজন নেই।
২. 🚀 (ঐচ্ছিক) ওয়ার্কশপ ডেভেলপমেন্ট সেটআপ প্রস্তুত করা
ধাপ ১: ক্লাউড কনসোলে সক্রিয় প্রজেক্ট নির্বাচন করুন
গুগল ক্লাউড কনসোলের প্রজেক্ট সিলেক্টর পেজে, একটি গুগল ক্লাউড প্রজেক্ট নির্বাচন করুন বা তৈরি করুন (আপনার কনসোলের উপরের বাম অংশ দেখুন)।

এটিতে ক্লিক করলে, আপনি এই উদাহরণের মতো আপনার সমস্ত প্রকল্পের একটি তালিকা দেখতে পাবেন।

লাল বাক্স দ্বারা নির্দেশিত মানটি হলো প্রজেক্ট আইডি এবং এই মানটি পুরো টিউটোরিয়াল জুড়ে ব্যবহার করা হবে।
আপনার ক্লাউড প্রজেক্টের জন্য বিলিং চালু আছে কিনা তা নিশ্চিত করুন। এটি পরীক্ষা করতে, আপনার উপরের বাম দিকের বারে থাকা বার্গার আইকনে ☰ ক্লিক করুন, যেটি নেভিগেশন মেনু দেখাবে এবং বিলিং মেনুটি খুঁজুন।

আপনার ক্লাউড কনসোলের উপরের বাম দিকের অংশে থাকা 'বিলিং / ওভারভিউ ' শিরোনামের অধীনে যদি "গুগল ক্লাউড প্ল্যাটফর্ম ট্রায়াল বিলিং অ্যাকাউন্ট" দেখতে পান, তাহলে আপনার প্রজেক্টটি এই টিউটোরিয়ালের জন্য ব্যবহারের জন্য প্রস্তুত। অন্যথায়, এই টিউটোরিয়ালের শুরুতে ফিরে যান এবং ট্রায়াল বিলিং অ্যাকাউন্টটি রিডিম করুন।

ধাপ ২: ক্লাউড শেল-এর সাথে পরিচিত হন
টিউটোরিয়ালের বেশিরভাগ অংশেই আপনি ক্লাউড শেল ব্যবহার করবেন। গুগল ক্লাউড কনসোলের উপরে থাকা ‘Activate Cloud Shell’-এ ক্লিক করুন। যদি এটি আপনাকে অনুমোদন করতে বলে, তাহলে ‘Authorize’-এ ক্লিক করুন।


ক্লাউড শেলে সংযুক্ত হওয়ার পর, আমাদের যাচাই করে দেখতে হবে যে শেলটি (বা টার্মিনালটি) আমাদের অ্যাকাউন্ট দিয়ে আগে থেকেই প্রমাণীকৃত আছে কি না।
gcloud auth list
আপনার ব্যক্তিগত জিমেইল যদি নিচের উদাহরণের মতো আউটপুট দেখায়, তাহলে সবকিছু ঠিক আছে।
Credentialed Accounts
ACTIVE: *
ACCOUNT: alvinprayuda@gmail.com
To set the active account, run:
$ gcloud config set account `ACCOUNT`
অন্যথায়, আপনার ব্রাউজার রিফ্রেশ করার চেষ্টা করুন এবং অনুরোধ করা হলে ' Authorize'- এ ক্লিক করুন (সংযোগ সমস্যার কারণে এটি বাধাগ্রস্ত হতে পারে)।
এরপর, আমাদের এটাও যাচাই করতে হবে যে শেলটি আপনার সঠিক প্রজেক্ট আইডিতে আগে থেকেই কনফিগার করা আছে কিনা। যদি আপনি টার্মিনালে $ আইকনের আগে ( ) বন্ধনীর ভেতরে কোনো মান দেখতে পান (নিচের স্ক্রিনশটে, মানটি হলো "adk-multimodal-tool" ), তাহলে এই মানটি আপনার সক্রিয় শেল সেশনের জন্য কনফিগার করা প্রজেক্টটি নির্দেশ করে।

প্রদর্শিত মানটি যদি ইতিমধ্যেই সঠিক হয়, তাহলে আপনি পরবর্তী কমান্ডটি এড়িয়ে যেতে পারেন। তবে যদি এটি সঠিক না হয় বা অনুপস্থিত থাকে, তাহলে নিম্নলিখিত কমান্ডটি চালান।
gcloud config set project <YOUR_PROJECT_ID>
এরপর, গিটহাব থেকে এই কোডল্যাবের টেমপ্লেট ওয়ার্কিং ডিরেক্টরিটি ক্লোন করুন এবং নিচের কমান্ডটি চালান। এটি adk-multimodal-tool ডিরেক্টরিতে ওয়ার্কিং ডিরেক্টরিটি তৈরি করবে।
git clone https://github.com/alphinside/adk-mcp-multimodal.git adk-multimodal-tool
ধাপ ৩: ক্লাউড শেল এডিটর সম্পর্কে জানুন এবং অ্যাপ্লিকেশন ওয়ার্কিং ডিরেক্টরি সেটআপ করুন।
এখন, আমরা কোডিং করার জন্য আমাদের কোড এডিটর সেট আপ করতে পারি। এর জন্য আমরা ক্লাউড শেল এডিটর ব্যবহার করব।
ওপেন এডিটর বাটনে ক্লিক করুন, এটি একটি ক্লাউড শেল এডিটর খুলবে। 
এরপর, ক্লাউড শেল এডিটরের উপরের অংশে যান এবং File->Open Folder-এ ক্লিক করুন, আপনার ইউজারনেম ডিরেক্টরি এবং adk-multimodal-tool ডিরেক্টরিটি খুঁজুন, তারপর OK বোতামে ক্লিক করুন। এটি নির্বাচিত ডিরেক্টরিটিকে প্রধান ওয়ার্কিং ডিরেক্টরি হিসেবে সেট করবে। এই উদাহরণে, ইউজারনেম হলো alvinprayuda , তাই ডিরেক্টরি পাথটি নিচে দেখানো হলো।


এখন, আপনার ক্লাউড শেল এডিটর ওয়ার্কিং ডিরেক্টরিটি ( adk-multimodal-tool এর ভিতরে) দেখতে এইরকম হবে।

এখন, এডিটরের জন্য টার্মিনালটি খুলুন। আপনি মেনু বারে থাকা Terminal -> New Terminal- এ ক্লিক করে এটি করতে পারেন, অথবা Ctrl + Shift + C ব্যবহার করতে পারেন, এটি ব্রাউজারের নিচের অংশে একটি টার্মিনাল উইন্ডো খুলবে।

আপনার বর্তমান সক্রিয় টার্মিনালটি adk-multimodal-tool ওয়ার্কিং ডিরেক্টরির ভিতরে থাকা উচিত। আমরা এই কোডল্যাবে পাইথন ৩.১২ ব্যবহার করব এবং পাইথন ভার্সন ও ভার্চুয়াল এনভায়রনমেন্ট তৈরি ও পরিচালনার কাজ সহজ করার জন্য uv পাইথন প্রজেক্ট ম্যানেজার ব্যবহার করব। এই uv প্যাকেজটি ক্লাউড শেলে আগে থেকেই ইনস্টল করা আছে।
.venv ডিরেক্টরিতে ভার্চুয়াল এনভায়রনমেন্টের জন্য প্রয়োজনীয় ডিপেন্ডেন্সিগুলো ইনস্টল করতে এই কমান্ডটি চালান।
uv sync --frozen
এই টিউটোরিয়ালের জন্য ঘোষিত ডিপেন্ডেন্সিগুলো, যেগুলো হলো google-adk, and python-dotenv , তা দেখতে pyproject.toml ফাইলটি দেখুন।
এখন, নিচে দেখানো কমান্ডের মাধ্যমে আমাদের প্রয়োজনীয় এপিআইগুলো সক্রিয় করতে হবে। এতে কিছুটা সময় লাগতে পারে।
gcloud services enable aiplatform.googleapis.com
কমান্ডটি সফলভাবে কার্যকর হলে, আপনি নিচে দেখানো বার্তার মতো একটি বার্তা দেখতে পাবেন:
Operation "operations/..." finished successfully.
ক্লোন করা রিপোজিটরির part2_starter_agent ডিরেক্টরির ভিতরে টেমপ্লেট এজেন্ট কাঠামোটি আপনার জন্য ইতিমধ্যেই সরবরাহ করা আছে। এখন, এই টিউটোরিয়ালের জন্য প্রস্তুত হতে আমাদের প্রথমে এটির নাম পরিবর্তন করতে হবে।
mv part1_ckpt_agent product_photo_editor
এরপরে, product_photo_editor/.env.example ফাইলটি product_photo_editor/.env- এ কপি করুন।
cp product_photo_editor/.env.example product_photo_editor/.env
যখন আপনি product_photo_editor/.env ফাইলটি খুলবেন, তখন নিচে দেখানো ছবির মতো বিষয়বস্তু দেখতে পাবেন।
GOOGLE_GENAI_USE_VERTEXAI=1
GOOGLE_CLOUD_PROJECT=your-project-id
GOOGLE_CLOUD_LOCATION=global
এরপর, আপনাকে your-project-id ভ্যালুটি আপনার সঠিক প্রজেক্ট আইডি দিয়ে আপডেট করতে হবে। এখন আমরা পরবর্তী ধাপের জন্য প্রস্তুত।
৩. 🚀 Veo MCP সার্ভারটি চালু করুন
প্রথমে, এই কমান্ডটি ব্যবহার করে MCP সার্ভিস ডিরেক্টরিটি তৈরি করা যাক।
mkdir veo_mcp
এরপর, এই কমান্ডটি ব্যবহার করে veo_mcp/main.py ফাইলটি তৈরি করুন।
touch veo_mcp/main.py
এরপর 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()
নিম্নলিখিত কোডটি নিম্নলিখিত কাজগুলো করে:
- একটি FastMCP সার্ভার তৈরি করে যা ADK এজেন্টদের কাছে একটি Veo 3.1 ভিডিও জেনারেশন টুল উন্মুক্ত করে।
- ইনপুট হিসেবে বেস৬৪-এনকোডেড ছবি, টেক্সট প্রম্পট এবং নেতিবাচক প্রম্পট গ্রহণ করে।
- Veo 3.1 API-তে অনুরোধ জমা দিয়ে এবং সম্পূর্ণ না হওয়া পর্যন্ত প্রতি ৫ সেকেন্ড পর পর পোলিং করার মাধ্যমে অ্যাসিঙ্ক্রোনাসভাবে ৮-সেকেন্ডের ভিডিও তৈরি করে।
- সমৃদ্ধ প্রম্পটের সাথে বেস৬৪-এনকোডেড ভিডিও ডেটা ফেরত দেয়।
এই Veo MCP টুলটির জন্য আমাদের এজেন্টের মতো একই এনভায়রনমেন্ট ভেরিয়েবল প্রয়োজন হবে, তাই আমরা শুধু .env ফাইলটি কপি-পেস্ট করতে পারি। এটি করার জন্য নিম্নলিখিত কমান্ডটি চালান।
cp product_photo_editor/.env veo_mcp/
এখন, এই কমান্ডটি চালিয়ে আমরা পরীক্ষা করতে পারি যে এমসিপি সার্ভারটি সঠিকভাবে চলছে কিনা।
uv run veo_mcp/main.py
এবং এটি কনসোল লগটি এইরকম দেখাবে
╭────────────────────────────────────────────────────────────────────────────╮
│ │
│ _ __ ___ _____ __ __ _____________ ____ ____ │
│ _ __ ___ .'____/___ ______/ /_/ |/ / ____/ __ \ |___ \ / __ \ │
│ _ __ ___ / /_ / __ `/ ___/ __/ /|_/ / / / /_/ / ___/ / / / / / │
│ _ __ ___ / __/ / /_/ (__ ) /_/ / / / /___/ ____/ / __/_/ /_/ / │
│ _ __ ___ /_/ \____/____/\__/_/ /_/\____/_/ /_____(*)____/ │
│ │
│ │
│ 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'
এখন CTRL+C ব্যবহার করে MCP সার্ভিস প্রসেসটি বন্ধ করুন। এই কমান্ডটি পরবর্তীতে ADK MCP টুলসেট থেকে ব্যবহার করা হবে। আমাদের এজেন্টকে এই MCP টুলগুলো ব্যবহার করার অনুমতি দেওয়ার জন্য আমরা পরবর্তী ধাপে যেতে পারি।
৪. 🚀 Veo MCP সার্ভারকে ADK এজেন্টের সাথে সংযুক্ত করুন
এখন, Veo MCP সার্ভারটি সংযুক্ত করা যাক যাতে আমাদের এজেন্ট এটি ব্যবহার করতে পারে। প্রথমে, টুলসেটটি রাখার জন্য একটি আলাদা স্ক্রিপ্ট তৈরি করে নিম্নলিখিত কমান্ডটি চালান।
touch product_photo_editor/mcp_tools.py
এরপর, নিচের কোডটি 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,
# ),
# )
উপরের কোডটিতে দেখানো হয়েছে কিভাবে ADK MCPToolset ব্যবহার করে একটি MCP সার্ভারের সাথে সংযোগ স্থাপন করা যায়। এই উদাহরণে আমরা STDIO কমিউনিকেশন চ্যানেল ব্যবহার করে MCP সার্ভারের সাথে সংযোগ স্থাপন করেছি। কমান্ডটিতে আমরা উল্লেখ করেছি কিভাবে MCP সার্ভারটি চালানো যায় এবং টাইমআউট প্যারামিটারটি সেট করা হয়েছে।
৫. 🚀 টুল কল প্যারামিটার পরিবর্তন
MCP সার্ভার টুল ডিক্লারেশনে, আমরা generate_video_with_image নামের একটি টুল ডিজাইন করেছি, যা টুল প্যারামিটার হিসেবে base64 স্ট্রিং নির্দিষ্ট করে। আমরা LLM-কে এই কাজটি করতে বলতে পারি না, তাই এটি সামলানোর জন্য আমাদের একটি নির্দিষ্ট কৌশল তৈরি করতে হবে।
পূর্ববর্তী ল্যাবে, আমরা before_model_callback এ ব্যবহারকারী-আপলোড করা এবং টুলের প্রতিক্রিয়া চিত্রকে একটি আর্টিফ্যাক্ট হিসাবে সংরক্ষণ করার ব্যবস্থা করেছি, যা পূর্বে প্রস্তুত করা এজেন্ট টেমপ্লেটেও প্রতিফলিত হয়। আমরা এটিকে কাজে লাগাব এবং নিম্নলিখিত কৌশলগুলি অবলম্বন করব:
- যদি নির্দিষ্ট টুল প্যারামিটারের জন্য বেস৬৪ স্ট্রিং ডেটা পাঠানোর প্রয়োজন হয়, তবে LLM-কে সর্বদা artifact_id মানটি পাঠাতে নির্দেশ দিন।
-
before_tool_callbackএ টুল কল আহ্বানটি আটকান এবং আর্টিফ্যাক্টটি লোড করে প্যারামিটারটিকে artifact_id থেকে এর বাইট কন্টেন্টে রূপান্তর করুন ও টুলের আর্গুমেন্টগুলো ওভাররাইট করুন।
যে অংশটি আমরা আটকাব, তার দৃশ্যায়নের জন্য নিচের ছবিটি দেখুন।

প্রথমে, before_tool_callback ফাংশনটি প্রস্তুত করার জন্য, নিম্নলিখিত কমান্ডটি চালিয়ে product_photo_editor/tool_callbacks.py নামে একটি নতুন ফাইল তৈরি করুন।
touch product_photo_editor/tool_callbacks.py
তারপর, নিচের কোডটি ফাইলে কপি করুন।
# 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
উপরের কোডটিতে নিম্নলিখিত ধাপগুলো দেখানো হয়েছে:
- যাচাই করুন যে ব্যবহৃত টুলটি একটি McpTool অবজেক্ট কিনা এবং এটিই সেই নির্দিষ্ট টুল কল কিনা যা আমরা পরিবর্তন করতে চাই।
-
image_dataআর্গুমেন্টের মানটি নিন, যেটি base64 ফরম্যাটে অনুরোধ করা হয়েছে, কিন্তু আমরা LLM-কে এর উপর `artifact_id` ফেরত দিতে অনুরোধ করি। -
tool_contextএ আর্টিফ্যাক্ট সার্ভিস ব্যবহার করে আর্টিফ্যাক্টটি লোড করুন। -
image_dataআর্গুমেন্টগুলোকে base64 ডেটা দিয়ে ওভাররাইট করুন।
এখন, আমাদের এজেন্টে এই কলব্যাকটি যোগ করতে হবে এবং নির্দেশাবলীও সামান্য পরিবর্তন করতে হবে, যাতে এজেন্ট সর্বদা আর্টিফ্যাক্ট আইডি দিয়ে বেস৬৪ টুল আর্গুমেন্টগুলো পূরণ করে।
product_photo_editor/agent.py ফাইলটি খুলুন এবং নিচের কোড দিয়ে এর ভেতরের বিষয়বস্তু পরিবর্তন করুন।
# 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,
)
আচ্ছা, এবার এই পরিবর্তনটি পরীক্ষা করার জন্য এজেন্টের সাথে ইন্টারঅ্যাক্ট করার চেষ্টা করা যাক। ওয়েব ডেভ UI চালু করতে নিম্নলিখিত কমান্ডটি চালান।
uv run adk web --port 8080
এটি নিচের উদাহরণের মতো আউটপুট তৈরি করবে, যার মানে হলো আমরা ইতিমধ্যেই ওয়েব ইন্টারফেসটি অ্যাক্সেস করতে পারব।
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)
এখন, এটি পরীক্ষা করার জন্য আপনি URL-টির উপর Ctrl + Click করতে পারেন অথবা আপনার Cloud Shell Editor-এর উপরের অংশে থাকা Web Preview বাটনটিতে ক্লিক করে পোর্ট 8080-এ Preview নির্বাচন করতে পারেন।

আপনি নিম্নলিখিত ওয়েব পেজটি দেখতে পাবেন যেখানে আপনি উপরের বাম দিকের ড্রপ-ডাউন বোতাম থেকে উপলব্ধ এজেন্টদের নির্বাচন করতে পারবেন (আমাদের ক্ষেত্রে এটি product_photo_editor হওয়া উচিত) এবং বটটির সাথে ইন্টারঅ্যাক্ট করতে পারবেন।
এরপর, নিচের ছবিটি আপলোড করুন এবং এজেন্টকে তা থেকে প্রচারমূলক ক্লিপ তৈরি করতে বলুন।
Generate a slow zoom in and moving from left and right animation

আপনি নিম্নলিখিত ত্রুটির সম্মুখীন হবেন

কেন? কারণ টুলটি সরাসরি বেস৬৪ স্ট্রিং আকারেও ফলাফল ফেরত দিয়েছে, যা সর্বোচ্চ টোকেন সীমা অতিক্রম করবে। এখন, চলুন পরবর্তী অংশে এই ত্রুটিটি সমাধান করা যাক।
৬. 🚀 টুলের প্রতিক্রিয়া পরিবর্তন
এই অংশে, আমরা এমসিপি (MCP) রেসপন্স থেকে টুল রেসপন্সটি পরিচালনা করব। আমরা নিম্নলিখিত কাজগুলো করব:
- টুল দ্বারা প্রাপ্ত ভিডিও প্রতিক্রিয়াটি আর্টিফ্যাক্ট সার্ভিসে সংরক্ষণ করুন।
- এর পরিবর্তে এজেন্টের কাছে আর্টিফ্যাক্ট আইডেন্টিফায়ারটি ফেরত দিন।
স্মরণ করিয়ে দেওয়ার জন্য আমরা নিম্নলিখিত এজেন্ট রানটাইমটি ব্যবহার করব।

প্রথমে, কলব্যাক ফাংশনটি ইমপ্লিমেন্ট করা যাক। এর জন্য product_photo_editor/tool_callbacks.py ফাইলটি খুলুন এবং 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
এরপরে, আমাদের এজেন্টকে এই ফাংশনটি দিয়ে সজ্জিত করতে হবে। product_photo_editor/agent.py ফাইলটি খুলুন এবং এটিকে নিম্নলিখিত কোড দিয়ে পরিবর্তন করুন।
# 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,
)
কাজটি হয়ে গেছে, এখন আপনি এজেন্টকে শুধু ছবি সম্পাদনা করতেই নয়, আপনার জন্য ভিডিও তৈরি করতেও বলতে পারেন! নিচের কমান্ডটি আবার চালান।
uv run adk web --port 8080
তারপর, এই ছবিটি ব্যবহার করে ভিডিও তৈরি করার চেষ্টা করুন।
Generate a slow zoom in and moving from left and right animation

আপনি নীচে দেখানো উদাহরণের মতো তৈরি ভিডিওটি দেখতে পাবেন এবং এটি ইতিমধ্যেই আর্টিফ্যাক্ট হিসাবে সংরক্ষিত থাকবে।

৭. ⭐ সারাংশ
এখন এই কোডল্যাবে আমরা ইতিমধ্যে যা করেছি তা পুনরায় দেখে নেওয়া যাক, এখানে মূল শিক্ষাগুলো তুলে ধরা হলো:
- মাল্টিমোডাল ডেটা হ্যান্ডলিং (টুল আই/ও) : সরাসরি র ডেটা পাস করার পরিবর্তে, ADK-এর আর্টিফ্যাক্টস সার্ভিস এবং বিশেষায়িত কলব্যাক ব্যবহার করে টুলের ইনপুট ও আউটপুটের জন্য মাল্টিমোডাল ডেটা (যেমন ছবি এবং ভিডিও) পরিচালনার কৌশলকে আরও শক্তিশালী করা হয়েছে।
- এমসিপি টুলসেট ইন্টিগ্রেশন : এজেন্টে ভিডিও তৈরির সক্ষমতা যোগ করার জন্য এডিকে এমসিপি টুলসেটের মাধ্যমে ফাস্টএমসিপি ব্যবহার করে একটি বাহ্যিক ভিও এমসিপি সার্ভার তৈরি ও ইন্টিগ্রেট করা হয়েছে।
- টুল ইনপুট পরিবর্তন (before_tool_callback) : generate_video_with_image টুল কলটিকে বাধা দেওয়ার জন্য একটি কলব্যাক প্রয়োগ করা হয়েছে, যা LLM দ্বারা নির্বাচিত ফাইলের artifact_id-কে MCP সার্ভারের ইনপুটের জন্য প্রয়োজনীয় base64-এনকোডেড ইমেজ ডেটাতে রূপান্তরিত করে।
- টুল আউটপুট পরিবর্তন (after_tool_callback) : MCP সার্ভার থেকে আসা বড় আকারের base64-এনকোডেড ভিডিও রেসপন্সটি ইন্টারসেপ্ট করতে, ভিডিওটিকে একটি নতুন আর্টিফ্যাক্ট হিসেবে সংরক্ষণ করতে এবং LLM-এ একটি পরিষ্কার video_artifact_id রেফারেন্স ফেরত পাঠাতে একটি কলব্যাক ইমপ্লিমেন্ট করা হয়েছে।
৮. 🧹 পরিষ্কার করা
এই কোডল্যাবে ব্যবহৃত রিসোর্সগুলির জন্য আপনার গুগল ক্লাউড অ্যাকাউন্টে চার্জ হওয়া এড়াতে, এই ধাপগুলি অনুসরণ করুন:
- গুগল ক্লাউড কনসোলে, 'ম্যানেজ রিসোর্সেস' পৃষ্ঠায় যান।
- প্রজেক্ট তালিকা থেকে, আপনি যে প্রজেক্টটি মুছতে চান সেটি নির্বাচন করুন এবং তারপর ডিলিট বোতামে ক্লিক করুন।
- ডায়ালগ বক্সে প্রজেক্ট আইডি টাইপ করুন এবং তারপর প্রজেক্টটি মুছে ফেলার জন্য 'শাট ডাউন'-এ ক্লিক করুন।