Installation¶
Kitsune has two parts that you install separately:
- The MCP server. Your MCP client launches it over stdio. You register it once with a command; uv downloads and runs it, so you do not need a checkout.
- The browser extension. You install it in your browser yourself. The browser asks for your approval, and nothing is installed silently.
The server starts the shared bridge daemon on demand. The extension connects to that daemon by itself once both are installed.
- Prerequisites
- 1. Register the MCP server
- 2. Install the browser extension
- 3. Check the connection
- Pinning a version
- Upgrading
- Automatic extension updates
- Extension and server compatibility
Setup problems are covered in Troubleshooting. To run Kitsune from a checkout, see Development.
Prerequisites¶
- uv, which provides
uvx. uv downloads a supported Python (3.10+) if none is installed. - Git, only if you install from the Git source instead of PyPI (see Pinning a version).
- A Firefox-family browser, Gecko 142+: Firefox 142+, Zen 1.23+, or LibreWolf.
- macOS or Linux. Windows is untested.
1. Register the MCP server¶
Every client runs the same stdio command:
uvx --from kitsune-browser-mcp kitsune
The first start downloads Kitsune and its dependencies into the uv cache, which
takes a few seconds. Later starts reuse the cached version until you upgrade
(see Upgrading). Kitsune is published on PyPI as
kitsune-browser-mcp; kitsune-mcp is an unrelated project, so do not install
that name.
On macOS, browser_trusted_click (needed for example to open "Continue with Google"
popups) needs uvx --from 'kitsune-browser-mcp[macos]' kitsune or brew install cliclick,
plus Accessibility permission; see Sign-in popups.
Optionally, warm the cache and check the install before you register it:
uvx --from kitsune-browser-mcp kitsune-bridge status
This prints {"status": "stopped"} (or the running bridge's status) and never
starts a daemon. Running kitsune with --help does not print help: it is the
MCP server itself, starts the bridge, and waits for an MCP client on stdin.
Claude Code¶
claude mcp add --scope user kitsune -- uvx --from kitsune-browser-mcp kitsune
--scope user makes Kitsune available in every project. Leave it out to register
it only for the current project (local scope). Pass environment variables
with -e, for example -e KITSUNE_CAPS=core,network before the --.
Codex CLI¶
codex mcp add kitsune -- uvx --from kitsune-browser-mcp kitsune
or in ~/.codex/config.toml:
[mcp_servers.kitsune]
command = "uvx"
args = ["--from", "kitsune-browser-mcp", "kitsune"]
# Optional
[mcp_servers.kitsune.env]
KITSUNE_CAPS = "core,network"
Pi¶
With Pi's built-in MCP support:
pi mcp add kitsune -- uvx --from kitsune-browser-mcp kitsune
pi mcp list
This writes user-level configuration to ~/.pi/agent/mcp.json. Add --local
before kitsune to write .pi/mcp.json in the current project instead; project
configuration is loaded only after project trust is granted. In a running
session, use /reload to pick up the change and /mcp to inspect the connection.
You can also edit the JSON config directly using the mcpServers example below.
If an MCP adapter extension overrides built-in MCP support, use that extension's
configuration instructions instead.
Claude Desktop, Cursor, Pi, and other mcpServers clients¶
Edit the client's JSON config, for example
~/Library/Application Support/Claude/claude_desktop_config.json (Claude Desktop
on macOS), ~/.cursor/mcp.json or .cursor/mcp.json (Cursor), or ~/.pi/agent/mcp.json or
.pi/mcp.json (Pi's built-in MCP support). Merge the entry with any existing servers:
{
"mcpServers": {
"kitsune": {
"command": "uvx",
"args": ["--from", "kitsune-browser-mcp", "kitsune"]
}
}
}
Add an "env": {"KITSUNE_CAPS": "core,network"} object next to args to set
environment variables.
OpenCode¶
Edit ~/.config/opencode/opencode.json (global) or opencode.json at a git repo
root (project) by hand.
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"kitsune": {
"type": "local",
"command": ["uvx", "--from", "kitsune-browser-mcp", "kitsune"],
"enabled": true
}
}
}
GUI apps and PATH¶
GUI apps such as Claude Desktop often do not inherit your shell PATH. If the
client cannot find uvx, use the full path from which uvx as the command, for
example /Users/you/.local/bin/uvx. Config files do not expand ~.
Several clients can be configured at once; they share one bridge daemon. Register them all with the same source and ref (see compatibility).
2. Install the browser extension¶
The extension is not part of the Python package, so download it separately, for the same version as the server. There are two builds:
Signed build (kitsune-<version>.xpi) |
Developer build (kitsune-extension-dev-<version>.zip) |
|
|---|---|---|
| Install | Once; survives browser restarts | Temporary add-on; load it again after every restart |
| Signed by Mozilla | Yes (self-distributed, not listed on AMO) | No |
browser_evaluate, JS conditions in browser_sync_barrier and batch if/while, HTML mode of editable typing, bundled workflows that use js steps |
Not available | Available |
| Everything else | Available | Available |
The signed build cannot run JavaScript supplied by the agent, because Mozilla's
add-on policies
forbid executing code that is not part of the signed package. Those tools return
an error that names the developer build. browser_status (in the admin group,
KITSUNE_CAPS=core,admin) reports which build is connected (extension_build:
signed or dev).
Signed build (recommended)¶
Signed XPIs are attached to releases from 0.2.0 on. For 0.1.0, use the developer build below.
- Download
kitsune-<version>.xpifrom GitHub Releases. - Open
about:addons, click the gear icon, choose Install Add-on From File…, and select the XPI. Dragging the file onto a browser window also works. - Approve the permission prompt. The browser asks every time; nothing is installed silently.
- Restart or reconnect your MCP client and ask it to list your tabs (
browser_tabswithaction: "list"). Withadminenabled,browser_statusshould report"extension_connected": trueand"extension_build": "signed".
Signed builds released after 0.2.0 update themselves (see Automatic extension updates).
Developer build¶
Use this for browser_evaluate, or to run an unreleased commit.
- Download
kitsune-extension-dev-<version>.zipfrom GitHub Releases and unzip it. For 0.1.0 the file is namedkitsune-extension-0.1.0.zip. For an unreleased commit, use theextension/folder of a repository ZIP or clone. - Open
about:debugging#/runtime/this-firefoxand click Load Temporary Add-on…. - Select
manifest.jsonfrom the unzipped folder (extension/manifest.jsonin a repository ZIP or clone). In the macOS file dialog, press Cmd+Shift+G to paste a path. - With
adminenabled, callbrowser_status; it should report"extension_build": "dev".
Both builds use the same add-on ID. While a developer build is loaded, it replaces the signed one; after a browser restart the signed build is back.
3. Check the connection¶
Restart the agent and ask it to list your tabs (browser_tabs with
action: "list"). An error's hint says what to fix; with
KITSUNE_CAPS=core,admin, browser_status reports "extension_connected": true
and a full diagnosis. Then try a first task.
Pinning a version¶
Pin a released version with ==:
claude mcp add --scope user kitsune -- uvx --from kitsune-browser-mcp==0.7.3 kitsune
Releases are listed on PyPI and GitHub Releases, which also carries the matching signed XPI and developer-build zip.
To run a commit, tag, or branch that is not on PyPI, use the Git source with
@<ref> (requires Git). The MCP server's package is in packages/kitsune-browser-mcp;
uv builds the code it depends on, kitsune-browser, from the same ref:
claude mcp add --scope user kitsune -- uvx --from "git+https://github.com/junyeong-nero/kitsune.git@<ref>#subdirectory=packages/kitsune-browser-mcp" kitsune
Without @<ref>, the Git source follows the latest default-branch commit. Get
the extension from the same ref:
https://github.com/junyeong-nero/kitsune/archive/<ref>.zip, or
git checkout <ref> in a clone.
Upgrading¶
Server¶
- Unpinned PyPI (
--from kitsune-browser-mcp): uvx keeps using the cached version. To move to the newest release, refresh it once, then restart or reconnect the MCP client (in Claude Code,/mcp):To check for a new release on every start instead, registeruvx --refresh --from kitsune-browser-mcp kitsune-bridge status--from kitsune-browser-mcp@latest. - Pinned (
==<version>or Git@<ref>): change the version in the client config. For Claude Code, runclaude mcp remove --scope user kitsune, then run theclaude mcp addcommand again with the new version. - Unpinned Git source: uv checks for the latest default-branch commit each time the MCP server starts (observed with uv 0.7.20).
- A pip install of 0.6.0 or earlier, such as a virtual environment for the Python API:
until 0.6.0 kitsune-browser-mcp held the code that kitsune-browser holds now. pip installs
kitsune-browser first and then removes the old kitsune-browser-mcp with the files they
share, so
import kitsunefails afterwards. Restore them once withpip install --force-reinstall --no-deps kitsune-browser. The same holds afterpip uninstall kitsune-browser-mcpin an environment that kept 0.6.0. uv and uvx are not affected. - A checkout: run
git pull, thenuv sync.
Bridge¶
Reconnect or restart the MCP server after upgrading it. It compares the running
bridge's build (package version plus a source hash, including extension JS/JSON in a
checkout) with its own and automatically restarts an outdated bridge. This briefly
interrupts all clients sharing that bridge. Set KITSUNE_NO_BRIDGE_RESTART=1 in the
MCP server's environment to opt out of automatic replacement. You can also stop it
explicitly; the next MCP connection starts a fresh daemon:
uvx --from kitsune-browser-mcp kitsune-bridge status # JSON; includes bridge_version and build
uvx --from kitsune-browser-mcp kitsune-bridge stop
From a checkout, use uv run kitsune-bridge status / stop instead.
Plain kitsune-bridge (or kitsune-bridge start) still runs the daemon
in the foreground. status and stop never start a daemon. All commands use
the same KITSUNE_HOME, token, and port environment settings as the server.
Shutdown uses a token-authenticated endpoint, with a verified, locked PID file
as the termination fallback; it never uses a broad pkill. Very old daemons
that have neither the shutdown endpoint nor a PID file require a one-time
manual stop of the specific old bridge process. Kitsune reports this instead
of guessing a PID or launching another daemon over it. After that, automatic
replacement and kitsune-bridge stop work normally.
Extension¶
Update the extension to the same version as the server: the signed build updates
itself (see Automatic extension updates); for 0.2.0,
or to update right away, install the new release's XPI the same way as the first time
(it replaces the old version and keeps no separate copy). For the developer
build, load the new release and click Reload on Kitsune in about:debugging
(or load the updated manifest.json again). A bridge restart reconnects the
extension but does not reload its browser-side code; reload it explicitly after
extension updates, and reload existing tabs if their content scripts are still
outdated. browser_status reports a developer build whose files changed after it
was loaded as extension_version_mismatch (state.reason: "stale_developer_build").
Then reconnect the MCP client again if needed (in Claude Code, use /mcp to
reconnect Kitsune), and call browser_status. Check extension_connected,
bridge_version, and build.
Idle shutdown (opt-in)¶
By default the shared bridge keeps running until it is stopped. To have it exit
when no client has used it for a while, set KITSUNE_BRIDGE_IDLE_TIMEOUT (in
seconds) in the MCP server's environment, or run the daemon yourself with
kitsune-bridge start --idle-timeout SECONDS. 0 (the default) disables it.
- Every HTTP call to the bridge counts as activity; MCP servers make one per tool call. The extension's WebSocket connection does not count.
- The timer only runs while nothing is in flight: no HTTP request, no command
waiting on the extension, and no
browser_keep_aliveloop. Callbrowser_keep_alive_stopwhen you no longer need one, or the bridge never goes idle. - The next tool call from any client starts a fresh bridge automatically. While an idle bridge is exiting, a client that needs one waits for it to finish instead of racing it.
- The bridge is shared, so the first MCP server that starts it decides the timeout; the setting in other clients takes effect the next time they start it.
Automatic extension updates¶
The signed build checks
https://github.com/junyeong-nero/kitsune/releases/latest/download/updates.json
and installs the signed XPI of the latest release. This works from the release
after 0.2.0 on: the 0.2.0 XPI has no update URL, so install the next release's
XPI once by hand (see Signed build); later releases
then arrive automatically. The developer build never updates itself.
- The browser checks about once a day. To check now, open
about:addons, click the gear icon, and choose Check for Updates. Updates can be turned off per add-on on Kitsune's page inabout:addons(Allow automatic updates). - A release's
updates.jsonis published only after its server is on PyPI, but uvx keeps using its cached server (see Upgrading). Until you refresh it, the extension can be newer than the server;browser_statusthen reports anextension_versionthat differs frombridge_version. - If you pin an older server version, turn off automatic updates for Kitsune and install the matching XPI from that release.
Extension and server compatibility¶
- The server and the extension are developed in the same repository and are only tested together at the same commit. Install both from the same release (or ref). There is no separate compatibility matrix yet.
browser_statusreports the bridge'sbridge_version(package version) andbuild(package version plus a hash of the bridge code). An installed package does not contain the extension, so itsbuilddoes not change when only extension files change. Reload the extension yourself after updating it.- Use one install source for all clients. A checkout run
(
uv run --directory …) also hashes the checkout'sextension/files, so itsbuilddiffers from auvxinstall of the same commit. If clients with different builds share a bridge, each one replaces the bridge when it starts. If you need to mix sources, setKITSUNE_NO_BRIDGE_RESTART=1in the MCP server environments and manage the bridge withkitsune-bridge stop. browser_statusalso reports the connected extension'sextension_versionandextension_build. Ifextension_versiondiffers frombridge_version, upgrade the server (the signed extension updates itself, so it is usually the newer one) or install the matching extension.- Browsers: Gecko 142+ (Firefox 142+, Zen 1.23+, LibreWolf). Firefox release and beta builds install only signed extensions, which is why the developer build is a temporary add-on.