web-ui-tester
web-ui-tester
Ein MCP-Server, der einer KI erlaubt, reale Webseiten schnell zu steuern und zu inspizieren – über Browsersitzungen, die zwischen Tool-Aufrufen aktiv bleiben.
Zwei Dinge machen ihn schnell. Seiten werden als Accessibility-Baum mit Element-Refs dargestellt, nicht als Screenshots oder rohes HTML, damit das Modell Dinge finden und anklicken kann, ohne Kontext für Markup zu verbrauchen oder auf Bilderkennung zu warten. Sitzungen bleiben erhalten – Cookies, Seitenzustand und Verlauf überdauern Aufrufe, sodass eine lange Interaktion aus einer Reihe günstiger Schritte besteht statt aus wiederholten Kaltstarts.
Er bringt außerdem Diagnose-Möglichkeiten auf DevTools-Niveau mit – Konsole, Netzwerk mit Antwort-Bodies, JS-Auswertung, berechnete Styles – damit die KI herausfinden kann, warum etwas kaputt ist, und nicht nur, dass es kaputt ist.
Schnellstart
claude mcp add web-ui-tester -- npx -y web-ui-testerMit einem Schlüssel für den integrierten Agenten (siehe [run_task](#the built-in agent)):
claude mcp add web-ui-tester \
-e GOOGLE_GENERATIVE_AI_API_KEY=your-key \
-- npx -y web-ui-testerOder in der Konfigurationsdatei eines beliebigen MCP-Clients:
{
"mcpServers": {
"web-ui-tester": {
"command": "npx",
"args": ["-y", "web-ui-tester"],
"env": { "GOOGLE_GENERATIVE_AI_API_KEY": "your-key" }
}
}
}Chromium kommt von Playwright. Falls es noch nicht installiert ist:
npx playwright install chromiumSo funktioniert eine Sitzung
browser_start → sessionId, kept alive across calls
browser_navigate → page state + snapshot with [ref=eN] handles
browser_click ref=e12 → act on what the snapshot showed you
browser_snapshot → fresh refs after the page changes
browser_close → done (or let it idle out after 30 minutes)Alles nach browser_start verwendet diese sessionId. Der Snapshot ist das zentrale Konzept:
- generic [ref=e1]:
- heading "Signup" [level=1] [ref=e2]
- textbox "Name" [ref=e5]:
- /placeholder: Your name
- combobox "Plan" [ref=e7]
- button "Create account" [ref=e10]
- link "Go to second page" [ref=e12] [cursor=pointer]:
- /url: /second.htmlDiese Refs gehen dann direkt in browser_click, browser_type und die übrigen Tools ein. Sie gehören zu dem Seitenzustand, der sie erzeugt hat: Nach einer Navigation oder einer DOM-Änderung erneut einen Snapshot erstellen. Wenn ein Tool eine Ref als nicht mehr gültig meldet, einen neuen Snapshot erstellen, statt erneut zu versuchen – die Meldung weist ausdrücklich darauf hin.
Die Tools, die Elemente adressieren, akzeptieren auch css oder role + name, wenn der Selektor bereits bekannt ist und ein Snapshot übersprungen werden soll.
Tools
Session – browser_start (Optionen: userAgent, viewportWidth, viewportHeight, headless, baseUrl, url, model), browser_list, browser_close.
Interaktion – browser_navigate, browser_click, browser_type, browser_press_key, browser_hover, browser_select_option, browser_scroll, browser_wait_for, browser_go_back, browser_handle_dialog.
Aktionen melden zurück, was sie verursacht haben: Navigation, neue Konsolenfehler, Request-Zähler und ein eventuell erschienener Dialog kommen mit dem Ergebnis zurück. Ein Klick, der still etwas kaputt macht, sieht dadurch nicht wie ein Erfolg aus.
Bei Dialogen ist eine Sache zu beachten. Ein alert/confirm/prompt blockiert die Seite, bis er beantwortet wird. Die Aktion, die ihn geöffnet hat, kann ihn daher nicht gleichzeitig beantworten – ein unbeantworteter Dialog wird automatisch verworfen, statt den Klick zu blockieren, und das Ergebnis sagt das auch. Um einen Dialog zu bestätigen oder ein prompt auszufüllen, wird browser_handle_dialog vor der auslösenden Aktion aufgerufen; die Antwort ist dann für den nächsten Dialog scharf.
Inspektion – browser_snapshot (per Element eingrenzbar, über depth begrenzt, interactiveOnly, mit offset umseitig), browser_query (find via role/name, Text oder CSS – gibt Refs und Zustand zurück), browser_read_text (angezeigter Text der Seite oder eines Teilbaums), browser_snapshot (verfügbar, aber der Baum ist normalerweise das bessere Werkzeug).
Diagnose – browser_console (Messages plus uncaught errors mit Stacks), browser_network (Status, Größen, Timings), browser_request_detail (Header, zeitliche Auflösung, Anforderungs- und Antwort-Bodies), browser_evaluate (JavaScript auf der Seite ausführen), browser_inspect_element (berechnete Styles, Box-Modell, Formularzustand).
Jedes Ergebnis ist durch ein Zeichenbudget begrenzt, und die umfangreichen (browser_snapshot, browser_read_text, Bodies) lassen sich über offset blättern, statt still abgeschnitten zu werden.
Der integrierte Agent
run_task übergibt eine Sitzung an ein schnelles Modell, das den Browser selbst steuert und berichtet:
run_task(sessionId, "Log in as demo@example.com / hunter2 and check the
dashboard loads without errors")Auf das Reporting kommt es an. Es liefert ein strukturiertes Ergebnis, nicht nur Fließtext:
status: success
model: google:gemini-flash-lite-latest
Logged in and opened the dashboard. The revenue widget rendered empty.
findings (3):
[error] Request failed: GET 500 [observed by the harness]
where: https://app.example.com/api/revenue
evidence: HTTP 500
[error] Console exception on the page [observed by the harness]
where: app.js:214:9
evidence: TypeError: Cannot read properties of undefined (reading 'total')
[warning] The revenue widget shows no empty state, just blank space
where: #revenue-card
evidence: card is present but contains no textFindings stammen aus zwei Quellen, und der Unterschied ist wichtig. Der Agent ruft report_finding parallel zum Lauf auf – so liefert ein Lauf, das sein Schrittelimit erreicht, trotzdem all bisher gefundenen. Außerdem zeichnet das Harness jeden Konsolenfehler, jeden fehlgeschlagenen Request und jeden Dialog während des Laufs auf und meldet diese unerabhängig davon, ob der Agent sie erwähnt, markiert mit [observed by the harness]. Ein Modell, das einen 500erJugend oder eine Exception nicht erwähnt, kann ihn damit nicht verbergen.
Dieselbe Meldung wird als structuredContent gegen ein deklariertes Output-Schema zurückgegeben, sodass eine aufrufende KI über findings[].severity verzweigen kann, statt Text zu parsen. Eine Aufgabe kann erfolgreich sein und trotzdem Findings enthalten; success reflequeert, ob die Aufgabe erledigt ist, nicht die Sau sauber oder die Seite.
Das ist der einzige Teil, der einen API-Schlüssel benötigt. Standardmäßig wird der Latenz wegen Gemini Flash Lite verwendet; Anthropic funktioniert ebenfalls:
Standardmodell | Schlüssel | |
|
| |
Anthropic |
|
|
WUT_MODEL setzen, um zu wählen (anthropic, oder google:gemini-flash-latest, oder jede beliebige provider:modelId). Eine Sitzung kann das eigene über model in browser_start außer Acht, ein einzelner Aufruf über model in run_task. Jedes andere Tool funktioniert ohne Schlüssel.
HTTP-Modus
web-ui-tester --port 7399
claude mcp add --transport http web-ui-tester http://127.0.0.1:7399/mcpIn diesem Modus leben die Browsersitzungen im längerlaufenden Server statt im Client-eigenen Prozess, sie überleben also Client-Neustarts und Wiederverbindungen – reconnecte, danach derselbe sessionId, und die Seite ist noch da. GET /health meldet Sitzungs- und Verbindungszahlen.
Der Server bindet standardmäßig an 127.0.0.1, einem DNS-Rebinding-Schutz in carries. --host erweitert das, und der Server mahnt, wenn man das tut: Es gibt keine keine Authentifizierung, und jeder, der den Port erreichen kann, hat damitein Browser and JavaScript-Bots access erlangt. Hänge ihn hinter einen Proxy oder eine Firewall.
Konfiguration
| Variable | Standard | Zweck |
| ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| WUT_MODEL | google:gemini-flash-lite-latest | Agent-Modell für run_task, als provider[:modelId] |
| GOOGLE_GENERATIVE_AI_API_KEY | – | Schlüssel für Gemini |
| ANTHROPIC_API_KEY | – | Schlüssel für Anthropic |
| WUT_USER_AGENT | AITester/1.0 | Standard-User-Agent für neue Sitzungen |
| WUT_HEADLESS | true | Standardmodus Headless |
| WUT_IDLE_TIMEOUT_MS | 1800000 | Sitzungen schliessen, die eine so lange Zeit ungenutzt sind |
| WUT_MAX_OUTPUT_CHARS | 15000 | Zeichenlimit pro Tool-Ergebnis |
| WUT_ACTION_TIMEOUT_MS | 5000 | Zeitüberschreitung Mood für eine einzelne Elementaktion |
| WUT_AGENT_MAX_STEPS | 20 | Standard-Schrittbudget für run_task |
| WUT_EXECUTABLE_PATH | – | Explizites Chromium-Binary |
| PLAYWRIGHT_BROWSERS_PATH | – | Ort, an dem Playwright nach Browsern sucht |
CLI-Optionen: --port, --host, --headless / --no-headless, --idle-timeout, --version, --help.
Falls die von Playwright erwartete Chromium-Version nicht installiert ist, aber eine andere vorhanden ist, findet der Server sie auch und verwendet sie, dass er danach oft nicht scheitert – nützlich in vorgefertigten Containern. WUT_EXECUTABLE_PATH aufgehoben die Suche vollständig.
Entwicklung
npm install
npm run build
npm test # agent loop (mocked model) + full end-to-end suite
npm run typechecknpm test führt die Agentenschleife gegen ein Mock-Modell aus und testet dazu den gebauten Server als echten MCP-Client über beide Transports against a local fixture App – abgedeckt sind Refs, stale-ref-Handling, Diagnosistics, Session-Persistenz über Reconnects und das Freigeben inaktiver Sitzungen. npm run test:agent:live testet zusätzlich run_task against a realer Provider und überspringt den Test, wenn kein Schlüssel eingerichtet ist.
Lizenz
MIT
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Reliable web access for AI agents: smart HTTP, rotating proxies, and full-browser rendering.
Live browser debugging for AI assistants — DOM, console, network via MCP.
Browser-backed QA with evidence and fix-ready reports for coding agents.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/hofmeister/web-ui-tester'
If you have feedback or need assistance with the MCP directory API, please join our Discord server