open
Open URL as numbered page text; act by #number.
urlrequired
io.github.perzianhqPublished by GitHub account perzianhqv0.1.13Updated Nov 6, 2026
The web as short, numbered text for AI agents: a lean browser interface over Playwright.
Mantis is a local Playwright-based browser MCP server that lets an assistant browse the web as short, numbered text instead of screenshots.
Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.
Follow the launch instructions in the repository.
Lets AI agents browse the web as short, numbered text instead of screenshots.
perzian.dev/mantis · by Perzian
It works with Claude Code, Codex, Cursor or your own agent as an MCP server. Install in two commands.
Windows, Linux servers and other agents: SETUP.
One real task (Luna, each tool’s median run of 5 by input tokens, replayed): about half the time, over 3.5x fewer input tokens, less than half the calls. Across all 5 runs: 3-5x fewer tokens, about half the time, 11-12 calls vs 21-29. This is a selected example from 16 long tasks; medians across all 16 are in Results. Full video.
Security and threat model: SECURITY.md.
Mantis vs the accessibility tree (Playwright MCP) on public sites, gpt-6-luna and claude-haiku-5-5. Every cell is a per-run median; time is end-to-end wall time per run:
0.1.11: headline numbers are 0.1.9's; later builds checked on Dickens (Luna, Haiku) and the capability-v1 local set.
Long tasks (correct: 14 keyed tasks, 42 runs per cell; medians: all 16 tasks, 48 runs per cell; both approaches run in the same session):
Short tasks (30 tasks, 90 runs per cell; tree and screenshot columns are the earlier 20261026 run):
Versus the accessibility tree:
Versus screenshots:
Caveats:
ask_human, which needs a display.MIT
Source: README.md at commit 74f61b0
Open URL as numbered page text; act by #number.
urlrequiredNumbered text; act by #number. ~"x" names are guesses. "Same as before" retains #numbers; region/full/fresh expands it; full is paged with offset. Verify the entity identity before editing. Before finishing, re-read and visibly verify every task constraint (filters, sort, size, quantity, date range). After an action confirms completion, stop and report it rather than re-inspecting. If #number is stale, read() and retry; if on the wrong page, back() and keep searching. open(url) returns to an earlier results page; back() can lose its query string.
fullfreshoffsetregionCase-insensitive whole-page text search, including trimmed content; returns #numbers, actionable row neighbours, and bounded local context. Give a list of up to 6 texts to search them all in one call. Use context_chars to expand just that local context; a matched heading is not a region label. With no match it scrolls virtualized lists and loads more of an infinite feed to look, and says so.
textrequiredcontext_charsClear region memory; next read shows everything.
Takes no parameters.
Click element #id.
idrequiredReplace input #id text; submit presses Enter.
idrequiredtextrequiredsubmitChoose option text in select or combobox #id. A <select multiple> takes a list and its selection becomes exactly that list. Matching ignores case, accents and punctuation.
idrequiredoptionrequiredPrefer one mixed call for related text, dropdown, and checkbox fields; unrelated fields stay unchanged. Verify entity identity before editing. On failure or rerender it stops and reports partial completion; after confirmed completion, report it rather than re-inspecting.
fieldsrequiredPress a key, e.g. Enter. For bottom-loaded feeds, try End (Control+End if no movement) to load more; a scroll key or scroll reports when the page grew; repeat only while new items appear.
keyrequiredScroll up/down/left/right (default down). id alone brings #id into view; id + direction scrolls its containing list/panel/table. For wide tables use right; without id, a scrollable container is used when the page cannot scroll.
iddirectionBack one page in history.
Takes no parameters.
Wait up to 10s: text states are present (or appears) / disappears; #id states are present / enabled. On timeout, inspect the returned current observation.
idtextstatetimeout_secondsHover element #id and show changes.
idrequiredSelect local file path(s) on #id; this selects files but does not submit a form.
idrequiredpathfilespathsList tabs, or switch/close tab #id.
idactionOnly if read is insufficient: media → data (prefer) → ocr → look (last resort) → ask_human. Numbered images/canvases/charts.
Takes no parameters.
Prefer; text only. Extract image/SVG/chart alt, caption, text or Chart.js/ECharts/Highcharts values; a table gives its rows. id from read()/media(), or CSS selector (#N refs work too).
idselectorText-only OCR for image/canvas. Use if data found nothing. id or CSS selector.
idselectorLAST RESORT; only image-returning tool (PNG, max 800px). Only after read/data/ocr failed. id or CSS selector.
idselectorHuman handoff for CAPTCHA, 2FA, payment or login; never solves CAPTCHAs. Waits for a page change, then returns the page.
untilreasonrequiredtimeout_seconds90% of the applicable checks met
How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.
Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.
npx -y -p mantis-browser mantis installclaude mcp add mantis -- npx -y -p mantis-browser mantis-mcpnpx -y -p mantis-browser mantis read https://example.com # try it without an agent