Narzędzia JavaScriptu agenta

Funkcje internetowe: document.modelContext

Interfejs Imperative API używa document.modelContext.registerTool() do programowego definiowania narzędzi JavaScript. Jest to idealne rozwiązanie w przypadku aplikacji jednostronicowych (SPA), w których narzędzia muszą być dodawane lub usuwane na podstawie bieżącej ścieżki lub stanu użytkownika.

WebMCP działa w architekturze producent/konsument:

  • Strony internetowe są producentami narzędzi: definiujesz i rejestrujesz narzędzia za pomocą document.modelContext.registerTool(). To wszystko, co musi zawierać strona internetowa. Nie musisz wywoływać na stronie funkcji getTools() ani executeTool(), aby udostępnić narzędzia agentom.
  • Przeglądarka i rozszerzenia są głównymi konsumentami: agenty udostępniane przez przeglądarkę lub za jej pośrednictwem – w tym wbudowany agent przeglądarki, rozszerzenia przeglądarki, Narzędzia deweloperskie i asystenci na poziomie systemu – wykrywają i wywołują zarejestrowane narzędzia poza pasmem za pomocą wewnętrznych mechanizmów platformy.
  • Agenty i jarzma testowe na stronie: getTools() i executeTool() istnieją specjalnie dla asystentów JavaScriptu na stronie (np. wbudowanego widżetu czatu lub <iframe>) oraz automatycznych pakietów testowych, które muszą wykrywać i wywoływać narzędzia bezpośrednio w kontekście strony.

Rejestracja i cykl życia

Narzędzia są rejestrowane przez przekazanie obiektu definicji narzędzia i opcjonalnego obiektu opcji (ModelContextRegisterToolOptions), który obsługuje 2 opcjonalne elementy:

  • signal: AbortSignal używany do wyrejestrowania narzędzia, gdy nie jest już potrzebne.
  • exposedTo: tablica ciągów znaków pochodzenia, która określa, które dokumenty w drzewie dokumentów mogą wykrywać i wykonywać narzędzie poza granicami ramki.

Obsługa cyklu życia za pomocą AbortController

WebMCP nie udostępnia metody unregisterTool(). Aby wyrejestrować narzędzie, musisz przekazać AbortSignal podczas rejestracji i przerwać ten sygnał, gdy narzędzie nie będzie już potrzebne.

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

Przerwanie sygnału rejestracji powoduje jedynie wyrejestrowanie narzędzia – nie anuluje już uruchomionych wykonań. Narzędzia, które rozpoczynają długotrwałe zadania, muszą też uwzględniać opisany poniżej sygnał dotyczący wykonania. W przeciwnym razie wyrejestrowanie pozostawi osierocone żądania i nieaktualne aktualizacje interfejsu.

Kontrolowanie ekspozycji narzędzi w różnych domenach za pomocą exposedTo

Domyślnie zarejestrowane narzędzie jest prywatne dla dokumentu rejestrującego i ramek z tego samego źródła. Jeśli Twoja aplikacja jest umieszczona w elemencie <iframe> (lub zawiera widżety innych firm) i potrzebujesz ramek nadrzędnych lub równorzędnych, aby wykryć i wywołać narzędzie, określ dozwolone źródła za pomocą 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"],
});
  • Wzajemne uzgadnianie akceptacji: wykrywanie narzędzi współdzielenia wymaga akceptacji po obu stronach. Ramka dostawcy narzędzia autoryzuje źródło klienta za pomocą exposedTo, a ramka klienta musi wyraźnie zażądać tego źródła dostawcy za pomocą getTools({ fromOrigins: [...] }). Bez fromOrigins getTools() wysyła zapytania tylko do dokumentów z tego samego źródła.
  • Dopasowanie źródła: źródło dokumentu rejestracyjnego zawsze ma dostęp. Źródła określone w exposedTo mają uprawnienia do wykrywania narzędzia za pomocą document.modelContext.getTools({ fromOrigins: [...] }) i wykonywania go za pomocą document.modelContext.executeTool().
  • Wymaganie dotyczące bezpieczeństwa: każde źródło w exposedTo MUSI być potencjalnie godne zaufania (HTTPS lub localhost). Przekazanie nieprawidłowego lub niezabezpieczonego źródła powoduje odrzucenie metody registerTool() z błędem SecurityError.
  • Zakres: exposedTo kontroluje wykrywanie dokumentów na stronie w ramkach w drzewie dokumentu.

Definiowanie parametrów

Parametry są definiowane za pomocą właściwości inputSchema. Musi to być obiekt JSON Schema, który opisuje uporządkowane dane oczekiwane przez narzędzie.

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 }
});

Pisanie opisów narzędzi i parametrów

Agent otrzymuje już pełny inputSchema, więc description musi tylko określać, co robi narzędzie i kiedy go używać. NIE powtarzaj w nim nazw parametrów, typów, wartości enum, wartości domyślnych ani limitów. Zamiast tego zadeklaruj je w schemacie (enum, default, minimum/maximum). Opisy parametrów podlegają tej samej zasadzie: podaj, co oznacza wartość, a nie jej typ lub dozwolone wartości.

Przeglądarka nie sprawdza argumentów pod kątem inputSchema ani nie stosuje wartości default, więc obie te czynności wykonaj w 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 },
});

Wzorce wykonywania

Wywołanie zwrotne execute zawsze otrzymuje 2 argumenty: obiekt wejściowy i obiekt opcji zawierający AbortSignal – execute(inputObject, { signal }).

Kiedy używać async execute

Użyj async, gdy narzędzie obejmuje operacje, które zwracają obiekt Promise lub wymagają czasu na wykonanie:

  • Wywołania sieciowe: pobieranie danych z interfejsu API.
  • Asynchroniczne miejsce na dane: dostęp do IndexedDB.
  • Zdarzenia zewnętrzne: oczekiwanie na zmianę stanu lub zakończenie animacji.
async execute(input, { signal }) {
  const response = await fetch(`/api/data/${input.id}`, { signal });
  return await response.json();
}

Kiedy używać execute (synchronicznego)

Użyj standardowej funkcji synchronicznej do natychmiastowych operacji. Narzędzie synchroniczne działa do zakończenia, zanim będzie można zaobserwować anulowanie, więc może zignorować sygnał:

  • Czysta logika: obliczenia matematyczne, filtrowanie lub sortowanie danych, które są już w pamięci.
  • Stan synchroniczny: odczyt z localStorage lub menedżera stanu synchronicznego.
execute(input) {
  return input.items.filter(item => item.active);
}

Obsługa błędów w execute

Gdy execute zgłasza błąd (lub zwraca odrzuconą obietnicę), agent otrzymuje tylko ogólny błąd wykonania. Komunikat o błędzie nie jest przekazywany do pracownika obsługi klienta. Jeśli narzędzie napotka błąd, który można naprawić lub który można rozwiązać (np. nieprawidłowe dane wejściowe, brakujące elementy lub nieprawidłowy stan HTTP), NIE throw new Error(...). Zamiast tego zwróć uporządkowany ładunek błędu za pomocą normalnej wartości zwracanej przez narzędzie, aby agent AI otrzymał szczegóły diagnostyczne i mógł samodzielnie poprawić błąd lub spróbować ponownie:

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;
}

Zgłaszaj ponownie tylko wtedy, gdy wykonanie zostało anulowane (signal.aborted to true).

Anuluję wykonywanie w trakcie

Anulowanie jest inicjowane przez użytkownika lub agenta. OBOWIĄZKOWE: każde narzędzie, które wykonuje żądania sieciowe lub inne długotrwałe zadania asynchroniczne, MUSI uwzględniać signal. W przeciwnym razie anulowane wykonania będą nadal zużywać zasoby i mogą zapisywać nieaktualne dane w interfejsie po przejściu agenta do innego zadania.

  • Interfejsy API, które akceptują sygnał (czytniki fetch(), addEventListener(), ReadableStream): przekazują signal bezpośrednio.
  • Interfejsy API, które nie obsługują (setTimeout, setInterval, pętle odpytywania, potoki z dużą liczbą await): wywołaj signal.throwIfAborted() między krokami lub odrzuć w przypadku signal.addEventListener('abort', ...). Minutniki nie akceptują sygnału, więc musisz je samodzielnie wyczyścić w detektorze przerwania.
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 }
});

Narzędzia do zgłaszania treści

Od Chrome 154 zasada annotations obsługuje consequentialHint. Ustaw wartość true w przypadku narzędzi, które wykonują działania o wysokiej stawce, nieodwracalne lub w świecie rzeczywistym – rezerwowanie podróży, przesyłanie pieniędzy, wysyłanie wiadomości lub usuwanie danych. Sygnalizuje agentom, że przed wykonaniem działania muszą poprosić użytkownika o wyraźne potwierdzenie.

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.
  }
});

OBOWIĄZKOWO: traktuj consequentialHint jako wskazówkę, a nie mechanizm egzekwowania. Nie blokuje on samodzielnie wykonywania, a przeglądarki, które nie obsługują tej wskazówki, nie będą w ogóle wyświetlać prośby. Zachowaj potwierdzenie w aplikacji, które jest już wymagane przez działanie.

Narzędzia do debugowania zgłaszania

Od wersji Chrome 156 annotations obsługuje debugging. W przypadku narzędzi przeznaczonych do debugowania i narzędzi dla programistów, a nie do zadań użytkowników, ustaw annotations.debugging na true. Przykłady: zrzucanie stanu wewnętrznego aplikacji, przełączanie flag funkcji lub wypełnianie danymi testowymi. Dzięki temu agenty mogą odróżnić narzędzia przeznaczone tylko dla deweloperów od narzędzi, które mają działać w imieniu użytkownika. Domyślna wartość to false. Agenty na stronie i jarzma testowe mogą odczytywać te dane z RegisteredTool.annotations.debugging za pomocą getTools().

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.
  }
});

Agenty na stronie i testowanie (getTools i executeTool)

Strony internetowe nie potrzebują getTools() ani executeTool(), aby udostępniać narzędzia agentom AI. Wystarczy wywołać document.modelContext.registerTool(), aby agenty przeglądarki, rozszerzenia przeglądarki, Narzędzia deweloperskie i asystenci na poziomie systemu mogli wykrywać i wykonywać narzędzia poza pasmem.

Metody getTools() i executeTool() są przeznaczone specjalnie dla klientów działających w środowisku JavaScript:

  1. Agenty JavaScript na stronie: asystent AI, widżet pomocniczy lub interfejs czatu umieszczony bezpośrednio na stronie (lub działający w elemencie <iframe>), który musi wykryć, jakie narzędzia oferuje otaczająca strona lub dostępne ramki w drzewie dokumentu, i wywołać je w imieniu użytkownika.
  2. Zautomatyzowane testowanie i debugowanie: pakiety testów (takie jak Playwright, Vitest lub testy jednostkowe w przeglądarce), które sprawdzają zarejestrowane metadane narzędzi i symulują wywołania narzędzi agenta bez konieczności korzystania z zewnętrznego LLM.

Odkrywanie dostępnych narzędzi za pomocą getTools()

Agenty na stronie wywołują document.modelContext.getTools(), aby pobrać tablicę obiektów RegisteredTool z bieżącego dokumentu i wszystkich dostępnych ramek w drzewie dokumentu.

Od wersji Chrome 155 RegisteredTool.inputSchema jest zwracany bezpośrednio jako obiekt w JavaScripcie (głęboka kopia schematu dostarczonego podczas rejestracji). Zmiana tego obiektu nie wpływa na rzeczywisty schemat zarejestrowanego narzędzia.

// 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(", ")}`);
});

Aby wykryć narzędzia zarejestrowane w elementach iframe potomnych współdzielenia (które podczas rejestracji muszą wyraźnie przyznać dostęp przez exposedTo), przekaż fromOrigins w słowniku opcji:

// 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"],
});

Wywoływanie narzędzi za pomocą executeTool()

Agenty na stronie i skrypty testowe wywołują funkcję document.modelContext.executeTool(tool, inputObject, options), aby wykonać zarejestrowane narzędzie. Narzędzie działa w dokumencie, w którym zostało zarejestrowane, a obietnica jest rozwiązywana do wyniku w postaci ciągu znaków zwróconego przez wywołanie zwrotne execute narzędzia.

Od wersji Chrome 155 executeTool() akceptuje zwykły obiekt w JavaScripcie bezpośrednio dla inputObject, co odpowiada formatowi danych wejściowych, który otrzymuje wywołanie zwrotne execute narzędzia.

// 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);
}

Zwrócona obietnica zostanie odrzucona, jeśli:

  • inputObject nie jest obiektem lub nie można go przekształcić w ciąg JSON (np. odwołania cykliczne lub wartości BigInt). Pamiętaj, że wartości pominięte przez serializację JSON (takie jak funkcje i undefined) zostaną pominięte w obiekcie otrzymanym przez narzędzie, a nie spowodują odrzucenia.
  • Wykonanie zostało przerwane przez: options.signal.
  • Narzędzie zostało wyrejestrowane przed wykonaniem lub wystąpił nieobsługiwany błąd środowiska wykonawczego.

Wzorzec fabryki narzędzi

Aby przekazać kontekst (np. sklepy lub instancje aplikacji) do narzędzi, użyj funkcji fabrycznych.

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 }
  };
}

Typy TypeScript

W projektach TypeScript NIE pisz ręcznie deklaracji dla document.modelContext. Zainstaluj oficjalny pakiet webmcp-types (npm install --save-dev webmcp-types) i dodaj go do tsconfig.json, ponieważ nie jest on automatycznie wykrywany:

{
  "compilerOptions": {
    "types": ["webmcp-types"]
  }
}
  • Typ document.modelContext jest opcjonalny, więc przed użyciem zabezpiecz go za pomocą if (document.modelContext).
  • W przypadku wbudowanego elementu inputSchema typ danych wejściowych execute jest określany na podstawie schematu.
  • Nazwane typy, takie jak WebMCP.ModelContextTool, są globalne (nie trzeba ich importować) i przydatne do wpisywania fabryk narzędzi.

Obsługa platformy

OBOWIĄZKOWO: jeśli aplikacja korzysta z React, Angular lub Vue, zarejestruj narzędzia za pomocą oficjalnej integracji WebMCP tej platformy, która jest wymieniona poniżej. NIE wywołuj funkcji document.modelContext.registerTool() z komponentów ani nie twórz własnego kodu opakowującego cykl życia. Każda integracja obsługuje już wykrywanie funkcji, czyszczenie AbortSignal i narzędzia do określania zakresu w cyklu życia komponentu lub wstrzykiwacza. Te interfejsy API są eksperymentalne, więc przed napisaniem kodu sprawdź bieżącą sygnaturę w typach lub dokumentacji pakietu.

Platforma Pakiet Interfejs API Dokumenty
React 18+ use-webmcp-tool useWebMCP(options): 1 wywołanie na narzędzie npmjs.com/package/use-webmcp-tool
Angular @angular/core, @angular/forms/signals provideExperimentalWebMcpTools([...]) (dostawcy aplikacji lub tras), declareExperimentalWebMcpTool(...) (usługi wewnętrzne), provideExperimentalWebMcpForms() + opcja experimentalWebMcpTool w formularzach Signal Forms angular.dev/ai/webmcp
Vue @vueuse/core Funkcja kompozycyjna useWebMCP(options) vueuse.org/core/usewebmcp

Wszystkie zasady opisane w tym przewodniku obowiązują również w przypadku korzystania z tych integracji:

  • Zachowaj ten sam kształt definicji narzędzia: name, description, inputSchema, execute(input, { signal }) i annotations.
  • Przestrzegaj zasad dotyczących opisów i adnotacji.
  • Sprawdź dane wejściowe i zastosuj wartości domyślne w execute.
  • Przekaż signal do długotrwałego zadania.
  • Aby udostępniać narzędzie tylko przez pewien czas, przekaż enabled (React, Vue). NIE umieszczaj wywołania funkcji hook ani funkcji kompozycyjnej w warunku.
  • Integracje mogą opakowywać wyniki i błędy (np. jako { content, isError }). Zanim zaczniesz polegać na sposobie, w jaki błędy docierają do agenta, zapoznaj się z dokumentacją integracji.

Uwagi dotyczące interfejsu API

  • annotations: (opcjonalnie) słownik metadanych narzędzia.
    • readOnlyHint: (opcjonalnie) ustaw wartość true, jeśli narzędzie nie modyfikuje żadnego stanu i tylko odczytuje dane. Pomaga to agentom zdecydować, kiedy można bezpiecznie wywołać narzędzie.
    • consequentialHint: (opcjonalnie, Chrome 154 lub nowszy) ustaw wartość true w przypadku działań o dużym znaczeniu, nieodwracalnych lub rzeczywistych, aby agenty najpierw prosiły użytkownika o potwierdzenie.
    • untrustedContentHint: (opcjonalnie) ustaw wartość true, gdy narzędzie zwraca treści, których Twoja witryna nie kontroluje, np. tekst wygenerowany przez użytkownika lub odpowiedzi interfejsu API innej firmy.
    • debugging: (opcjonalnie, Chrome 156 lub nowszy) ustaw wartość true, gdy narzędzie jest przeznaczone do debugowania i narzędzi dla programistów, a nie do zadań użytkownika. Domyślna wartość to false.
  • Opcje rejestracji:
    • signal: (opcjonalnie) AbortSignal używany do wyrejestrowania narzędzia, gdy nie jest już potrzebne.
    • exposedTo: (opcjonalnie) tablica ciągów znaków bezpiecznego źródła, która określa, które dokumenty w drzewie dokumentów mogą wykrywać i wykonywać narzędzie poza granicami ramki.
  • Opcje wykrywania narzędzi (ModelContextGetToolOptions):
    • fromOrigins: (opcjonalnie) tablica ciągów znaków bezpiecznych źródeł, które mają być wyszukiwane w dostępnych ramkach. Wywołanie getTools() bez fromOrigins wysyła zapytania tylko do dokumentów z tego samego źródła.
  • Format zwracanych danych: funkcja execute może zwracać dowolną wartość, którą można przekształcić w format JSON (obiekt, tablicę, ciąg znaków, liczbę, wartość logiczną). Komunikat o wyjątku zgłoszonym przez execute nie jest przekazywany do agenta, dlatego zwracaj błędy, które można naprawić, jako ustrukturyzowane ładunki błędów (np. { error: "..." }) za pomocą wartości zwracanej przez narzędzie, aby agent mógł je odczytać i podjąć odpowiednie działania.
  • Bezpieczny kontekst: WebMCP wymaga protokołu HTTPS. Wszystkie źródła w exposedTo i fromOrigins muszą być potencjalnie godne zaufania.
  • Wycofane/usunięte: navigator.modelContext (wycofane w Chromium 150), unregisterTool(), provideContext() i clearContext() nie są już obsługiwane.

Strategie zastępcze

Interfejs WebMCP Imperative API powinien być używany z wykrywaniem funkcji, aby zapewnić zgodność z przeglądarkami, które nie obsługują jeszcze WebMCP.

if ('modelContext' in document) {
  // Register tools
}