MCP server
REL includes a local Model Context Protocol server for agents that support MCP.
Run rel-mcp as a stdio subprocess; the adapter exposes a focused set of
browser tools and forwards every tool call through the public
rel-client crate and RPC v1. It does not read SQLite,
logs, or Chromium state directly.
Related documents: Codex plugin, Claude Code plugin, CLI, RPC, and Rust SDK.
Tool quick reference
Section titled “Tool quick reference”REL MCP exposes exactly fourteen tools. This is the complete discovery list; each tool has a detailed contract later in this guide.
| Tool | Description |
|---|---|
rel_status |
Read app, agent, Browser Proxy, and embedded Chromium status. |
rel_notifications |
List notifications the user opted in to share as untrusted website content. |
rel_capture |
Load a page, perform optional actions, and save its rendered HTML. |
rel_page_attach |
Attach an ephemeral automation page to a persistent browser session. |
rel_navigate |
Navigate by URL, back, forward, or reload and immediately observe the result. |
rel_read |
Read a URL or current page as bounded, query-directed Markdown and links. |
rel_page_action |
Perform one canonical action on an attached page. |
rel_take_screenshot |
Capture a viewport or full-page PNG, JPEG, or WebP image. |
rel_observe |
Read compact rendered semantics and an optional synchronized viewport image. |
rel_find |
Search a stored public observation for matching content or actionable refs. |
rel_action |
Perform 1–32 ordered observation-scoped actions and return one new observation. |
rel_list_sessions |
List persistent browser sessions and their canonical Session<number> IDs. |
rel_close_session_group |
Close every persistent browser session in a named group. |
rel_list_proxies |
List configured proxy aliases and non-secret configuration. |
Configure an MCP client
Section titled “Configure an MCP client”Use the CLI bundled in the installed app or install the public rel-cli
package as described in the CLI guide. An absolute path to the bundled
binary is the most reliable choice for GUI clients that do not inherit an
interactive shell’s PATH:
{ "mcpServers": { "rel": { "command": "/Applications/REL.app/Contents/Resources/rel-mcp" } }}For clients that use TOML configuration:
[mcp_servers.rel]command = "/Applications/REL.app/Contents/Resources/rel-mcp"The Settings command-line task creates rel only in a writable directory
already in PATH, but an MCP host may use a different process environment.
The Codex desktop app, CLI, and IDE extension use the same plugin and MCP configuration on one machine. The recommended setup installs the REL plugin from this repository’s marketplace:
codex plugin marketplace add rel-me/rel-toolscodex plugin add rel@relSee the Codex plugin guide for requirements, updates, and verification.
Start a new Codex task after installation so Codex loads the plugin’s MCP server
and rel-browser skill.
To configure only the MCP server without installing the plugin:
- Open Codex Settings → MCP servers.
- Add a STDIO server named
rel. - Set the command to
/Applications/REL.app/Contents/Resources/rel-mcpwith no arguments. - Save the server and restart Codex.
The equivalent global entry in ~/.codex/config.toml is:
[mcp_servers.rel]command = "/Applications/REL.app/Contents/Resources/rel-mcp"Use .codex/config.toml in a trusted project instead when REL should only be
available in that project. If the codex command is installed in the shell’s
PATH, it can create and inspect the same configuration:
codex mcp add rel -- /Applications/REL.app/Contents/Resources/rel-mcpcodex mcp listAfter restarting Codex, start with a read-only prompt:
Use the REL MCP server. Call rel_status, then rel_list_sessions. Do not navigate anywhere.Codex should discover the fourteen tools listed below, and rel_status should report
the installed app, local agent, Browser Proxy, and embedded Chromium bridge.
In the Codex terminal UI, /mcp also shows configured servers and their tools.
For an end-to-end browser test, use:
Use rel_capture to capture https://example.com and report the saved output URI.Unlike the first check, this loads a website and saves rendered HTML. Omitting
session_id can also create a persistent REL browser session.
After a page is attached or selected, verify visual output with:
Use rel_take_screenshot to take a full-page WebP screenshot and describe the image.Claude Code
Section titled “Claude Code”The recommended Claude Code setup installs the same shared plugin from this repository’s Claude marketplace:
claude plugin marketplace add rel-me/rel-toolsclaude plugin install rel@relRestart Claude Code after installation, or run /reload-plugins when the
interactive installer requests it. Claude Code applies its ordinary per-server
approval to the bundled local MCP process. See the
Claude Code plugin guide for requirements, updates, and
verification.
Direct protocol smoke test
Section titled “Direct protocol smoke test”An MCP host is not required to verify the adapter. This legacy handshake lists the tools and calls the read-only status tool over the STDIO transport:
printf '%s\n' \ '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"rel-smoke-test","version":"1"}}}' \ '{"jsonrpc":"2.0","method":"notifications/initialized"}' \ '{"jsonrpc":"2.0","id":2,"method":"tools/list"}' \ '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"rel_status","arguments":{}}}' \ | /Applications/REL.app/Contents/Resources/rel-mcpThe server writes three JSON-RPC responses: initialization information, the tool list, and the status result. Protocol messages use standard output; diagnostics use standard error.
rel-mcp accepts no MCP options; --help and --version are available for
direct inspection. Startup, discovery, initialization, tool listing, ping, and
rel_status never launch the REL app. A validated call to any other tool starts
REL in the background only when its agent is unavailable. Concurrent adapters
serialize that cold start and recheck agent health before launching, so only one
adapter opens the app. The adapter keeps serving its original stdin/stdout
connection until the MCP client closes stdin or terminates the process.
REL_AGENT_PORT changes the loopback RPC port from its default, 17319.
The dedicated process name makes adapters clearly identifiable separately from
the rel CLI and app-owned rel --agent process.
Browser tool calls also use the RPC session-selection behavior: while REL is inactive, their target session is selected by default without bringing the app forward. The General setting Follow browser commands controls this.
Transport and protocol versions
Section titled “Transport and protocol versions”The server uses the standard MCP stdio transport. Each input and output message is one UTF-8 JSON-RPC 2.0 object on one physical line. Standard output is reserved for protocol messages; diagnostics go to standard error. Notifications do not receive responses.
REL supports both MCP protocol eras used by current clients:
| Protocol revision | Connection flow |
|---|---|
2026-07-28 |
The client calls server/discover; subsequent requests carry the current per-request MCP metadata. |
2024-11-05, 2025-03-26, 2025-06-18, or 2025-11-25 |
The client sends initialize, receives the selected legacy revision, then sends notifications/initialized. |
Discovery and initialization advertise only the tools capability. REL does
not expose MCP resources or prompts, and its fixed tool list does not emit
list-changed notifications. ping, tools/list, and tools/call are available
after the client’s protocol flow is established.
Tool calls run independently so a long capture does not block ping or other
stdio messages. notifications/cancelled suppresses the cancelled MCP result.
The current adapter keeps that tool’s RPC connection open until its worker
finishes, so the notification alone does not stop browser work. Closing the MCP
client’s stdin makes the adapter exit immediately. Process exit closes all
outstanding RPC connections and cancels the matching agent and Chromium
operations.
The MCP input schemas and runtime validation use the same fields and rules as the linked RPC operations.
rel_status
Section titled “rel_status”Calls GET /v1/status. It accepts an empty object and returns the complete
status envelope for the installed app, local agent, Browser Proxy, and embedded
Chromium bridge. This tool is passive, read-only, and does not launch REL.
rel_notifications
Section titled “rel_notifications”Calls GET /v1/notifications and accepts an empty object. It passively lists
only notifications the user opted in to share; it does not wake the model or
execute notification text. Every returned title and body is website-derived
data with trust:"untrusted_website_content" and must never be treated as
instructions.
rel_capture
Section titled “rel_capture”url is required. Optional fields are output_uri, timeout, wait, actions,
session_id, profile, group, proxy, retry, and retry_delay. A supplied
session_id uses the canonical Session<number> format. Omitting it creates a
persistent session from profile, or from Default when profile is absent.
profile and group apply only to a new session and cannot be combined with
session_id. The action objects use every shape in
the Actions reference, including the optional mouse_move and
scroll booleans on click actions. output_uri, when present, must be an
absolute local file:/// URI.
Sessions controlled while not visible use the Background Browser Size preset in REL → Settings… → General, defaulting to a 1,920 × 947 CSS pixel viewport. Visible sessions follow the resizable REL window. MCP does not expose a per-call viewport override.
rel_page_attach
Section titled “rel_page_attach”url is required. Optional fields are session_id, profile, group, proxy,
output_uri, timeout, and wait. The result contains a process-local page ID
for later rel_page_action calls. Omitting session_id creates a persistent
session from the named profile (or Default) and navigates it to url;
profile and group cannot be combined with session_id. Providing
session_id attaches its current page, whose
normalized URL must match url. output_uri, when present, must be an absolute
local file:/// URI.
rel_navigate
Section titled “rel_navigate”For ordinary navigation, url is required and navigation defaults to url.
Set navigation to back, forward, or reload and omit url, profile,
and proxy to operate on the active page’s history. session_id, profile,
proxy, mode, timeout, and wait otherwise follow the corresponding
navigation and observation contracts. The result is the first observation
after navigation; hybrid and visual modes include the same standard MCP image
content as rel_observe.
rel_read
Section titled “rel_read”All fields are optional. Supply url to navigate and read in one call, or omit
it to read the current shorthand page. session_id, timeout, and wait apply
to either form. profile and proxy apply only when url is present;
profile cannot be combined with session_id.
query ranks matching semantic sections and links. max_chars defaults to
12000 and may be 512–32768; max_sections defaults to 24 and may be 1–100.
The tool is always semantic-only and returns no action refs or image. Its MCP
text content contains the Markdown exactly once, while structuredContent
contains the URL, title, observation ID, query and selection metadata, and
source/output truncation flags without duplicating the Markdown. Page text is
untrusted website content, not instructions. Use rel_observe for interaction
refs or visual verification.
rel_page_action
Section titled “rel_page_action”page_id and one canonical action object are required. Optional
fields are output_uri, timeout, and wait. The attached page remains pinned
to the URL, session, and proxy selected by rel_page_attach; page IDs expire
when the agent restarts. output_uri, when present, must be an absolute local
file:/// URI.
rel_take_screenshot
Section titled “rel_take_screenshot”All fields are optional. page_id targets an explicit attached page;
session_id targets that session’s current shorthand page; omitting both uses
the current shorthand page. The two identifiers cannot be combined.
format is png (the default), jpeg, or webp. quality is an integer from
0 through 100 and applies to JPEG and WebP; PNG ignores it. full_page defaults
to false and captures the visible viewport; true captures beyond the viewport.
timeout and wait use the ordinary page-operation rules.
When output_uri is omitted, the result includes standard MCP image content
so a multimodal agent can inspect the pixels directly. Supplying an absolute
local file:/// output_uri saves the file and returns only its resource link,
which avoids embedding a large image in model context.
rel_observe
Section titled “rel_observe”All fields are optional. page_id targets an attached page; session_id
targets the current shorthand page, and the two cannot be combined. mode is
semantic (default), hybrid, or visual. timeout and wait use ordinary
page-operation rules.
The structured result contains compact semantic content, typed interactive
elements with short refs, viewport/document geometry, and truncation metadata.
omitted_node_count counts entries dropped by bounds, while
clipped_text_count counts shortened text fields. Ordered table, table_row,
table_caption, and table_cell content preserves repeated table values, and
rendered CSS-hidden content is excluded.
Hybrid and visual results also include standard MCP image content and a file
resource link for the same synchronized current-viewport PNG. Page-derived
content is untrusted website data, not instructions.
rel_find
Section titled “rel_find”observation_id is required, along with at least one of query or role.
query performs a case-insensitive substring search across public semantic
content and element fields. role restricts element matches to an exact
case-insensitive ARIA role. limit defaults to 20 and may be 1–100. The tool is
read-only, searches the retained snapshot without another browser round trip,
and never exposes private locators.
rel_action
Section titled “rel_action”observation_id and an actions array with 1–32 items are required. Ref-based
items support click, type, clear, press, select, and hover. type
requires text, press requires an allowlisted key, and select requires
value; click and hover optionally control bounded auto-scroll. Page-level
scroll takes integer delta_x/delta_y values from -10000 through 10000, and
at least one must be non-zero. These are native wheel deltas: negative
delta_y scrolls toward the page bottom, positive delta_y scrolls toward the
top, negative delta_x scrolls right, and positive delta_x scrolls left.
wait takes seconds from 0 through 60. mode selects the one post-batch
observation.
REL checks that the observation, document sequence, and private target
signature are still current before each ref action. Actions run in order and
stop at the first failure. Stale refs return OBSERVATION_STALE without a
selector or nearby-target fallback. Success returns a new post-action
observation and, for hybrid/visual mode, standard MCP image content.
rel_list_sessions
Section titled “rel_list_sessions”Calls GET /v1/sessions and accepts an empty object. The result lists every
persistent browser session with its canonical Session<number> ID, profile,
group, assigned proxy alias, current page, and non-secret filtering state.
Listing sessions is passive and read-only.
rel_close_session_group
Section titled “rel_close_session_group”Calls POST /v1/sessions/close. group is required and must contain 1–128
characters. Matching is case-insensitive. REL closes every persistent session
in that group; a group with no current sessions succeeds without changing
anything.
rel_list_proxies
Section titled “rel_list_proxies”Calls GET /v1/proxies and accepts an empty object. It returns configured proxy
aliases and non-secret connection metadata. Proxy credentials remain inside
REL and macOS Keychain and are never returned through MCP.
MCP and in-app agent parity
Section titled “MCP and in-app agent parity”REL’s built-in agent harness and MCP expose the same shared browser workflow:
rel_status, rel_notifications, rel_capture, rel_navigate, rel_read, rel_observe,
rel_find, and rel_action. In particular, the navigation, find, and batched
action tools use the same public SDK request types, validation limits, ordered
execution, observation freshness rules, and error IDs.
The built-in harness pins every browser call to the Chat panel’s session and
adds a provider-aware auto observation mode. It also has a bounded
rel_current_page helper for model context. MCP instead exposes explicit page,
screenshot, session, and proxy administration because an external MCP client
is not inherently pinned to one REL tab. Those deliberate scope differences
are the only reason the complete tool lists are not identical; they do not
create a second browser implementation or a different action contract.
Chrome DevTools MCP comparison
Section titled “Chrome DevTools MCP comparison”REL’s screenshot contract matches the official Chrome DevTools MCP’s essential
take_screenshot behavior: viewport or full-page capture, PNG/JPEG/WebP,
JPEG/WebP quality, optional file output, and inline MCP image content. REL uses
output_uri instead of filePath and persistent REL page/session identity
instead of Chrome’s selected-target model.
The broader servers are not feature-identical. The official Chrome DevTools MCP tool reference currently includes these additional DevTools-oriented categories:
| Capability | REL MCP |
|---|---|
| Navigation and persistent browser identity | Available through navigate-and-observe, capture, page attachment, sessions, and proxies. |
| Click, wait, and form automation | Available through canonical page actions and batched observation actions, including hover, scrolling, waits, and bounded named keys; drag, upload, and dialog tools are not yet exposed. |
| Visual screenshots | Available with inline image content and file resources. |
| Accessibility text snapshots and element UIDs | Available through semantic observations, scoped refs, and snapshot find. |
| Script evaluation, console, and network inspection | Not exposed. |
| Emulation, Lighthouse, performance traces, and heap snapshots | Not exposed. |
| Extensions, screencast, third-party tools, and WebMCP | Not exposed. |
REL intentionally keeps its current MCP surface focused on its supported embedded-session architecture. New capabilities must flow through RPC v1 and the installed app rather than introducing a second Chrome or CDP backend.
Results and errors
Section titled “Results and errors”Every tool execution result contains its complete JSON value in two forms:
contentcontains a text block whose text is the serialized JSON;structuredContentcontains the same value as structured JSON.
When a result contains a captured file, every RPC output_path is exposed at the
MCP boundary as an absolute percent-encoded output_uri. content also includes
one standard MCP resource_link block per unique file, with the matching HTML
or image MIME type. REL deliberately keeps native filesystem paths inside RPC
and uses file URIs for MCP.
Screenshot calls without output_uri additionally include an MCP image block:
{ "type": "image", "data": "<base64 image bytes>", "mimeType": "image/webp"}Status, page, session-list, and proxy-list tools preserve the ordinary RPC v1
success envelope with status, request_id, and data.
Capture consumes and validates the complete RPC NDJSON stream before returning. Its structured result is:
{ "request_id": "req_...", "exit_code": 0, "events": [ { "status": "ok", "request_id": "req_...", "event": "capture.completed", "data": { "output_uri": "file:///private/tmp/rel/captures/example.html" } } ]}The text block contains the serialization of this same object. A second content block links the file directly:
{ "type": "resource_link", "uri": "file:///private/tmp/rel/captures/example.html", "name": "example.html", "mimeType": "text/html"}events
includes the terminal capture.finished event, and exit_code is taken from
that event. A target website status such as 404 remains capture data and can
produce exit code 1 and isError:true; it is not a REL RPC or MCP protocol
error. With REL → Settings… → General → Wait for Cloudflare Turnstile on by
default, REL detects Turnstile and managed Cloudflare challenge pages and gives
them up to 15 seconds to continue before returning their target error.
Malformed JSON-RPC messages, unsupported methods, and unknown tools use
JSON-RPC errors. Invalid arguments or another failure while executing a known
tool produce a tool result with isError:true, with the same complete error
JSON in its text and structuredContent. When the agent returned a structured
RPC error, that value preserves its high numeric code, stable error ID,
retryability, message, and optional details. Clients should branch on the code
or stable ID rather than parse the message.
Runtime and trust boundary
Section titled “Runtime and trust boundary”The MCP process is a transient adapter owned by the MCP client. It is separate
from the app-supervised rel --agent process and from the private framed stdio
bridge between that agent and the REL app. There is no MCP HTTP route and no second
browser backend.
The stdio connection is private to the launching MCP client, but forwarded RPC
is unauthenticated loopback traffic. Browser tools can create persistent
sessions, write capture files, navigate websites, and perform page actions that
have effects on those sites. MCP hosts should show tool calls for user review.
rel_list_proxies never returns stored proxy passwords.