Agent, který mění webovou aplikaci, se na ni musí podívat. Otázka je, kolik tokenů ten pohled stojí a co při něm vidí.

AI agent, který upraví komponentu, stylesheet nebo routu, má ve chvíli, kdy skončí, problém: nedokáže poznat, jestli je výsledek správně. Může si kód přečíst zpátky a uvažovat nad ním, a přesně tak sebejistý agent dodá kartu, která na 320 pixelech přetéká, focus ring, který už neodpovídá hoveru, nebo lištu, která načte Google Analytics dřív, než kdokoli klikl na přijmout. Jediná poctivá kontrola je ta, kterou dělá vývojář: otevřít stránku a podívat se, zkusit interakci, přečíst konzoli, sledovat síť. Agent potřebuje prohlížeč.

To, jak mu ho dáte, rozhoduje o tom, kolik každá kontrola stojí a kolik toho vidí. Tento článek porovnává tři způsoby, které jsem používal, obhajuje ten, který vyhrál, a prochází, co všechno odemyká. Úvaha je nezávislá na agentovi. Já používám Claude Code, takže příklady jsou z Claude, ale ten samý server mluví přes stejný protokol s Codexem, Gemini CLI, Cursorem i Copilotem.

Tři způsoby, jak dát agentovi oči

Jednorázový automatizační kód. Agent napíše skript pro Playwright nebo Puppeteer, spustí ho, přečte screenshot a skript smaže. Každá kontrola je malý program: spustit prohlížeč, přejít na URL, nastavit viewport, najít element podle selektoru, udělat screenshot nebo vypsat rozměr. Když byl selektor špatně nebo stránka nebyla připravená, program upraví a spustí znovu.

Vlastní harness. Skript napíšete jednou a pořádně: CLI, které vezme URL, viewport, téma a element a vypíše to, co agent obvykle chce. To je lepší a většina týmů tam skončí po měsíci s první variantou, jenže odpovídá jen na otázky, které jste předvídali, když jste ho psali, a vyžaduje údržbu jako každý jiný nástroj.

Prohlížeč vystavený jako nástroje. Chrome DevTools MCP je server protokolu Model Context Protocol od týmu Chrome DevTools, který řídí skutečný Chrome přes DevTools protokol a vystavuje ho jako typované nástroje: navigovat, udělat snapshot stránky, kliknout, vyplnit, udělat screenshot, vyhodnotit skript, vypsat síťové požadavky, přečíst konzoli, nahrát performance trace, spustit Lighthouse. Agent zavolá nástroj, dostane strukturovaný výsledek a rozhodne o dalším volání. Na to, aby se podíval na stránku, nepíše žádný kód.

Argument tokeny

Jednorázový skript je drahý způsobem, který se snadno přehlédne, protože každý jednotlivý krok vypadá levně.

Agent skript vygeneruje, čtyřicet až osmdesát řádků, které musí vyprodukovat token po tokenu a za které pak platíte tím, že zůstávají v kontextu po zbytek úkolu. Když bylo něco špatně, selektor, čekání, viewport, upraví ho a spustí znovu a v kontextu teď leží obě verze. Další kontrola je jiná stránka nebo jiný stav, takže potřebuje jiný skript. Během jedné session, která ověřuje redesign ve dvou tématech, dvou jazycích a třech viewportech, platíte za tucet malých programů a jejich výstupů, z nichž si žádný nenecháte.

Druhým nákladem je screenshot na konci každého skriptu. Obrázek se čte jako obrazové tokeny a agent, který má jen screenshoty, jich chce hodně, protože screenshot je jediný způsob, jak cokoli „vidí“.

MCP server mění obojí. Každá kontrola je volání nástroje: hrstka tokenů v argumentech, žádný kód a strukturovaný výsledek. Výchozí způsob, jak se podívat na stránku, není screenshot, ale snapshot: take_snapshot vrátí accessibility tree stránky jako text, každý interaktivní element s krátkým id, jeho rolí, názvem a stavem. To je pár set až pár tisíc tokenů za celou stránku, zatímco DOM by byl desítky tisíc a screenshot je obrázek. Agent ho čte tak, jak čte cokoli jiného, vybere element podle id a provede akci přes click nebo fill. O screenshot požádá jen tehdy, když opravdu potřebuje oči. Rozměry, které by skript vypsal, bounding box, vypočtený styl, počet, přijdou z evaluate_script jako JSON, jedním voláním.

S tím klesá i počet obrátek. Skript je dávka: běží až do konce a agent vidí výsledek až potom, takže špatný předpoklad v polovině stojí celý další běh. Volání nástroje je jeden krok a chyba se zachytí u toho kroku, ne na konci.

Poctivé srovnání také říká, kde skripty pořád vyhrávají.

V mém repozitáři instrukce pro agenta říkají ověřovat vizuální změny nejdřív přes Chrome MCP, s náhradou v podobě vlastního Playwrightu repozitáře, když je MCP nedostupné. Ta náhrada se použila a pokaždé to byla pomalá, drahá cesta.

Jak to nastavit

Server běží na Node LTS a potřebuje aktuální stabilní Chrome. Jeden příkaz ho zaregistruje pro Claude Code, a to pro aktuálního uživatele, ne jen pro jeden projekt:

Bashclaude mcp add chrome-devtools --scope user npx chrome-devtools-mcp@latest

Pro kteréhokoli jiného klienta má konfigurace stejný tvar, příkaz a jeho argumenty:

JSON{ "mcpServers": { "chrome-devtools": { "command": "npx", "args": ["-y", "chrome-devtools-mcp@latest"] } } }

Nebo ruční krok přeskočte. Agent, který umí číst dokumentaci, si umí nainstalovat vlastní nástroje, a je to dobrá první věc, o kterou čerstvého agenta požádat.

Takto spuštěný server při prvním volání nástroje nastartuje vlastní Chrome s vlastním profilem a ten profil pak používá dál. Dva přepínače stojí za to znát od prvního dne: --isolated dá každému běhu dočasný profil, který se po skončení smaže, správná volba pro cokoli, co nechcete mít zapamatované, a --viewport=1280x720 ušetří agentovi volání resize_page na začátku každé session. Když je kontext těsný, --screenshotMaxWidth a --screenshotFormat=jpeg zmenší výstup toho jediného drahého nástroje.

Jak vypadá session

Reference uvádí jedenáct skupin nástrojů; ověřovací session žije v šesti z nich: navigace, vstup, emulace, síť, ladění a výkon. Středem smyčky je snapshot. Každý vstupní nástroj adresuje elementy podle id z posledního take_snapshot, emulate nastaví viewport, barevné schéma a škrcení a evaluate_script odpoví na cokoli, co strom vyjádřit neumí. Snapshot, akce, snapshot.

Tři prompty ze session s Claude, která ověřuje přepracovanou kontaktní sekci, a nástroje, na které se promění:

Claude zavolá new_page, emulate, take_snapshot a odpoví ze stromu. Zatím žádný screenshot.

hover, evaluate_script s malou funkcí čtoucí getComputedStyle, click na pole, press_key Tab, znovu evaluate_script. Dva výsledky v JSON, jedno porovnání. Tohle je kontrola, která zachytí focus styl, co se rozešel s hover stylem, a v kontextu je to tucet řádků textu, ne dva screenshoty.

take_screenshot s id sekce. Jeden obrázek, když je obrázek správná odpověď.

Profil, ve kterém jste přihlášeni

Tohle je případ, který mění to, co agent dokáže, ne jen to, jak levně to dokáže.

Server si drží vlastní profil Chrome na disku, ve výchozím stavu pod ~/.cache/chrome-devtools-mcp/chrome-profile. Cokoli v tom Chrome uděláte, zůstane: přihlaste se jednou a každá další session je přihlášená také. Agent tak může otevřít náhled rozepsaného článku v CMS a zkontrolovat, že se nový embed vykreslí, podívat se na chráněné staging prostředí nebo projít admin flow, to vše jako vy, aniž by se jediný přihlašovací údaj objevil v konverzaci nebo ve skriptu.

Dostat se tam lze třemi způsoby, seřazenými podle toho, kolik ze svého skutečného prohlížeče předáváte. Vlastní profil serveru je výchozí: spusťte ho jednou, přihlaste se k tomu, co agent potřebuje, zavřete ho a další volání nástroje ho použije znovu. Tenhle používám já, vyhrazený Chrome, který zná CMS, Storybook na stagingu a analytickou property, a nic jiného. Připojení k Chrome, který jste spustili vy, přes --browserUrl=http://127.0.0.1:9222: Chrome spustíte s --remote-debugging-port=9222 a s jiným než výchozím --user-data-dir a přesně určujete, který profil vystavujete. Připojení k běžícímu Chrome, přes --autoConnect: Chrome 144 a novější umí vystavit remote debugging pro běžící instanci (chrome://inspect/#remote-debugging) a server se připojí k Chrome, který už máte otevřený, i se všemi záložkami. Nejpohodlnější možnost a ta, nad kterou je třeba přemýšlet nejvíc.

Protože přihlášený profil znamená, že agent jedná jako vy. Pár přepínačů to drží na uzdě:

  • --allowedUrlPattern a --blockedUrlPattern ohraničí agenta na hosty, které úkol potřebuje.

  • --redactNetworkHeaders začerní citlivé hlavičky, mimo jiné cookies a authorization, v tom, co vrací get_network_request, takže session token nikdy neskončí v přepisu.

  • --javascriptEvaluation=false odebere skriptovací nástroje pro session, které potřebují jen číst.

Případy, které se vyplatí

Ověření designu v nepohodlných velikostech. Kontrola, kterou vývojář přeskočí, protože stojí osm kliknutí: jazyk s delšími slovy, tmavé téma, spodní hranice 320 pixelů. Agent třikrát spustí emulate, pokaždé udělá snapshot a screenshot jen u té, která se zalomila.

Audity souhlasu a analytiky. Otevřete web v čerstvém izolovaném kontextu prohlížeče, který new_page na požádání vytvoří, takže běh začíná s prázdnou dózou na cookies. Přijměte v liště jednu kategorii a pak list_network_requests filtrované na analytické hosty. Agent přečte parametry souhlasu z odeslaných hitů, přes evaluate_script zkontroluje localStorage, souhlas odvolá a potvrdí, že úložiště je zase prázdné. Tohle je kontrola, která na mém vlastním webu našla tag střílející před souhlasem, a je to přesně ten druh vícekrokové sondy závislé na stavu, který jednorázový skript dělá špatně.

Reprodukce nahlášené chyby. Kroky z ticketu se stanou voláními navigate_page, click a fill, list_console_messages vrátí chybu i s jejím stackem a get_css_styles vysvětlí, proč element vypadá špatně, tím, že vypíše pravidla, která se skutečně uplatnila, v pořadí kaskády. Agent dojde k opravě s důkazy místo s odhadem.

Výkon s připojenou příčinou. performance_start_trace s reloadem nahraje trace, která se vrátí s pojmenovanými poznatky, rozpad LCP, požadavky blokující vykreslení, posuny layoutu i s elementy, které se posunuly, a performance_analyze_insight jde do hloubky u každého z nich. Přidejte emulate se škrcením CPU a sítě a agent uvidí stránku tak, jak ji vidí průměrný telefon ve vlaku.

A když je flow ověřené, --experimentalScreencast z něj udělá krátké video pro pull request, lepší podklad k review než odstavec, který ho popisuje.

Na co přijdete, až to spustíte

Pár věcí z mých vlastních poznámek, nezávislých na agentovi, protože jsou to fakta o Chrome, ne o Claude:

  • resize_page mění velikost sdíleného okna, takže změní každou otevřenou záložku. Nejmenší viewport dělejte jako poslední a velikost pak vraťte.

  • Záložka na pozadí zmrazí CSS animace. Element změřený v záložce, která není vepředu, je uprostřed keyframe; než měříte cokoli, co se hýbe, přeneste záložku dopředu pomocí select_page.

  • Profil si pamatuje zoom stránky. Můj měl localhost na 125 procentech, což z emulovaného viewportu 320 pixelů udělalo 256 CSS pixelů a vyrobilo falešná zalomení. Emulujte širší a než důvěřujete úzkému průchodu, přečtěte innerWidth.

  • Dvě volání nástrojů vystřelená paralelně na studený server se obě pokusí spustit Chrome a to druhé selže na zámku profilu toho prvního. První volání v session je jedno volání.

  • localhost se může přeložit na IPv6 a skončit u jiné aplikace, která tam poslouchá. Směrujte agenta na 127.0.0.1.

Nic z toho není důvod server nepoužívat. Jsou to věci, které si tým zapíše jednou, a agent s pamětí si je zapíše za vás.

Kam to vede

Prohlížeč nikdy nebyl ta těžká část dávání očí agentovi. Těžká část je cena každého pohledu a to, co každý pohled vidí. Jednorázový skript dělá z každého pohledu program a program vidí jen to, co jste mu řekli vypsat. Prohlížeč vystavený jako nástroje dělá z každého pohledu volání, nechá agenta číst stránku jako text a žádat o pixely jen tehdy, když na pixelech záleží, a dává mu síť, konzoli, trace i vaše vlastní přihlášené session na jedno volání. Pro průzkumné ověřování závislé na stavu, které následuje po každé skutečné změně, je to rozdíl mezi agentem, který hlásí, co udělal, a agentem, který vám to ukáže.