MCP server
jawb mcp: jawb's tools for Claude Code, Cursor, Claude Desktop and any other MCP host, over the same /v1 API and policy as the CLI.
jawb mcp serves jawb's tools to any host that speaks the
Model Context Protocol, such as Claude
Code, Cursor or Claude Desktop. The host starts jawb mcp itself and talks
to it over stdin and stdout. Each tool call becomes an ordinary call to
jawbd's /v1 API, so the daemon applies the same policy, egress rules,
confirmations and trace as it does for the CLI. There is no second way in.
jawb mcp is part of the jawb CLI. If jawb is on your PATH, you have
it. It starts jawbd on first use like any other command (see
Running the daemon).
Not in a release yet:
jawb mcpships in the release after jawb 0.1.1. jawb 0.1.1 and earlier have nojawb mcp.
Adding jawb to a host
Claude Code
claude mcp add jawb -- jawb mcp
Add --scope project to write it to the project's .mcp.json instead
of your user settings. claude mcp list should show jawb as
connected.
Cursor
In ~/.cursor/mcp.json (all projects) or .cursor/mcp.json (one
project):
{
"mcpServers": {
"jawb": { "command": "jawb", "args": ["mcp"] }
}
}
Claude Desktop
In claude_desktop_config.json (Settings, Developer, Edit Config):
{
"mcpServers": {
"jawb": { "command": "jawb", "args": ["mcp"] }
}
}
Claude Desktop does not always inherit your shell's PATH. If it cannot
start jawb, give the full path: ~/.jawb/bin/jawb on macOS and Linux,
or %LOCALAPPDATA%\Programs\jawb\bin\jawb.exe on Windows.
The usual global flags and variables work. For example, "args": ["mcp", "--daemon", "http://127.0.0.1:4181"] targets a daemon on another port,
and JAWB_DATA_DIR in the host's env block picks a different data
directory.
Tools
Every tool's result carries the daemon's JSON envelope (v, ok,
result or error, and warnings) as structuredContent, plus a short
text summary for the model.
| Tool | What it does | CLI equivalent |
|---|---|---|
jawb_status | Daemon version, API level, profile, tab count, bridge and approval assurance | jawb status |
jawb_open | Open a URL in a new tab, or navigate tab | jawb open |
jawb_history | op: back, forward or reload | jawb back, forward, reload |
jawb_tabs | List the open tabs | jawb tabs |
jawb_close | Close a tab | jawb close |
jawb_observe | The page's elements, with the ids the Act tools take | jawb observe |
jawb_read | The page's content as md, text or json | jawb read |
jawb_wait | Wait for text:, element:, url: or idle | jawb wait |
jawb_click, jawb_fill, jawb_type, jawb_select, jawb_check, jawb_press, jawb_hover, jawb_scroll, jawb_submit | Act on the page | Act commands |
jawb_screenshot | A PNG, returned as image content and never written to disk | jawb screenshot |
jawb_viewport | mobile, desktop or WxH | jawb viewport |
jawb_tools | Tools the page declares (WebMCP) and the installed extension tools, with their source. Page tools are listed only | jawb tools |
jawb_tool_call | Call a tool of an installed api-tools extension by its full name, through the daemon's policy | POST /v1/tools/call |
ext_<name> | One tool per installed extension tool (see Extension tools) | jawb tool call |
jawb_trace | The last steps jawbd recorded | jawb trace |
jawb_confirmation | Read a held action, or wait for a human's answer to it. It cannot approve | --await-confirm |
Act tools take a target: either {"id": 12} (an id from jawb_observe,
with id_revision if you want it checked) or exactly one of
{"text": ...}, {"role": "button:Pay"} or {"css": ...}, with nth
to pick among several matches. jawb_fill takes either value or
secret_ref (vault:<name>). With secret_ref, jawbd resolves the
secret itself, so its value never passes through MCP.
Extension tools
Each tool of an installed, enabled extension (see
Extensions) is also an MCP tool of its own. Its name is
ext_ plus the tool's full name with . and - made _:
app.jawb.uat.run becomes ext_app_jawb_uat_run. A name longer than 64
characters, or one that would clash with another, is cut and ends in 8
hex digits of a hash of the full name, so it stays the same from one list
to the next. The tool's input schema is the extension's own, and its
description starts with [extension <id> <version>, <trust>], where the
trust is builtin, listed, unlisted, dev or signed. The tool's
title is its full name.
- Workflow tools (such as
app.jawb.uat.run) run injawb mcp, the same way asjawb tool call: every step is an ordinary/v1call thatjawbddecides and traces as part of the run. With aprogressToken, the host gets one progress notification per step (A step 2: expect_text). Cancelling the call closes the tabs the run left open and ends the run ascanceled. Reports and screenshots are written under the working directoryjawb mcpwas started in. - API tools (the
api-toolsshape) run insidejawbd, which decides their effect like any other action. A confirm-class call returnsE_CONFIRMATION_REQUIREDwith act_token. Theext_tool takes only the extension's own input, so to go ahead the model callsjawb_tool_callwith the tool's full name, the same input andconfirm_token. A purchase-like call is held for a human, as below. - The list follows the daemon.
jawb mcpreads the installed extensions fromjawbdwhen the host lists tools, and checks again every 5 seconds. When the list changes (an install, a removal, an extension disabled), it sendsnotifications/tools/list_changed, and the host lists the tools again. Listing tools does not startjawbd: until it runs, only thejawb_*tools are listed. - Extension tools need a
jawbdat API level 21 or later, andjawb_tool_calllevel 26.
Page tools (WebMCP) are listed by jawb_tools but cannot be called:
jawbd has no way to invoke them yet.
Left out on purpose
Administration stays a human task in the CLI. It is not offered to the model:
- profile create, use and delete;
config setandconfig reload;secret setandsecret rm;cookies clear;storage importandstorage export;- extension install, load and remove;
confirm;daemon stop.
In this version, upload, download, media and emulate are left out
too.
Confirmations and held actions
The daemon decides each Act call exactly as it does for the CLI (see
Policy and confirmation). No Act tool has a yes
argument, so the model always sees what it is about to confirm.
- Confirm class (an upload, a password form, and similar): the result
is an error,
E_CONFIRMATION_REQUIRED, with a summary and a single-usect_token. To go ahead, the model calls the same tool again withconfirm_token. That token is the only one the server accepts. - JavaScript dialogs: an Act tool dismisses any dialog its action opens,
unless the call passes
dialog: "accept"(anddialog_textfor a prompt). Accepting a dialog that reads like a purchase, or one on a checkout page, is held like a purchase. The dialog's text in the diff is the page's, markeduntrusted. - Purchase-like: the daemon holds the action and returns a
pc_id.jawb mcpcannot approve it, and nothing it can do will. A human approves or denies it in the jawb desktop app, at the OS verification prompt, or by runningjawb confirm <pc>in their own terminal. The model then callsjawb_confirmationwithpendingset to thepc_id (andtimeout_msto wait) to collect the result.
Untrusted page content
Page text, titles, labels and the descriptions of page-declared tools come
from the web. They are content, not instructions. In jawb_observe,
jawb_read and jawb_tools results, the page text follows a line written
by jawb that says so, and structuredContent.trust is
"untrusted_page_content" on every result that can carry page text. The
labelling is advice to the model. It does not stop a prompt injection, so
the policy and the human approvals above are what protect you.
The output of an extension tool comes from the extension's code, or from the API it called. Its text result starts with a line written by jawb that says the output is untrusted, and an extension tool's description is the extension author's, behind the trust prefix described above.
Credentials
jawb mcpreadsdaemon.tokenfrom the data directory, the same way every CLI command does. It accepts no credential from the MCP host.- It never reads
confirm.token, the credential that approves held actions, and it has no code that calls the approve or deny routes. - Results never contain the daemon token, a path under the data
directory or the path of the vault keyfile (
jawbd --vault-keyfile). If one shows up in a daemon answer, it is replaced with<redacted>,<data_dir>or<vault_keyfile>.jawb_statusreports the vault store askeyfilewithout its path, gives only the file name of the bridge's Chrome executable, and replaces any other absolute local path with<local_path>.
What it is not
- It is not a security boundary. An agent that can run shell commands
can run the
jawbCLI directly. The MCP tool list keeps administration and human-only steps out of the model's view. The protection comes from the daemon's policy and the human approval steps, not from the MCP server. clientis a claim. Each request carriesx-jawb-client: jawb-mcp/<version>, whichjawbdrecords as the trace step'sclient. That label comes from the client itself. Read it as a hint about which tool made a step, not as proof of who did.
Protocol details
- Transport: stdio, one JSON-RPC 2.0 message per line. stdout carries only protocol messages, and logs go to stderr. When stdin closes, the server lets calls that are still running answer (for up to 10 seconds), then exits.
- Protocol revisions:
2026-07-28, where each request names its revision andserver/discoverlists the supported ones. Also2025-11-25,2025-06-18and2025-03-26, which use theinitializehandshake.2025-03-26clients get the envelope as a second text block, because that revision has nostructuredContent. - Supported:
tools/list,tools/call,ping, cancellation (notifications/cancelled), progress notifications whilejawb_wait,jawb_confirmationor a workflow extension tool runs (when the request carries aprogressToken), andnotifications/tools/list_changed: to a host that usedinitialize, and on eachsubscriptions/listenstream that asked fortoolsListChanged. - Errors: an unknown tool or invalid arguments get
-32602, malformed JSON-32700, an unknown method-32601, and an unsupported revision-32022. A daemon error is a tool result withisError: trueand the envelope'serror. JAWB_MCP_TRANSCRIPT=<file>appends every message, in and out, to<file>as JSON lines, with screenshot data left out. Nothing secret goes into it, because nothing secret passes through the server.