Tools, capabilities and modes¶
By default Kitsune publishes the 25 tools of Playwright MCP's
default capabilities, with the same names, descriptions, input schemas and annotations, as
its core capability group (see Core tools), with Kitsune's browser_resume,
which continues a call that stopped for you, and browser_ask_user, with which the agent asks
you for what it cannot do (#376). Kitsune's other tools are in the other
groups. Set KITSUNE_CAPS in the MCP server environment before starting it;
restart the MCP client after changing it. The comma-separated list selects exactly those
groups (include core to retain the default tools). all enables all 97 tools in every
group except storage and history, which read personal data and must be named
(KITSUNE_CAPS=all,storage,history). Whitespace and case are ignored; unknown group names
fail at startup.
[mcp_servers.kitsune.env]
KITSUNE_CAPS = "core,browse,read"
| Group | Tools for |
|---|---|
browse |
Scrolling, forward navigation, checkboxes, focus, form submits, real mouse clicks |
read |
Page text and Markdown, forms, DOM, links, images, metadata |
inspect |
Element bounds, computed styles, selector checks, highlights |
tabs |
Pinning, muting, zoom, windows, tab tags, keep-alive |
automation |
Batches, retries, workflows, parallel tabs, and resuming an interrupted batch |
network |
Downloads, request interception and capture |
admin |
Connection status, logs, audit, cache, policy |
storage, history |
Cookies, page storage, clipboard and saved sessions; history and bookmarks. These read personal data, so all leaves them out and you name them yourself |
The tool list names every tool in each group.
Earlier releases' devtools, parallel, windows and session groups are gone, and
naming them fails at startup. devtools became browse, read, inspect, admin and
(browser_workflows, browser_workflow) automation; parallel became automation
and, for tab tags and keep-alive, tabs; windows joined tabs; session joined
storage, which all no longer includes.
A tool left out by KITSUNE_CAPS is absent from tools/list, and clients usually say
nothing about it. Calling it anyway returns an MCP error with
code: "tool_not_published" whose hint names the setting that publishes it, for
example KITSUNE_CAPS=browse,core for browser_scroll. browser_status (admin)
reports this server's mcp_tools: the enabled caps, how many known tools are
unpublished, and its audit client and tab owner ids.
The bridge enforces the groups too. The MCP server sends its enabled groups with every
request, and the bridge refuses a route or a container step (of browser_batch,
browser_parallel, browser_retry, browser_broadcast, browser_workflow or
browser_resume) that belongs to another group with code: "capability_restricted".
So automation runs only commands of the groups you enabled: with
KITSUNE_CAPS=core,automation, a batch cookies step is refused until you add
storage, and a workflow needs the groups of its steps. Like task modes, this limits
what an agent can do through this MCP server; it is not a boundary against other local
programs that hold the bridge token.
Finding tools without a restart¶
KITSUNE_CAPS decides which tools this server runs. KITSUNE_PUBLISH decides which of
them tools/list shows when a session starts; unset, it is KITSUNE_CAPS, so nothing
changes. Set it to fewer groups to keep the list small and let the agent reach the rest
in the same connection:
[mcp_servers.kitsune.env]
KITSUNE_CAPS = "all"
KITSUNE_PUBLISH = "core"
With Claude Code:
claude mcp add --scope user kitsune -e KITSUNE_CAPS=all -e KITSUNE_PUBLISH=core -- uvx --from kitsune-browser-mcp kitsune
tools/list then has the 27 core tools and three gateway tools:
browser_tools_search(query, limit=5)finds the tools this server runs but does not list, best match first, each with its full description, input schema and annotations. An empty query lists their names by group.browser_tools_call(name, arguments)runs one and returns its own result, images included, and its error status.browser_tools_publish(names)adds tools, or whole groups, to this session'stools/listand sendsnotifications/tools/list_changed; clients that refresh on it can then call them directly.
KITSUNE_PUBLISH takes the group names KITSUNE_CAPS does, and only groups
KITSUNE_CAPS enables: naming another one fails at startup. The gateway tools appear
only when some enabled tool is not published.
The gateway never runs more than a direct call could. It finds and runs only tools
KITSUNE_CAPS and KITSUNE_MODE permit: all still leaves out storage and
history unless named, and a name it does not permit gets the same tool_not_published
as a direct call. A call through browser_tools_call takes the direct call's path, so
argument validation, the task mode, confirmation tokens, protected user tabs, redaction
and file name roots apply the same way, and its audit entries record
via: {"gateway": "browser_tools_call", "tool": …}. Your client's permission prompt may
show only browser_tools_call and its conservative annotations (destructive,
open-world), not the tool it runs, so do not rely on per-tool client prompts for these
calls. browser_tools_publish changes only that session's list, never what the server
permits or another session's list. Clients differ in whether they act on
notifications/tools/list_changed; the notification is not proof that the model sees
the new tools, and browser_tools_call works either way.
This reaches tools that are already installed. Changing KITSUNE_CAPS or upgrading
Kitsune still needs a restart.
The Kitsune-owned tools take tab_id to target background tabs; without it they act on
the current tab like the core tools. They share an action
contract (ref, wait, expect, confirm_token, first; confirm_token is the
approval fallback for clients without elicitation) documented on
browser_check; see the API reference and the
tool list.
Every tool includes MCP annotations. The core tools carry Playwright MCP's; the
Kitsune-owned ones have a human-readable title and read-only, destructive, idempotent,
and open-world hints, annotated for their most dangerous operation. Clients can use
these hints to inform permission prompts; enforcement depends on the client. The hints
are not enforced policy. The bridge enforces task-mode limits and browser_set_policy
(readonly, allow/deny, and ask-before-act).
Core tools¶
The core tools other than browser_resume and browser_ask_user are Playwright MCP's, published verbatim from
src/kitsune/playwright_tools.json (captured from @playwright/mcp with
node scripts/update_playwright_tools.mjs), so a client or prompt written for Playwright
MCP works unchanged. They drive your own browser through the Kitsune extension and return
Kitsune's compact JSON results, not Playwright's Markdown. Where the two differ:
- Current tab. Tools act on the tab
browser_tabsneworselectmade current;selectdoes not switch your view. It takes any tab, yours and other clients' too, so the agent can read it; on a tab it cannot write, the result saysread_only: true. Kitsune's own tools called withouttab_id, andbrowser_batch,browser_retryandbrowser_workflowcommands that name notabId, act on the current tab too. Until there is one, reads act on the active tab, and writes and navigations that name no tab returnno_current_tabwithout sending anything (No current tab). An MCP server that restarts starts without a current tab; itsno_current_tabthen lists the open tabs its MCP client opened before, the most recent first, instate.ownTabs, and the hint names that tab, so the agent can pass it astab_id(to a core tool, which takes none, the hint names itsbrowser_tabsindex to select). The server does not pick one itself: the tab may belong to an earlier conversation. Persistent ownership survives bridge/extension restarts and browser session restore for the same client id; handed-off tabs return when their session ends (Tab owners). A tab a batch or workflownewTabopens, or an action on the current tab opens (a click on atarget=_blanklink, for example), becomes current, and the result names it incurrent_tab.browser_navigateandbrowser_navigate_backalso accept atab_idthat Playwright MCP's schema does not list.indexis the position inbrowser_tabslist, which also marksactiveand agent-ownedtabs, and thecurrentone regardless of ownership. Selection does not grant ownership (Protecting your tabs).new,selectandclosereturn the tabs after the change in the same form;newreturns the new tab'sindex.browser_closecloses the current tab, never the browser; closing a user or other client's tab is refused withuser_tab_read_onlyby default. - Targets.
targetis a snapshot ref (e12) or a CSS selector. Actions require one actionable match (elseambiguous_target). Actions and scoped snapshots also accept a subset of Playwright selectors:text=(also/regex/),role=…[name="…"](also[name=/regex/]),internal:text=,internal:role=,internal:label=,:has-text(),:text-is(),:text(),:visible, CSS lists,>>chains (also starting at a ref, as ine12 >> xpath=..),nth=Nandxpath=(refused on pages holding redacted content); see Target selectors. Unsupported forms returnunsupported_selectorwith a hint, not a retryable missing target. Element screenshots use the same resolver and capture the exact selected node, including inside shadow roots. Refs survive newer observations while their nodes remain attached in the same document; navigation or replacement nodes require new refs. - Snapshots. Default core snapshots include redacted static text and resolved HTTP(S) link
URLs (same-origin ones as paths; a link repeating the previous sibling link's URL, or, first
under its parent, the page's, has no
/urlline). Returned inline they are capped at 12,000 characters, cut between blocks so a product card or paragraph is never split (a long navigation, banner or footer outsidemainis shown as its line and a… not shownmarker untilmainis listed), withtruncated: trueand a hint towardbrowser_find, a scopedtargetorfilename(which saves the whole snapshot; seebrowser_snapshot). Existing line clipping, structural collapsing and depth rules still apply: past the fifth of a run of similar items the snapshot shows- … N more similar items; snapshot e14 to list allwhen that hides at least three items (a run of up to seven is listed in full), and a snapshot withtargete14(the items' container) lists up to 100 of them.browser_findsearches collapsed items too. In the full toolset,text=Falseis compact andtext=Trueenables explicitly bounded readable output (12,000 final public chars). Explicit HTTPmaxCharsand post-action limits also apply after URL redaction; scoped snapshots remain useful for large pages. - Sliders and repeated keys.
browser_fill_formtype: "slider"andbrowser_type(withoutslowly) set a native<input type=range>directly. An ARIA slider or spinbutton (role=sliderorspinbuttonwith a numericaria-valuenowand no native input, the usual custom widget) is set as a user would: the extension focuses it and presses arrow keys (Home/Endfor an end) until itsaria-valuenowis the value, all in one call, and returns the finalvalue. If the value is outsidearia-valuemin/aria-valuemax, the call fails withvalue_not_reachedbefore any key; if it is not reached (the steps skip it, the widget stops moving, or 1,000 keys or 20 s run out) it fails the same way withstate.value(Action errors).browser_press_keyalso accepts arepeatcount (1–100) that Playwright MCP's schema does not list; the extension presses the key that many times in one call, a task apart. - Dialogs.
browser_handle_dialogsets how the current tab answers its next dialogs (Firefox answers dialogs synchronously, so one already open cannot be answered). - Uploads and drops. A synthetic click opens no file chooser, so
browser_file_uploadfills the file input last clicked (or the input inside it, else the page's only file input).browser_dropfiresdragenter/dragover/dropwith the files and data. - JavaScript.
browser_evaluateneeds the developer extension build and runs in the content-script context; the result is JSON-parsed. - Console and network.
browser_console_messagesstarts capture on first use, so earlier messages are missed.browser_network_requestslists the page's resource timing entries since it loaded; there are no headers or bodies, sobrowser_network_requestwithpartanswersnot_supported. - Screenshots.
browser_take_screenshotreturns an inline image;filenamesaves PNG or JPEG.typechooses the encoding; otherwise.jpg/.jpegfilenames infer JPEG, with PNG as the default. Other formats answernot_supported;scaleis ignored. - Not supported.
browser_emulate_mediaandbrowser_run_code_unsafeare listed but answernot_supported(retryable: false): an extension cannot override CSS media features, and there is no Playwright page to run code against. - File names. A relative
filenameis resolved againstKITSUNE_OUTPUT_DIRif set, else the firstfile://root the MCP client lists (MCProots, asked for on each call with afilename; no answer within 5 seconds counts as none), else the MCP server's working directory. Absolute names and~are used as given.saved_tois the absolute path written.
Ask-before-act holds still apply. On a client with elicitation the MCP server asks the
user and repeats a held call itself (see Approving held actions).
The core schemas have no confirm_token, the fallback for clients without elicitation; the
tools accept it anyway, so on such a client, after the user approves a held action, an agent
can repeat the call with confirm_token from the needs_user error.
Task modes¶
Set KITSUNE_MODE=read|draft|act in the MCP server environment and restart the client.
The default is act, preserving the existing tool surface and bridge policy. Mode names
ignore case and surrounding whitespace; unknown names fail at startup.
[mcp_servers.kitsune.env]
KITSUNE_MODE = "read"
| Mode | Published tools and enforced limits |
|---|---|
read |
Read tools plus navigation to HTTP(S) pages (or about:blank) and scrolling. browser_tab_list replaces the multi-action browser_tabs; with new_tab it opens a background tab that later calls act on. It cannot close or select tabs. No clicks, field writes, JavaScript, submits, confirmations or screenshots/file writes. |
draft |
Read surface plus browser_type, browser_select_option, browser_fill_form and, with the browse group, browser_check. Fills plain text only; no click/keypress/submit/dialog confirmation or JavaScript. Ask-before-act is forced: sensitive fields, payment-like pages and uninspectable targets are refused before filling, without a confirmation token. |
act |
Existing behavior, including the independently configured ask-before-act policy. |
Modes intersect with KITSUNE_CAPS; they never enable a disabled group. With the
default core group, read publishes eight tools: list-only tabs, navigate, snapshot,
find, wait for text, console messages and the network request list and details.
draft adds type, select-option and fill-form. Page text, forms and DOM need the
read group, and scrolling the browse group. Extra enabled groups contribute only
their read tools. The personal-data storage and history groups still require
explicit opt-in.
Restricted surfaces use first-paragraph descriptions and omit confirm_token, the approval
fallback for clients without elicitation: they cannot approve.
Calling an unpublished tool by name returns tool_not_published with the mode setting
needed to publish it; browser_status.mcp_tools.mode identifies a restricted server.
The gateway tools are listed in every mode and reach
only the tools the mode permits.
The bridge enforces the mode on every request, including calls made by name or directly
over HTTP. A restricted request cannot change policy, run containers or resume an act
call. Draft form-fill inspects every target before writing any field.
Modes are per MCP client: a read client cannot loosen its mode by calling
browser_set_policy, and does not change another client's policy on the shared daemon.
The bridge's existing URL/readonly/locked-ask policy can tighten the mode further.
Use an act client or the browser itself for a sensitive action. Modes limit agent
commands, not page scripts: navigation can still trigger site behavior and field events
can autosave a draft. They are not an incognito session or an application-level sandbox.
Exact token counts and research/account-lookup task measurements belong to
kitsune-benchmark; character-size guards in this repo are not token measurements.