ইম্পারেটিভ API, জাভাস্ক্রিপ্ট টুল প্রোগ্র্যামাটিক উপায়ে ডিফাইন করতে document.modelContext.registerTool() ব্যবহার করে। এটি সিঙ্গেল পেজ অ্যাপ্লিকেশনের (SPA) জন্য আদর্শ যেখানে বর্তমান রুট বা ব্যবহারকারীর অবস্থার উপর ভিত্তি করে টুল যোগ বা সরাতে হবে।
WebMCP একটি প্রোডিউসার/কনজিউমার আর্কিটেকচারে কাজ করে:
- ওয়েব পৃষ্ঠা হল টুল প্রোডিউসার: আপনি
document.modelContext.registerTool()ব্যবহার করে টুল সংজ্ঞায়িত ও রেজিস্টার করেন। কোনও ওয়েবপেজে শুধু এইটুকুই প্রয়োগ করতে হয়। এজেন্টদের টুল দেখানোর জন্য আপনাকে পৃষ্ঠায়getTools()বাexecuteTool()কল করতে হবে না। - ব্রাউজার ও এক্সটেনশন এজেন্ট হল প্রাথমিক কনজিউমার: ব্রাউজার দ্বারা বা তার মাধ্যমে প্রদান করা এজেন্ট — যার মধ্যে ব্রাউজারের বিল্ট-ইন এজেন্ট, ব্রাউজার এক্সটেনশন, DevTools ও সিস্টেম-লেভেল অ্যাসিস্ট্যান্ট অন্তর্ভুক্ত — ইন্টার্নাল প্ল্যাটফর্ম মেকানিজমের মাধ্যমে আউট-অফ-ব্যান্ড রেজিস্টার করা টুল খুঁজে বের করে ও কল করে।
- ইন-পেজ এজেন্ট ও টেস্ট হারনেস:
getTools()ওexecuteTool()বিশেষভাবে ইন-পেজ জাভাস্ক্রিপ্ট অ্যাসিস্ট্যান্ট (যেমন, এম্বেড করা চ্যাট উইজেট বা<iframe>) এবং অটোমেটেড টেস্ট স্যুটের জন্য আছে যেগুলিকে পৃষ্ঠার প্রসঙ্গে সরাসরি টুল খুঁজে বের করতে ও চালু করতে হয়।
রেজিস্ট্রেশন ও লাইফসাইকেল
টুল ডেফিনিশন অবজেক্ট এবং ঐচ্ছিক বিকল্প অবজেক্ট (ModelContextRegisterToolOptions) পাস করার মাধ্যমে টুল রেজিস্টার করা হয়, যা দুটি ঐচ্ছিক মেম্বারকে সাপোর্ট করে:
signal: টুলটি আর প্রয়োজন না হলে সেটির রেজিস্ট্রেশন বাতিল করতে একটিAbortSignalব্যবহার করা হয়।exposedTo: অরিজিন স্ট্রিংয়ের একটি অ্যারে যা নিয়ন্ত্রণ করে যে ডকুমেন্ট ট্রির কোন কোন ডকুমেন্টকে ফ্রেমের সীমানা জুড়ে টুলটি খুঁজে বের করার এবং চালানোর অনুমতি দেওয়া হয়েছে।
AbortController-এর সাথে লাইফসাইকেল ম্যানেজ করা
WebMCP-তে unregisterTool() পদ্ধতি নেই। কোনও টুল আনরেজিস্টার করতে, আপনাকে অবশ্যই রেজিস্ট্রেশনের সময় একটি AbortSignal পাস করতে হবে এবং টুলের আর প্রয়োজন না হলে সেই সিগন্যালটি বাতিল করতে হবে।
const controller = new AbortController();
await document.modelContext.registerTool({
name: "get_user_preferences",
description: "Retrieves the user's saved preferences.",
inputSchema: { type: "object", properties: {} },
execute() {
const prefs = localStorage.getItem("user_prefs");
return prefs ? JSON.parse(prefs) : { theme: "light" };
},
annotations: { readOnlyHint: true }
}, { signal: controller.signal });
// To unregister the tool (e.g., on component unmount):
controller.abort();
রেজিস্ট্রেশন সিগন্যাল বাতিল করলে শুধু টুলটি আনরেজিস্টার হয় — এটি আগে থেকে চলা এক্সিকিউশন বাতিল করে না। যেসব টুল দীর্ঘ সময় ধরে চলা কাজ শুরু করে, সেগুলিকে নিচে বর্ণিত প্রতি-এক্সিকিউশন সিগন্যাল মেনে চলতে হবে, অন্যথায় আনরেজিস্টার করার ফলে অনাথ অনুরোধ এবং পুরনো UI আপডেট থেকে যাবে।
exposedTo-এর মাধ্যমে ক্রস-অরিজিন টুল এক্সপোজার নিয়ন্ত্রণ করা
ডিফল্ট হিসেবে, রেজিস্টার করা টুলটি রেজিস্টার করা ডকুমেন্ট এবং একই সোর্স ফ্রেমের জন্য ব্যক্তিগত। আপনার অ্যাপ্লিকেশন কোনও <iframe>-এ এম্বেড করা থাকলে (অথবা থার্ড-পার্টি উইজেট এম্বেড করলে) এবং টুলটি খুঁজে পেতে ও চালু করতে আপনার পূর্বপুরুষ বা ভাইবোন ফ্রেমের প্রয়োজন হলে, exposedTo ব্যবহার করে অনুমোদিত অরিজিন নির্দিষ্ট করুন।
const controller = new AbortController();
await document.modelContext.registerTool({
name: "get_cart_items",
description: "Retrieves items currently in the user's shopping cart.",
inputSchema: { type: "object", properties: {} },
async execute(input, { signal }) {
return await cartService.getItems({ signal });
},
annotations: { readOnlyHint: true },
}, {
signal: controller.signal,
exposedTo: ["https://checkout.example.com"],
});
- মিউচুয়াল অপ্ট-ইন হ্যান্ডশেক: ক্রস-অরিজিন টুল ডিসকভারি হল টু-ওয়ে অপ্ট-ইন। টুল প্রোভাইডার ফ্রেম
exposedTo-এর মাধ্যমে কনজিউমার অরিজিনকে অনুমোদন করে এবং কনজিউমার ফ্রেমকে অবশ্যইgetTools({ fromOrigins: [...] })-এর মাধ্যমে সেই প্রোভাইডার অরিজিনের জন্য স্পষ্টভাবে অনুরোধ করতে হবে।fromOriginsছাড়া,getTools()শুধুমাত্র একই-অরিজিন ডকুমেন্টে কোয়েরি করে। - অরিজিন ম্যাচিং: রেজিস্টার করা ডকুমেন্টের নিজস্ব অরিজিনের কাছে সবসময় অ্যাক্সেস থাকে।
exposedTo-এ উল্লেখ করা অরিজিনকেdocument.modelContext.getTools({ fromOrigins: [...] })-এর মাধ্যমে টুল খুঁজে পাওয়ার এবংdocument.modelContext.executeTool()-এর মাধ্যমে তা এক্সিকিউট করার অনুমতি দেওয়া হয়েছে। - নিরাপত্তা সংক্রান্ত প্রয়োজনীয়তা:
exposedTo-এর প্রতিটি অরিজিনকে অবশ্যই সম্ভাব্য বিশ্বস্ত (HTTPS বা লোকালহোস্ট) হতে হবে। ভুল বা অসুরক্ষিত অরিজিন পাস করলেregisterTool(),SecurityError-এর মাধ্যমে বাতিল করে দেয়। - স্কোপ:
exposedToডকুমেন্ট ট্রির ফ্রেম জুড়ে ইন-পেজ ক্রস-ডকুমেন্ট ডিসকভারি নিয়ন্ত্রণ করে।
প্যারামিটার নির্ধারণ করা হচ্ছে
inputSchema প্রপার্টি ব্যবহার করে প্যারামিটার (params) সংজ্ঞায়িত করা হয়। এটি অবশ্যই একটি JSON স্কিমা অবজেক্ট হতে হবে যা টুলটি প্রত্যাশা করে এমন স্ট্রাকচার্ড ডেটা বর্ণনা করে।
await document.modelContext.registerTool({
name: "calculate_area",
description: "Calculates the area of a rectangle.",
inputSchema: {
type: "object",
properties: {
width: { type: "number", description: "The width of the rectangle." },
height: { type: "number", description: "The height of the rectangle." }
},
required: ["width", "height"]
},
execute(input) {
// input is { width: 10, height: 20 }
return input.width * input.height;
},
annotations: { readOnlyHint: true }
});
রাইটিং টুল ও প্যারামিটারের বিবরণ
এজেন্ট আগে থেকেই সম্পূর্ণ inputSchema পায়, তাই description-কে শুধু বলতে হবে যে টুলটি কী করে এবং কখন এটি ব্যবহার করতে হবে। এতে প্যারামিটারের নাম, ধরন, enum ভ্যালু, ডিফল্ট বা সীমা রিপিট করবেন না; পরিবর্তে, স্কিমায় (enum, default, minimum/maximum) সেগুলি ঘোষণা করুন। প্যারামিটারের বিবরণ একই নিয়ম অনুসরণ করে: ভ্যালুর অর্থ কী তা বলুন, এর ধরন বা অনুমোদিত ভ্যালু নয়।
ব্রাউজার inputSchema-এর সাথে আর্গুমেন্ট যাচাই করে না বা default ভ্যালু প্রয়োগ করে না, তাই execute-এ দুটিই করুন।
const SORT_ORDERS = ["newest", "price_low_to_high"];
await document.modelContext.registerTool({
name: "search_products",
// Don't list the sort orders here, even via SORT_ORDERS: `enum` already does.
description: "Searches the product catalog by keyword. Use when the user wants to find or compare products.",
inputSchema: {
type: "object",
properties: {
query: { type: "string", description: "Words to search for." },
sort: { type: "string", enum: SORT_ORDERS, default: "newest", description: "Order of the results." },
},
required: ["query"],
},
async execute({ query, sort = "newest" }, { signal }) {
if (typeof query !== "string" || !SORT_ORDERS.includes(sort)) {
return { error: "Pass a search query and a supported sort order.", sortOrders: SORT_ORDERS };
}
return await productService.search({ query, sort }, { signal });
},
annotations: { readOnlyHint: true },
});
এক্সিকিউশন প্যাটার্ন
execute কলব্যাক সবসময় দুটি আর্গুমেন্ট পায়: ইনপুট অবজেক্ট এবং AbortSignal — execute(inputObject, { signal }) সহ বিকল্প অবজেক্ট।
async execute কখন ব্যবহার করবেন
টুলটি এমন অপারেশন করে যা একটি Promise রিটার্ন করে বা সম্পূর্ণ হতে সময় নেয়, তখন async ব্যবহার করুন:
- নেটওয়ার্ক কল: API থেকে ডেটা ফেচ করা।
- অ্যাসিঙ্ক্রোনাস স্টোরেজ: IndexedDB অ্যাক্সেস করা হচ্ছে।
- এক্সটার্নাল ইভেন্ট: নির্দিষ্ট কোনও স্টেট পরিবর্তন বা অ্যানিমেশন শেষ হওয়ার জন্য অপেক্ষা করা।
async execute(input, { signal }) {
const response = await fetch(`/api/data/${input.id}`, { signal });
return await response.json();
}
execute (সিনক্রোনাস) কখন ব্যবহার করবেন
অবিলম্বে অপারেশনের জন্য স্ট্যান্ডার্ড সিঙ্ক্রোনাস ফাংশন ব্যবহার করুন। বাতিল করার বিষয়টি লক্ষ্য করার আগে সিঙ্ক্রোনাস টুল সম্পূর্ণ হওয়ার জন্য রান করে, তাই এটি সিগন্যাল উপেক্ষা করতে পারে:
- বিশুদ্ধ লজিক: মেমরিতে আগে থেকেই থাকা ডেটা ফিল্টার বা সাজানো অথবা গণিত।
- সিঙ্ক্রোনাস স্টেট:
localStorageবা সিঙ্ক্রোনাস স্টেট ম্যানেজার থেকে রিড করা।
execute(input) {
return input.items.filter(item => item.active);
}
execute-এ সমস্যা ম্যানেজ করা
execute থ্রো করলে (বা প্রত্যাখ্যাত প্রমিস ফেরত দিলে), এজেন্ট শুধুমাত্র একটি সাধারণ এক্সিকিউশন ব্যর্থতা পায়। এজেন্টকে সমস্যার মেসেজ ফরওয়ার্ড করা হয়নি। আপনার টুল যদি কোনও অ্যাকশনযোগ্য বা সমাধানযোগ্য সমস্যার (যেমন ভুল ইনপুট, অনুপস্থিত আইটেম বা ব্যর্থ HTTP স্ট্যাটাস) সম্মুখীন হয়, তাহলে throw new Error(...) করবেন না। পরিবর্তে, টুলের সাধারণ রিটার্ন ভ্যালুর মাধ্যমে একটি স্ট্রাকচার্ড এরর পেলোড রিটার্ন করুন যাতে AI এজেন্ট ডায়াগনস্টিক বিবরণ পায় এবং নিজে থেকে সংশোধন বা আবার চেষ্টা করতে পারে:
execute({ itemName }) {
const item = menuItems.find((entry) => entry.name.toLowerCase() === itemName.toLowerCase());
if (!item) {
// Return the error as a value instead of throwing, so the agent receives the message:
return {
error: `Menu item "${itemName}" not found.`,
availableItems: menuItems.map((entry) => entry.name),
};
}
return item;
}
এক্সিকিউশন বাতিল করা হলে তবেই আবার থ্রো করুন (signal.aborted হল true)।
ইন-ফ্লাইট এক্সিকিউশন বাতিল করা হচ্ছে
ব্যবহারকারী বা এজেন্ট বাতিল করার প্রসেস শুরু করেছেন। বাধ্যতামূলক: নেটওয়ার্ক অনুরোধ বা অন্যান্য দীর্ঘ সময় ধরে চলা অ্যাসিঙ্ক কাজ করে এমন যেকোনও টুলকে অবশ্যই signal মেনে চলতে হবে, অন্যথায় বাতিল করা এক্সিকিউশন রিসোর্স ব্যবহার করতে থাকবে এবং এজেন্ট এগিয়ে যাওয়ার পরে UI-তে বাসি ডেটা লিখতে পারে।
- সিগন্যাল গ্রহণ করে এমন API (
fetch(),addEventListener(),ReadableStreamরিডার):signalসরাসরি পাস করুন। - যেসব API-তে (
setTimeout,setInterval, পোলিং লুপ,await-হেভি পাইপলাইন) নেই: ধাপগুলির মধ্যেsignal.throwIfAborted()কল করুন এবং/অথবাsignal.addEventListener('abort', ...)-এ বাতিল করুন। টাইমার কোনও সিগন্যাল গ্রহণ করে না, তাই আপনাকে অবশ্যই অ্যাবর্ট লিসেনারে সেগুলি নিজে থেকে মুছে ফেলতে হবে।
await document.modelContext.registerTool({
name: "fetch_tool",
description: "Fetch the text content of a URL and show it on the page.",
inputSchema: {
type: "object",
properties: {
url: { type: "string", description: "The URL to fetch" },
priority: {
type: "string",
enum: ["high", "low", "auto"],
description: "Relative network priority for the request",
},
},
required: ["url"],
},
execute: async ({ url, priority }, { signal }) => {
const output = document.querySelector("pre");
output.textContent = "Loading…";
try {
// Passing `signal` aborts the network request the moment execution is cancelled.
const response = await fetch(url, { priority, signal });
if (!response.ok) {
output.textContent = "";
return { error: `Request failed with status ${response.status}` };
}
const text = await response.text();
output.textContent = text;
return text;
} catch (err) {
// Roll back the UI state this execution set, so a cancelled run leaves no trace.
output.textContent = "";
if (signal.aborted) {
// The execution was cancelled: re-throw instead of returning an error value.
throw err;
}
// Return other errors as a value instead of throwing, so the agent receives the message.
return { error: err instanceof Error ? err.message : String(err) };
}
},
annotations: { readOnlyHint: true }
});
ফ্ল্যাগিং কনসিকুয়েনশিয়াল টুল
Chrome 154 থেকে, annotations-এ consequentialHint কাজ করে। যেসব টুল হাই-স্টেক, আগের অবস্থায় ফিরিয়ে আনা যায় না বা বাস্তব-জগতের অ্যাকশন নেয় — ভ্রমণ বুক করা, টাকা ট্রান্সফার করা, মেসেজ পাঠানো বা ডেটা মুছে ফেলা — সেগুলির জন্য এটি true-এ সেট করুন। এটি এজেন্টকে এক্সিকিউট করার আগে ব্যবহারকারীর কাছ থেকে স্পষ্ট কনফার্মেশন চাওয়ার জন্য সিগন্যাল দেয়।
await document.modelContext.registerTool({
name: 'book_flight',
description: 'Book a flight for the user with confirmed flight details.',
inputSchema: {
type: 'object',
properties: {
flightId: { type: 'string', description: 'ID of the flight to book' },
passengers: { type: 'number', description: 'Number of tickets to purchase' },
},
required: ['flightId', 'passengers'],
},
execute: async ({ flightId, passengers }, { signal }) => {
// Forward `signal` to the transaction API to honor cancellation:
return await bookFlightReservation({ flightId, passengers }, { signal });
},
annotations: {
readOnlyHint: false, // This tool mutates state (it makes a booking).
consequentialHint: true, // Spends money and is not trivially reversible.
untrustedContentHint: false, // Output is first-party data, not third-party content.
}
});
বাধ্যতামূলক: consequentialHint-কে ইঙ্গিত হিসেবে বিবেচনা করুন, এনফোর্সমেন্ট মেকানিজম হিসেবে নয়। এটি নিজে থেকে এক্সিকিউশন ব্লক করে না এবং যেসব ব্রাউজার হিন্টের আগে থেকে আছে সেগুলি কোনও প্রম্পট দেখাবে না। অ্যাকশনের জন্য আগে থেকেই যে অ্যাপ-মধ্যস্থ কনফার্মেশন প্রয়োজন হয়, তা বজায় রাখুন।
ফ্ল্যাগিং ডিবাগিং টুল
Chrome 156 থেকে, annotations debugging-কে সাপোর্ট করে। এন্ড-ইউজার টাস্কের পরিবর্তে ডিবাগিং ও ডেভেলপার টুলিংয়ের জন্য তৈরি টুলের ক্ষেত্রে annotations.debugging-কে true-এ সেট করুন। যেমন: ইন্টার্নাল অ্যাপ স্টেট ডাম্প করা, ফিচার ফ্ল্যাগ টগল করা বা টেস্ট ডেটা সিড করা। এটি এজেন্টকে শুধুমাত্র ডেভেলপারদের জন্য টুল এবং ব্যবহারকারীর জন্য কাজ করার জন্য টুলের মধ্যে পার্থক্য করতে দেয়। এটি ডিফল্ট হিসেবে false-এ সেট করা থাকে। ইন-পেজ এজেন্ট এবং টেস্ট হারনেস getTools()-এর মাধ্যমে RegisteredTool.annotations.debugging থেকে এটি পড়তে পারে।
await document.modelContext.registerTool({
name: "dump_app_state",
description: "Returns a snapshot of the internal application store for debugging.",
execute() {
return appStore.getState();
},
annotations: {
readOnlyHint: true, // Only reads state.
debugging: true, // Developer tooling, not an end-user action.
}
});
ইন-পেজ এজেন্ট ও টেস্টিং (getTools এবং executeTool)
AI এজেন্টের কাছে টুল প্রকাশ করার জন্য ওয়েব পেজের getTools() বা executeTool()-এর প্রয়োজন নেই। ব্রাউজার এজেন্ট, ব্রাউজার এক্সটেনশন, DevTools এবং সিস্টেম-লেভেল অ্যাসিস্ট্যান্টের জন্য আপনার টুল আউট-অফ-ব্যান্ড খুঁজে পেতে এবং এক্সিকিউট করতে শুধু document.modelContext.registerTool() কল করলেই হবে।
getTools() এবং executeTool() পদ্ধতিগুলি বিশেষভাবে জাভাস্ক্রিপ্ট এনভায়রনমেন্টের মধ্যে চলা গ্রাহকদের জন্য রয়েছে:
- ইন-পেজ জাভাস্ক্রিপ্ট এজেন্ট: একটি AI অ্যাসিস্ট্যান্ট, কোপাইলট উইজেট বা চ্যাট ইন্টারফেস যা সরাসরি পৃষ্ঠায় এম্বেড করা থাকে (বা
<iframe>-এর মধ্যে রান করে) এবং আশেপাশের পৃষ্ঠা বা ডকুমেন্ট ট্রিতে অ্যাক্সেসযোগ্য ফ্রেম কী কী টুল অফার করে তা খুঁজে বের করতে এবং ব্যবহারকারীর হয়ে সেগুলি কল করতে হয়। - অটোমেটেড টেস্টিং ও ডিবাগিং: টেস্ট স্যুট (যেমন Playwright, Vitest বা ইন-ব্রাউজার ইউনিট টেস্ট) যা রেজিস্টার করা টুল মেটাডেটা পরীক্ষা করে এবং লাইভ এক্সটার্নাল LLM হার্নেসের প্রয়োজন ছাড়াই এজেন্ট টুল ইনভোকেশন সিমুলেট করে।
getTools()-এর সাথে উপলভ্য টুল খুঁজে দেখা হচ্ছে
বর্তমান ডকুমেন্ট এবং ডকুমেন্ট ট্রির যেকোনও অ্যাক্সেসযোগ্য ফ্রেম থেকে RegisteredTool অবজেক্টের একটি অ্যারে ফিরিয়ে আনতে ইন-পেজ এজেন্ট document.modelContext.getTools()-কে কল করে।
Chrome 155 থেকে, RegisteredTool.inputSchema সরাসরি জাভাস্ক্রিপ্ট অবজেক্ট (রেজিস্ট্রেশনের সময় দেওয়া স্কিমার ডিপ কপি) হিসেবে রিটার্ন করা হয়। এই অবজেক্ট মিউটেট করলে রেজিস্টার করা টুলের আসল স্কিমা পরিবর্তন হয় না।
// Example: An in-page AI assistant discovering tools available on the page:
const tools = await document.modelContext.getTools();
// In-page agents can listen for tools being registered or unregistered dynamically:
document.modelContext.addEventListener("toolchange", async () => {
const updatedTools = await document.modelContext.getTools();
console.log(`Active tools updated: ${updatedTools.map((t) => t.name).join(", ")}`);
});
ক্রস-অরিজিন ডিসেন্ডেন্ট iframe-এর (যা রেজিস্ট্রেশনের সময় exposedTo-এর মাধ্যমে স্পষ্টভাবে অ্যাক্সেস দিতে হবে) মধ্যে রেজিস্টার করা টুল খুঁজে পেতে, বিকল্প ডিকশনারিতে fromOrigins পাস করুন:
// Query tools registered in the embedded cart frame that exposed them to this checkout origin:
const cartTools = await document.modelContext.getTools({
fromOrigins: ["https://cart.example.com"],
});
executeTool()-এর মাধ্যমে টুল চালু করা হচ্ছে
রেজিস্টার করা টুল এক্সিকিউট করতে, ইন-পেজ এজেন্ট ও টেস্ট স্ক্রিপ্ট document.modelContext.executeTool(tool, inputObject, options) কল করে। যে ডকুমেন্টে টুলটি রেজিস্টার করা হয়েছে সেখানে এটি রান করে এবং টুলটির execute কলব্যাক দ্বারা রিটার্ন করা স্ট্রিংগিফাইড ফলাফলে প্রমিসটি রিজলভ হয়।
Chrome 155 থেকে, executeTool() সরাসরি inputObject-এর জন্য একটি প্লেন JavaScript অবজেক্ট গ্রহণ করে, যা আপনার টুলের execute কলব্যাক যে ইনপুট ফর্ম্যাট গ্রহণ করে তার সাথে মেলে।
// 1. Discover the tool (typically done during agent initialization or test setup):
const tools = await document.modelContext.getTools();
const areaTool = tools.find((t) => t.name === "calculate_area");
if (areaTool) {
const controller = new AbortController();
// Example input payload matching the tool's inputSchema:
const inputObject = { width: 10, height: 20 };
const options = { signal: controller.signal };
// 2. Pass input arguments as a JavaScript object, with a JSON string fallback for Chrome <155:
let resultString;
try {
resultString = await document.modelContext.executeTool(areaTool, inputObject, options);
} catch (err) {
if (err?.message?.startsWith("Failed to parse input")) {
resultString = await document.modelContext.executeTool(
areaTool,
JSON.stringify(inputObject),
options
);
} else {
// Re-throw real tool execution or cancellation errors:
throw err;
}
}
console.log("Execution output string:", resultString);
}
ফেরত দেওয়া প্রমিস বাতিল করা হয় যদি:
inputObjectকোনও অবজেক্ট নয় অথবা JSON স্ট্রিংয়ে সিরিয়ালাইজ করা যাবে না (যেমন, সার্কুলার রেফারেন্স বাBigIntভ্যালু)। মনে রাখবেন যে JSON সিরিয়ালাইজেশন (যেমন ফাংশন এবংundefined) দ্বারা বাদ দেওয়া মানগুলি টুল দ্বারা প্রাপ্ত অবজেক্ট থেকে বাদ দেওয়া হবে, যার ফলে কোনও প্রত্যাখ্যান হবে না।options.signal-এর মাধ্যমে এক্সিকিউশন বাতিল করা হয়েছে।- এক্সিকিউশনের আগে টুলটি আনরেজিস্টার করা হয়েছে অথবা রানটাইম সংক্রান্ত কোনও সমস্যা হয়েছে যা সমাধান করা যায়নি।
টুল ফ্যাক্টরি প্যাটার্ন
আপনার টুলে প্রসঙ্গ (যেমন স্টোর বা অ্যাপ্লিকেশন ইনস্ট্যান্স) পাস করতে, ফ্যাক্টরি ফাংশন ব্যবহার করুন।
export function createInventoryTool(inventoryManager) {
return {
name: "get_inventory",
description: "Lists items in the inventory.",
inputSchema: { type: "object", properties: {} },
execute() {
return inventoryManager.getItems();
},
annotations: { readOnlyHint: true }
};
}
TypeScript-এর ধরন
TypeScript প্রোজেক্টে, document.modelContext-এর জন্য হাতে লিখে ডিক্লেয়ারেশন করবেন না। অফিসিয়াল webmcp-types প্যাকেজ (npm install --save-dev webmcp-types) ইনস্টল করুন এবং এটি tsconfig.json-এ যোগ করুন, কারণ এটি অটোমেটিক বেছে নেওয়া হয় না:
{
"compilerOptions": {
"types": ["webmcp-types"]
}
}
document.modelContextঐচ্ছিক হিসেবে টাইপ করা হয়েছে, তাই ব্যবহার করার আগেif (document.modelContext)দিয়ে এটি গার্ড করুন।- ইনলাইন
inputSchema-এর সাথে,executeইনপুট টাইপ স্কিমা থেকে অনুমান করা হয়। WebMCP.ModelContextTool-এর মতো নামযুক্ত ধরনগুলি গ্লোবাল (ইমপোর্ট করার প্রয়োজন নেই), টাইপিং টুল ফ্যাক্টরির জন্য উপযোগী।
ফ্রেমওয়ার্ক সাপোর্ট
বাধ্যতামূলক: অ্যাপটি React, Angular বা Vue ব্যবহার করলে, নিচে তালিকাভুক্ত সেই ফ্রেমওয়ার্কের অফিসিয়াল WebMCP ইন্টিগ্রেশনের মাধ্যমে টুল রেজিস্টার করুন। কম্পোনেন্ট থেকে document.modelContext.registerTool() কল করবেন না অথবা আপনার নিজস্ব লাইফসাইকেল র্যাপার লিখবেন না। প্রতিটি ইন্টিগ্রেশন আগে থেকেই ফিচার শনাক্তকরণ, AbortSignal ক্লিনআপ এবং কম্পোনেন্ট বা ইনজেক্টর লাইফসাইকেলে টুল স্কোপিং ম্যানেজ করে। এই APIগুলি পরীক্ষামূলক, তাই কোড লেখার আগে, প্যাকেজের ধরন বা ডকুমেন্টে বর্তমান সিগনেচার দেখুন।
| ফ্রেমওয়ার্ক | প্যাকেজ | API | Docs |
|---|---|---|---|
| React 18+ | use-webmcp-tool |
useWebMCP(options): টুল প্রতি একটি কল |
npmjs.com/package/use-webmcp-tool |
| Angular | @angular/core, @angular/forms/signals |
provideExperimentalWebMcpTools([...]) (অ্যাপ বা রুট প্রদানকারী), declareExperimentalWebMcpTool(...) (ইনসাইড পরিষেবা), provideExperimentalWebMcpForms() + সিগন্যাল ফর্মে experimentalWebMcpTool বিকল্প |
angular.dev/ai/webmcp |
| Vue | @vueuse/core |
useWebMCP(options) কম্পোজেবল |
vueuse.org/core/usewebmcp |
আপনি এইসব ইন্টিগ্রেশন ব্যবহার করার সময় এই গাইডের সব নিয়ম এখনও প্রযোজ্য:
- টুল ডেফিনিশনের আকার একই রাখুন:
name,description,inputSchema,execute(input, { signal })এবংannotations। - বিবরণ ও অ্যানোটেশনের জন্য নিয়মাবলী অনুসরণ করুন।
- ইনপুট যাচাই করুন এবং
execute-এর মধ্যে ডিফল্ট প্রয়োগ করুন। - দীর্ঘ সময় ধরে চলা কাজের জন্য
signalপাস করুন। - কোনও টুল শুধুমাত্র কিছু সময়ের জন্য অফার করতে,
enabled(React, Vue) পাস করুন। কোনও শর্তে হুক বা কম্পোজেবল কল র্যাপ করবেন না। - ইন্টিগ্রেশন ফলাফল এবং ত্রুটিগুলি (যেমন
{ content, isError }) র্যাপ করতে পারে। এজেন্টের কাছে কীভাবে ত্রুটি পৌঁছায় তার উপর নির্ভর করার আগে ইন্টিগ্রেশনের ডকুমেন্ট চেক করুন।
API Notes
- annotations: (ঐচ্ছিক) টুল মেটাডেটার জন্য একটি ডিকশনারি।
- readOnlyHint: (ঐচ্ছিক) টুলটি কোনও স্ট্যাটাস পরিবর্তন না করে এবং শুধুমাত্র ডেটা পড়লে
true-এ সেট করুন। এটি এজেন্টদের সিদ্ধান্ত নিতে সাহায্য করে যে কখন টুলটি কল করা নিরাপদ। - consequentialHint: (ঐচ্ছিক, Chrome 154+) উচ্চ-ঝুঁকি, অপরিবর্তনীয় বা বাস্তব-জগতের অ্যাকশনের জন্য
true-এ সেট করুন যাতে এজেন্টরা প্রথমে ব্যবহারকারীর কনফার্মেশনের অনুরোধ করে। - untrustedContentHint: (ঐচ্ছিক) টুলটি এমন কন্টেন্ট রিটার্ন করলে
true-এ সেট করুন যা আপনার সাইট নিয়ন্ত্রণ করে না, যেমন ব্যবহারকারীর তৈরি করা টেক্সট বা থার্ড-পার্টি API রেসপন্স। - ডিবাগিং: (ঐচ্ছিক, Chrome 156+) টুলটি ডিবাগিং এবং ডেভেলপার টুলিংয়ের জন্য হলে,
true-এ সেট করুন, ব্যবহারকারীর টাস্কের জন্য নয়। ডিফল্ট হিসেবেfalseসেট করা থাকে।
- readOnlyHint: (ঐচ্ছিক) টুলটি কোনও স্ট্যাটাস পরিবর্তন না করে এবং শুধুমাত্র ডেটা পড়লে
- রেজিস্ট্রেশন সংক্রান্ত বিকল্প:
- signal: (ঐচ্ছিক) টুলটির আর প্রয়োজন না থাকলে, সেটির রেজিস্ট্রেশন বাতিল করতে
AbortSignalব্যবহার করা হয়। - exposedTo: (ঐচ্ছিক) নিরাপদ অরিজিন স্ট্রিংয়ের একটি অ্যারে যা নিয়ন্ত্রণ করে যে ডকুমেন্ট ট্রির কোন কোন ডকুমেন্টকে ফ্রেমের সীমানা জুড়ে টুলটি খুঁজে বের করার এবং চালানোর অনুমতি দেওয়া হয়েছে।
- signal: (ঐচ্ছিক) টুলটির আর প্রয়োজন না থাকলে, সেটির রেজিস্ট্রেশন বাতিল করতে
- টুল খোঁজার বিকল্প (
ModelContextGetToolOptions):- fromOrigins: (ঐচ্ছিক) অ্যাক্সেসযোগ্য ফ্রেমে কোয়েরি করার জন্য সুরক্ষিত অরিজিন স্ট্রিংয়ের একটি অ্যারে।
fromOriginsছাড়াgetTools()কল করলে শুধু একই-অরিজিনের ডকুমেন্ট কোয়েরি করে।
- fromOrigins: (ঐচ্ছিক) অ্যাক্সেসযোগ্য ফ্রেমে কোয়েরি করার জন্য সুরক্ষিত অরিজিন স্ট্রিংয়ের একটি অ্যারে।
- রিটার্ন ফর্ম্যাট:
executeফাংশন যেকোনও JSON-সিরিয়ালাইজেবল ভ্যালু (অবজেক্ট, অ্যারে, স্ট্রিং, সংখ্যা, বুলিয়ান) রিটার্ন করতে পারে।executeথেকে থ্রো করা ব্যতিক্রমের মেসেজ এজেন্টের কাছে ফরওয়ার্ড করা হয় না, তাই টুলের রিটার্ন ভ্যালুর মাধ্যমে স্ট্রাকচার্ড এরর পেলোড (যেমন,{ error: "..." }) হিসেবে অ্যাকশনেবল এরর রিটার্ন করুন যাতে এজেন্ট সেগুলি পড়তে ও সেই অনুযায়ী কাজ করতে পারে। - সুরক্ষিত কনটেক্সট: WebMCP-এর জন্য HTTPS প্রয়োজন।
exposedToএবংfromOrigins-এর সব উৎসও সম্ভাব্য বিশ্বাসযোগ্য হতে হবে। - বন্ধ/সরিয়ে দেওয়া হয়েছে:
navigator.modelContext(Chromium 150-এ বন্ধ করা হয়েছে),unregisterTool(),provideContext()এবংclearContext()আর কাজ করে না।
ফলব্যাক স্ট্র্যাটেজি
WebMCP Imperative API-কে ফিচার শনাক্তকরণের সাথে ব্যবহার করা উচিত যাতে যেসব ব্রাউজারে এখনও WebMCP কাজ করে না সেগুলির সাথে মানানসই হয়।
if ('modelContext' in document) {
// Register tools
}