Strona główna / Artykuły

WebMCP w praktyce: przekształcanie tablicy zadaniami w narzędzia dla agentów AI

WebMCP w praktyce: tablica z zadaniami przekształcona w narzędzia dla agentów AI z deklaratywnymi i skryptowanymi narzędziami, zmieniającą się listą narzędzi, mostkiem MCP oraz odmową.

Wydawca: REACTAPP.TOP14 min czytania3318 słów

Źródła: WebMCP: When Websites Become AI Tools

Agenty, które zgadują co do twojej strony internetowej

Dziś agent AI pracujący ze stroną internetową głównie zgaduje. Pobiera zrzut ekranu i szuka czegoś, co przypomina przycisk, albo analizuje DOM w nadziei, że nazwy klas oznaczają to, co wydają się oznaczać. Po kliknięciu sprawdza, czy strona uległa zmianie w sposób wskazujący na sukces. To imponujący trik oparty na słabej podstawie, ponieważ strona nigdy nic nie powiedziała agentowi, a każdy wniosek został wyciągnięty z analizy.

WebMCP to propozycja Chrome mająca na celu położenie kresu temu zgaduwaniu. Strona ogłasza swoje możliwości, agent czyta to ogłoszenie i wywołuje funkcję z ustrukturyzowanymi argumentami, zamiast celować w prostokąt na ekranie. Zmiana wydaje się niewielka, ale przenosi inteligencję w inne miejsce: zamiast odbudowywać cel aplikacji na podstawie pikseli i kodu, agent otrzymuje ten cel bezpośrednio od samej aplikacji.

Aby sprawdzić, czy to sprawdza się w praktyce, stworzono małą tablicę z zadaniami do wykonania i skierowano do niej rzeczywistego agenta. Najbardziej pouczający wynik uzyskano wtedy, gdy agent kategorycznie odrzucił prośbę.

Trzy role

Każda chwila eksperymentu obejmuje jednego z trzech uczestników.

  • Strona pełni rolę dostawcy. Rejestruje narzędzia. Każde narzędzie łączy nazwę z opisem przeznaczonym dla modelu, schematem JSON opisującym argumenty oraz funkcją, która wykonywa pracę.
  • Przeglądarka pełni rolę rejestru. Dla każdej karty przechowuje listę narzędzi, w miarę możliwości wyodrębnia schematy z HTML i decyduje, kiedy narzędzie się pojawi, a kiedy zniknie.
  • Agent to konsument. Pyta przeglądarkę o dostępne opcje za pomocą getTools() i uruchamia wybrany narzędzie za pomocą executeTool(). DOM pozostaje poza jego zasięgiem, a on nie ma możliwości uzupełnienia funkcji, których strona nigdy nie udostępniła.
  • To ostatnie punkt stanowi sedno tej koncepcji. Dokumentacja Chrome opisuje API wystarczająco jasno, ale czytanie wyjaśnień nie jest równoznaczne z zrozumieniem rzeczy, dlatego najszybszym rozwiązaniem było stworzenie najmniejszej możliwej wersji.

    Demo: tablica z zadaniami w trzech plikach

    Struktura składa się z plików index.html, app.js oraz style.css. Nie trzeba nic budować ani instalować. Użytkownicy mogą dodawać zadania, je oznaczać jako wykonane oraz filtrować listę – to projekt, który można zrealizować w ciągu popołudnia. Nowością jest to, że strona jest również prezentowana agentowi AI jako zbiór dostępnych narzędzi, za pośrednictwem jednego obiektu dostarczanego przez przeglądarkę.

    const mc = document.modelContext;   // undefined if WebMCP is off
    

    To jedno zdanie stanowi cały punkt wejścia. Gdy obiekt istnieje, strona może rejestrować narzędzia. Gdy go nie ma, strona jest po prostu tablicą z zadaniami, co jest właściwym sposobem jej funkcjonowania w takim przypadku.

    Aby obie części były widoczne, strona demonstracyjna umieszcza je obok siebie. Po lewej znajduje się tablica, czyli dostawca. Po prawej znajduje się panel „Pretend Agent”, który pełni rolę konsumenta i wysyła wywołania getTools() oraz executeTool() dokładnie tak, jak robiłby to prawdziwy agent, co eliminuje konieczność dodatkowych połączeń. Zobaczycie ten panel na każdym poniższym zrzutku ekranu.

    WebMCP nadal ma status „Proposed” na stronie Chrome Platform Status i domyślnie nie jest włączony nigdzie, więc najpierw potrzebna jest odpowiednia flaga.

    Otwórz chrome://flags/#enable-webmcp-testing, ustaw go na „Enabled” i uruchom przeglądarkę ponownie. Bez tego document.modelContext jest niezdefiniowany. Chrome oferuje również wersję testową WebMCP origin, dostępną od wersji 149. Ta flaga nadaje się do eksperymentów lokalnych, natomiast wersja testowa origin jest rozwiązaniem proponowanym przez Chrome do szerszych testów.

    Najpierw ukończony pętla

    Latwiej jest zrozumieć API po zobaczeniu, co on generuje. Claude Code został połączony z płytką i otrzymał jedno zdanie z prośbą o dodanie czterech zadań: poszukiwanie informacji i przeprowadzanie badań, tworzenie szkiców bloga, przygotowanie kompletnego bloga z przykładami oraz jego publikacja. Pojawiły się cztery zadania. Drugie zdanie poprosiło o oznaczenie zadań 3, 4 i 5 jako zakończonych, i to również zadziałało.

    Claude nie zrobił skrótu ekranu z tablicą ani nie przeczytał jej kodu HTML. Zapytał przeglądarkę o dostępne narzędzia, znalazł add-task i uruchomił je cztery razy z ustrukturyzowanymi argumentami. Oto ten sam moment widziany z wnętrza przeglądarki.

    Cztery nowe zadania znajdują się teraz na pozycjach od #3 do #6 na tablicy, a panel DevTools (Application, następnie WebMCP) wyświetla wszystkie sześć narzędzi, które obecnie używa strona. Jedno z nich, clear-completed, nie było tam minutę wcześniej, a powód tego wkrótce się ujawni. Trzy zakończenia zadań są rejestrowane po kolei.

    Każde wezwanie jest pokazywane wraz ze swoimi argumentami ({"id":3}, {"id":4} i {"id":5}), a w linii podsumowującej widnieje informacja o trzech wezwaniach łącznie, bez żadnych błędów, anulowań ani wezwań w trakcie wykonywania. Debugowanie WebMCP jest tutaj najszybsze, ponieważ panel pokazuje dokładnie to, co wysłał agent.

    Zatem zdanie wpisane do terminala zamieniło się w cztery strukturyzowane wezwania funkcji w kartce przeglądarki. Następnym pytaniem jest to, co strona musiała zrobić, aby to osiągnąć.

    Dwa sposoby publikacji narzędzia

    Pierwszy w ogóle nie wymaga JavaScripta. Istniejący formularz otrzymuje cztery dodatkowe atrybuty.

    <form id="add-form"
          toolname="add-task"
          tooldescription="Add a new task to the user's task board."
          toolautosubmit>
      <input name="title" required maxlength="80"
             toolparamdescription="Short description of the task to add.">
      <select name="priority"
              toolparamdescription="How urgent the task is.">
        <option value="low">low</option>
        <option value="normal" selected>normal</option>
        <option value="high">high</option>
      </select>
      <button type="submit">Add</button>
    </form>
    

    To formularz jest narzędziem add-task, które Claude wywołał cztery razy. Nazwy pól, atrybuty required oraz opcje <select> są wszystkie odczytywane przez przeglądarkę, która sama tworzy JSON Schema. Agent widzi jedną wymaganą wartość typu ciąg i enum z trzema wartościami, a nikt nie wpisał tego schematu ręcznie. W istniejącej aplikacji jest to prawdopodobnie najprostsze doświadczenie z WebMCP, ponieważ zwykły formularz HTML daje już pewną przewagę. Jedyne, co zostaje dodane, to opis tego, co formularz oznacza dla agenta.

    Jeden szczegół wymaga chwili zrozumienia: ten sam obsługiwacz submit służy zarówno osobie klikającej „Dodaj”, jak i agentowi wywołującemu narzędzie, a zdarzenie wskazuje, który to przypadek.

    $('#add-form').addEventListener('submit', (e) => {
      e.preventDefault();
      const task = addTask(new FormData(e.target).get('title'), /* ... */);
    
      if (!e.agentInvoked) {
        e.target.reset();          // human — clear the box
      } else {
        e.respondWith?.(Promise.resolve(
          text(`Added task #${task.id}: "${task.title}".`)
        ));
      }
    });
    

    Flaga agentInvoked informuje, kto nacisnął przycisk, a respondWith() zwraca wynik agentowi bez opuszczania strony. Istnieje jeden ścieżka kodowa z dwoma wywołującymi, co jest dobrą decyzją projektową, ponieważ nikt nie chce „wersji AI” każdej akcji w aplikacji. Ta sama logika powinna służyć zarówno ludziom, jak i agentom, gdy to ma sens.

    Ścieżka deklaratywna jest chyba mniej interesująca, choć to właśnie ona najprawdopodobniej przyciąga uwagę, ponieważ dobrze się prezentuje i nie wymaga żadnego dodatkowego myślenia. To, czego nie może wyrazić formularz, sprawia, że sytuacja staje się ciekawa. To właśnie druga ścieżka – registerTool – która wygląda bardzo podobnie do tego, co napisałbyś dla serwera MCP w tle.

    await mc.registerTool({
      name: 'list-tasks',
      description: 'List the tasks on the board. Use this before acting so you know the task IDs.',
      inputSchema: {
        type: 'object',
        properties: {
          status: { type: 'string', enum: ['all', 'open', 'done'] },
        },
      },
      annotations: { readOnlyHint: true },
      async execute({ status = 'all' }) {
        const rows = visible(tasks, status);
        return text(rows.map((t) => `#${t.id} [${t.done ? 'x' : ' '}] ${t.title}`).join('\n'));
      },
    });
    

    Przyjrzyj się uważnie temu description. Jest napisany dla modelu, a nie dla programisty, a zdanie takie jak „użyj tego przed podjęciem działań, aby znać ID zadań” wskazuje, kiedy należy go wywołać. Opisy stanowią teraz część interfejsu API, a niejasne z nich powodują, że agenci muszą zgadywać.

    Flaga readOnlyHint sygnalizuje, że narzędzie można bezpiecznie wywołać bez uprzedniego pytania użytkownika. list-tasks i estimate-task ją posiadają. complete-task i clear-completed jej nie mają, ponieważ zmieniają coś w systemie.

    Narzędzia mogą również działać powoli, a agent może zmienić zdanie w trakcie działania. Narzędzie estimate-task celowo czeka trzy sekundy i otrzymuje AbortSignal jako swój drugi argument.

    async execute({ id }, { signal }) {
      const t = findTask(tasks, id);
    
      if (!t) {
        return text(`No task #${id}.`);
      }
    
      await sleep(3000, signal); // throws if the agent aborts
    
      return text(
        `Task #${t.id} is about ${
          t.priority === 'high' ? '2 hours' : '30 minutes'
        }.`
      );
    }
    

    Jeśli uszanujesz ten sygnał, anulowanie zadziała. Jeśli go zignorujesz, narzędzie będzie nadal działać po odejściu agenta.

    Lista narzędzi, która zmienia się podczas otwartej strony

    Najważniejszym powodem rejestracji narzędzi w skrypcie, zamiast wysyłania statycznego manifestu, jest to, że lista może ulegać zmianom w trakcie wykonywania programu. Na tablicy znajduje się narzędzie clear-completed, które usuwa wszystkie zakończone zadania. Ma to sens tylko wtedy, gdy coś jest ukończone, co tłumaczy, dlaczego pojawiło się na wcześniejszym zrzutku ekranu zaraz po oznaczeniu trzech zadań jako zakończonych. Dlatego istnieje tylko w takich momentach.

    let clearCtl = null;
    
    async function syncClearTool() {
      const has = tasks.some((t) => t.done);
    
      if (has && !clearCtl) {
        const ctl = new AbortController();
        clearCtl = ctl;
    
        await mc.registerTool(
          {
            name: 'clear-completed',
            /* ... */
          },
          {
            signal: ctl.signal
          }
        );
      } else if (!has && clearCtl) {
        const ctl = clearCtl;
        clearCtl = null;
    
        setTimeout(() => ctl.abort(), 0); // abort() IS unregister
      }
    }
    

    Nie istnieje funkcja unregisterTool(). Podczas rejestracji przekazuje się AbortSignal, a jego anulowanie usuwa narzędzie. Wtedy układa się cała logika: sygnał, który anuluje trwające wywołanie, jednocześnie cofa uprawnienia, dzięki czemu jeden mechanizm pełni dwie funkcje.

    Gdy zadanie zostanie oznaczone jako zakończone, w liście agenta pojawia się opcja clear-completed; po jej wybraniu narzędzie znika. Agent dowiaduje się o tym poprzez zdarzenie toolchange i nie musi wykonywać żadnych dodatkowych czynności w celu sprawdzenia stanu.

    mc.addEventListener('toolchange', refreshTools);
    

    Zatem lista narzędzi nie jest manifestem publikowanym raz na zawsze. Opisuje to, co aplikacja potrafi robić w danej chwili, w swoim obecnym stanie.

    Jak to różni się od serwera MCP backendowego

    Następnie poproszono Claude Code o zawężenie listy do zakończonych zadań.

    Agent wywołał funkcję filter-tasks z parametrem {"status":"done"}, przycisk „Zakończono” stał się aktywny, a lista pokazywała tylko zadania ukończone. Agent nie pobrał filtrowanej kopii danych – zmienił jedynie widok, który widział użytkownik.

    Server MCP typu backend nie jest w stanie tego zrealizować. Znajdując się po drugiej stronie granicy sieci, pracuje na przechowywanych danych i nie wie nic o tym, co aktualnie pokazuje dowolny ekran. Narzędzia WebMCP funkcjonują wewnątrz karty, dzieląc się jej DOM-em, sesją oraz plikami cookie, dzięki czemu agent i użytkownik widzą ten sam ekran, a każdy z nich może go zmieniać. To zarówno prawdziwa zaleta, jak i poważne ryzyko, które omówione zostanie w osobnym rozdziale poniżej. To również powód, dla którego określanie WebMCP mianem „MCP w przeglądarce” jest niedocenieniem jego możliwości. Miejsce, w którym znajduje się narzędzie, ma znaczenie, ponieważ jest ono powiązane z samym stanem strony, który ogląda użytkownik.

    Łączenie z zewnętrznym agentem

    Panel Pretend Agent pomaga podczas rozwoju, ale ma niewielką wartość, ponieważ jest to strona, która sama siebie wywołuje. Prawdziwy test wymaga czegoś poza przeglądarką, co może widzieć tylko to, co raportuje getTools(). Dlatego istnieje agent.mjs – mały narzędzie wiersza poleceń wykorzystujące elementy protokołu Chrome DevTools i nieposiadające żadnych zależności, ponieważ Node 22 ma wbudowany globalny WebSocket. Zgodnie ze swoją konstrukcją może ono widzieć tylko to, co raportuje getTools(), i działać wyłącznie poprzez executeTool(), bez możliwości przeszukiwania DOM-u.

    node agent.mjs list
    node agent.mjs call add-task '{"title":"Ship the demo","priority":"high"}'
    

    Te dwa polecenia wyświetlają listę narzędzi, a następnie wywołują add-task z tytułem i priorytetem. Konfiguracja użyta do stworzenia skrínówek idzie o krok dalej. Claude Desktop, Claude Code oraz ChatGPT używają protokołu MCP, a nie WebMCP, więc mcp-bridge.mjs pełni rolę adaptera – przy tym adaptera dość prostego, ponieważ protokoły są niemal identyczne: tools/list odpowiada getTools(), a tools/call odpowiada executeTool(). Claude Code łączy się z tym protokołem za pośrednictwem pliku .mcp.json.

    {
      "mcpServers": {
        "webmcp-board": {
          "command": "node",
          "args": ["C:\\projects\\web-mcp-demo\\mcp-bridge.mjs"],
          "env": { "PAGE_URL": "https://tusharkanjariya.github.io/web-mcp-demo/" }
        }
      }
    }
    

    Cały łańcuch wygląda więc tak: Claude Code komunikuje się z mostkiem za pomocą MCP, mostek komunikuje się z Chrome za pomocą CDP, a Chrome wywołuje narzędzia zarejestrowane na stronie. To cztery etapy komunikacji, a strona na końcu nie może stwierdzić, jaki klient znajduje się po drugiej stronie.

    Claude Code
        ↓
    MCP
        ↓
    mcp-bridge.mjs
        ↓
    Chrome DevTools Protocol
        ↓
    WebMCP
        ↓
    my task board
    

    Kolejna wygoda: narzędzie uruchamia własny Chrome, jeśli na porcie debugowania nie ma odpowiedzi, i otwiera stronę, gdy karta nie istnieje. Klient MCP może uruchomić wszystko od zera.

    Odrzucenie

    Następnie poproszono agenta o usunięcie pojedynczego zadań.

    Górna połowa zrzutu ekranu pokazuje wcześniejszą prośbę o filtrowanie. Dolna połowa to najciekawsza część: Claude stwierdził, że na tym panelu nie istnieje narzędzie delete-task, że jedyne dostępne usunięcie to clear-completed, które usunęłoby również zadania nr 2, 3, 4 i 5, i że nie zamierza tego zrobić.

    Odmowę spowodowało nie co innego jak zabezpieczenie, instrukcja systemowa czy warstwa bezpieczeństwa. Możliwość usunięcia pojedynczego zadań po prostu nie istniała, a agent to zauważył. Błędem byłoby przypisywanie zbyt wielkiego znaczenia jednej rozmowie w aplikacji testowej. Mimo to zmienia to sposób postrzegania problemu. Agent sterujący stroną za pomocą pikseli i współrzędnych znalazłby coś przypominającego funkcję usuwania i spróbowałby jej użyć, ponieważ agenci do skrapowania ekranu mają do dyspozycji jedynie improwizację. Ten agent przeliczył swoje sześć narzędzi, zobaczył, że żadne z nich nie służy do usuwania zadań, rozpoznał uboczne skutki najbliższej opcji i zatrzymał się, by zapytać.

    Powierzchnia narzędzi stanowiła granicę. Nikt nie napisał zasady zakazującej usuwania elementów. Strona po prostu nigdy nie oferowała możliwości usunięcia jako czegoś, co mogłoby się zdarzyć, a to wystarczyło jako dowód, mimo że WebMCP nie czyni agentów magicznie bezpiecznymi.

    Gdzie Chrome i specyfikacja się różnią

    Próba uruchomienia tego oprogramowania ujawniła różnice pomiędzy dokumentacją a przeglądarką, a ich rozwiązanie zajęło całe popołudnie. Trzy z nich dotyczą kształtu danych.

    • Argumenty dla executeTool(): specyfikacja opisuje obiekt, ale Chrome 151 oczekuje ciągu JSON, a obiekt powoduje błąd Failed to parse input arguments.
    • RegisteredTool.inputSchema: w specyfikacji jest określony jako obiekt, ale Chrome zwraca ciąg JSON, więc należy go najpierw przetworzyć, zanim można odczytać properties.
    • To, co zwraca executeTool(): specyfikacja mówi o DOMString, co jest prawdą, ale w rzeczywistości jest to zserwowany obwój {content:[…]}, który musi zostać dwukrotnie rozwinięty, aby uzyskać tekst.

    To wszystko nie stanowi problemu, gdy już się tego nauczy. Dwa problemy, które faktycznie sprawiły kłopoty, były błędami związanymi z cyklem życia aplikacji i pojawiają się tylko wtedy, gdy rzeczywisty agent obsługuje stronę.

    Wywołanie form.reset() podczas trwania wysyłki inicjowanej przez agenta anuluje wywołanie narzędzia z komunikatem Tool execution cancelled by a form reset. Zupełnie zwykły obsługiwacz, który po wysłaniu danych opróżnia pole wejściowe, jak to robi większość, powodował awarię każdego wywołania add-task przez agenta. Zadanie było tworzone, ale odpowiedź nigdy nie przychodziła, dlatego obsługiwacz pokazany wcześniej służy tylko do resetowania po wysyłce danych przez człowieka.

    W wersjach przed Chrome 153 usunięcie narzędzia anulowało również wszystkie jego aktualnie trwające wywołania. Nie stanowiło to problemu, dopóki narzędzie samo się nie usuwało w wyniku pomyślnego wykonania. Funkcja clear-completed usuwa każde zakończone zadanie, więc nic nie pozostaje do zrealizowania, a narzędzie się wycofuje. W wersji 151 takie przerwanie powodowało, że odpowiedź narzędzia była odcinana, zanim została zwrócona. Rozwiązaniem jest setTimeout(() => ctl.abort(), 0): odroczenie przerwania o jeden tick pozwala najpierw na zakończenie wywołania. Jest to zrozumiałe i skuteczne, ale odroczenie procesu wycofywania o jeden tick to typ poprawki, którą warto ponownie przeanalizować po kilku nowych wersjach Chrome.

    Dostarczanie demo

    Demo jest w pełni statyczne, więc GitHub Pages może je serwować bez zmian, a HTTPS zapewnia bezpieczny kontekst wymagany przez WebMCP. W ten sposób wszyscy otrzymują działającą tablicę z zadaniami, ale nie działające WebMCP, ponieważ odwiedzający, którzy nie ustawili odpowiedniej flagi, nadal widzą, że document.modelContext jest niezdefiniowany. Aby to naprawić, konieczny jest token do testowania pochodzenia w sekcji <head>, zarejestrowany jako token pierwszej strony, ponieważ Chrome odrzuca tokeny stron trzecich umieszczone w tagu meta. W czystym profilu bez żadnych flag modelContext zwracał wartość „object” wraz ze wszystkimi sześcioma narzędziami. Okres próbny trwa do wersji Chrome 156.

    Pytanie bezpieczeństwa bez odpowiedzi

    Narzędzia WebMCP działają w zakładce z zalogowanym użytkownikiem. To jest cały sens, ale jednocześnie cały problem.

    Specyfikacja zawiera pole untrustedContentHint, które jest jedynie wskazówką. Kwestia sposobu radzenia sobie z iniekcją poleceń pozostaje nierozwiązana, a żadna część tej API nie pełni funkcji granicy autoryzacji. Jeśli tekst kontrolowany przez atakującego może zostać wyświetlony na stronie i agent go odczyta, readOnlyHint nie może w tym pomóc.

    Most może być również udostępniany przez HTTP za pośrednictwem tunelu, aby konektory ChatGPT mogły do niego dotrzeć. Działa to, ale należy dokładnie to przemyśleć przed podjęciem takiej decyzji, ponieważ tunel ujawnia endpoint bez autoryzacji, który umożliwia uruchamianie narzędzi w otwartym karcie przeglądarki po zalogowaniu każdemu, kto odgadnie adres. Dwadzieścia minut eksperymentowania jest w porządku, natomiast pozostawianie go włączonego przez całą noc – nie.

    Próba użycia w własnej aplikacji

    Utrzymywacze aplikacji internetowej mogą ocenić API w ciągu popołudnia, ponieważ jest niewielkie. Wybierz dowolny istniejący formularz, dodaj do niego atrybuty toolname i tooldescription, a następnie otwórz panel WebMCP w DevTools i zobacz, jak pojawia się narzędzie. Około dziesięciu minut takiej pracy nauczy więcej niż kolejna godzina czytania.

    Kluczowe jest to, że chodzi tu o coś więcej niż tylko składnię. Szczere opisanie tego, co potrafi twoja aplikacja, stało się częścią samego produktu, a nie dokumentacją pisaną później. Panel nie oferował funkcji usuwania pojedynczych zadań, więc agent nigdy żadnego nie usunął. To, co zwraca getTools(), określa, jak agent postrzega możliwości twojej aplikacji, a to postrzeganie stopniowo przeradza się w sam interfejs. W demonstracji użyto sześciu narzędzi z trzech plików bez żadnych zależności, więc zastanów się, co twoja własna strona powiedziałaby o sobie. Aby to odtworzyć, włącz flagę chrome://flags/#enable-webmcp-testing, a następnie wykonaj polecenie node agent.mjs list. Otrzymanie sześciu narzędzi jako odpowiedzi oznacza, że komunikujesz się z stroną internetową w taki sam sposób, w jaki robiłby to agent.

    Szybkie odpowiedzi

    Czym jest WebMCP? To proponowana API dla przeglądarek, za pomocą której strona może publikować swoje własne funkcje jako narzędzia dostępne dla agenta AI, wykorzystując document.modelContext. Agenci mogą bezpośrednio korzystać z tych narzędzi, unikając w ten sposób przeszukiwania DOM-u oraz koordynacji kliknięć.

    W czym różni się od zwykłego serwera MCP? Serwery backendowe działają poza granicami sieci i przetwarzają przechowywane dane. Narzędzia WebMCP działają wewnątrz karty, więc mogą zmieniać to, co widzi użytkownik, a także ponownie wykorzystywać sesję i uprawnienia strony. Wywołanie filter-tasks widocznie zmieniło układ na tablicy.

    Jak strona rejestruje narzędzie? Można dodać atrybuty toolname i tooldescription do istniejącego formularza i pozwolić przeglądarce wywnioskować schemat na podstawie pól, albo wywołać funkcję document.modelContext.registerTool() z nazwą, opisem, schematem JSON oraz funkcją execute. Formularze nadają się do prostych działań, natomiast registerTool obejmuje wszystko, czego formularz nie może wyrazić.

    Czy wymagana jest flaga? Na razie tak. Włącz flagę i ponownie uruchom Chrome, albo uruchom go z parametrem --enable-features=WebMCP. Dla odwiedzających, którzy nie włączyli tej flagi, zadziała token próbny pierwszostronnej domeny w sekcji <head> strony.

    Czy Claude Desktop lub ChatGPT mogą korzystać z tych narzędzi? Nie same w sobie, ponieważ używają MCP zamiast WebMCP. Mały adapter mapuje tools/list na getTools(), a tools/call na executeTool(). Ten konkretny adapter składa się z około 130 linii kodu, nie wymaga żadnych zależności i działa poprzez stdio dla lokalnych klientów.

    Czy jest to bezpieczne? Pytanie pozostaje otwarte. untrustedContentHint oraz readOnlyHint to jedynie wskazówki – żadne z nich nie określa granic uprawnień, a specyfikacja nie rozstrzygnęła jeszcze kwestii iniekcji poleceń. Należy projektować interfejs narzędzi przy założeniu, że agent może zostać przekonany do wywołania czegokolwiek, co udostępniamy.

    Literatura pokrewna

  • Serena MCP Server: Edycja kodu z uwzględnieniem symboli dla asystentów AI — Konfiguruj Serena przy użyciu Dockera i SSE, aby Claude Code, VS Code i OpenCode mogły korzystać z wyszukiwania symboli wspieranego przez LSP, bezpiecznego przemianowywania nazw oraz trwałej pamięci przy mniejszej liczbie tokenów.