Skip to content

Maho MCP Server

maho mcp is the stdio entry point for using Maho Browser as an MCP (Model Context Protocol) tool server from another AI application.

From Claude Desktop, Cursor, or another MCP host, the configuration is simply: run the maho executable with the mcp argument. Maho then exposes browser tabs, navigation, page extraction, history/bookmark operations, and session coordination as MCP tools.

Maho keeps the privileged server logic inside the browser process. The CLI is the stdio-facing adapter used by MCP clients:

Claude Desktop / Cursor / MCP host
|
| stdio
v
maho mcp
|
| local browser IPC
v
Maho Browser MCP server
|
+--> tabs / navigation / page tools
+--> history / bookmarks
+--> policy / approvals / redaction

There is no TCP listener and no public HTTP endpoint. Quitting Maho removes the browser-side service; maho mcp is not a daemon that keeps a browser API alive after the Browser exits.

The command is:

Terminal window
maho mcp

Normally you do not run it in an interactive terminal. The MCP host launches it as a child process and owns stdin/stdout. Starting it manually is useful only for process/path troubleshooting; a healthy stdio server may simply wait for MCP input.

Claude Desktop reads MCP server entries from claude_desktop_config.json.

On macOS:

~/Library/Application Support/Claude/claude_desktop_config.json

On Windows:

%APPDATA%\Claude\claude_desktop_config.json

Add Maho under mcpServers:

{
"mcpServers": {
"maho": {
"command": "maho",
"args": ["mcp"]
}
}
}

If the CLI is not on the GUI application’s PATH, use an absolute path:

{
"mcpServers": {
"maho": {
"command": "/absolute/path/to/maho",
"args": ["mcp"]
}
}
}

Restart Claude Desktop after changing the config. The client should enumerate Maho’s tools during MCP initialization.

A low-risk first test is to ask Claude to list your open Maho tabs. That maps to browser_tab_list and does not require navigating to a new domain.

Cursor can use the same stdio definition. Add a Maho MCP server through Cursor’s MCP settings, or use the JSON MCP configuration for the scope you want (for example a project .cursor/mcp.json):

{
"mcpServers": {
"maho": {
"command": "maho",
"args": ["mcp"]
}
}
}

Restart/reload Cursor after changing MCP configuration, then confirm the Maho server is enabled and its tools are visible.

A useful smoke-test prompt is:

Use the Maho browser tools to list my open tabs. Do not navigate or close anything.

Once tool discovery works, try a read-only page request before a mutating action:

Read the visible text from the active Maho tab and summarize it. Do not navigate.

Maho’s browser MCP registry is organized by capability. Tools are standard MCP tools/list / tools/call entries and return JSON-bearing tool content.

ToolPurpose
browser_tab_listList open tabs.
browser_tab_getGet details for one tab.
browser_tab_newOpen a new tab.
browser_tab_closeClose a tab.
ToolPurpose
browser_navigateNavigate a tab to a URL, subject to the session’s allowed-domain policy.
browser_set_allowed_domainsSet/update the session-scoped domain allowlist used for navigation.
ToolPurpose
browser_page_contentReturn full page content in the requested supported representation.
browser_page_textReturn visible/readable page text.
browser_search_in_pageSearch within page text.
browser_page_contextReturn high-level page context such as title/URL and extracted document metadata.
page_query_selectorResolve a CSS selector to a node reference.
page_get_textRead text from a resolved node.
page_get_attributeRead an attribute from a resolved node.
page_wait_for_selectorWait until a selector resolves.
ToolPurpose
browser_history_searchSearch local browsing history.
browser_bookmarks_searchSearch bookmarks.
browser_bookmark_createCreate a bookmark.
ToolPurpose
browser_acquire_leaseAcquire exclusive control of a tab for the MCP session.
browser_heartbeat_leaseKeep an existing lease alive.
browser_release_leaseRelease the session’s tab lease.

For argument schemas and raw JSON-RPC examples, see the Agent Protocol tools reference.

When Browser-integrated Mail is enabled and the relevant consent gates pass, Mail read tools can also be surfaced through the Browser tool layer, including:

  • mail_list_accounts
  • mail_list_folders
  • mail_list_emails
  • mail_get_email
  • mail_search_emails
  • mail_list_thread
  • mail_extract_otp

Mail tools are not an independent mail server. They are dispatched by Maho Browser to the profile-scoped Mail helper. See MCP and Agent access for the feature, helper, consent, and typed-approval gates.

The MCP registry intentionally does not expose a generic JavaScript execution primitive. Page access is provided through typed content/query tools, which gives Maho a place to apply redaction and policy before content leaves the browser process.

This is different from maho tab eval, an explicit local CLI operation. Do not wrap tab eval and hand it to an agent as a way to bypass the MCP policy surface.

MCP tool access is local, but “local” is not the same as “unrestricted”. Maho keeps policy enforcement in the browser where the page/profile data lives.

The Agent Protocol is not a network service. On macOS/Linux the browser uses a local Unix-domain transport with same-user checks; Windows uses a local Named Pipe/session-token model. This prevents a normal MCP configuration from becoming a LAN-accessible browser-control endpoint.

Navigation is scoped by an allowed-domain policy. A session that has not been approved for a target domain cannot simply navigate there because the model asked. MCP clients should expect a browser-side approval flow or a policy error when a domain is outside the current allowlist.

Content leaving the browser goes through Maho’s credential-redaction boundary. Sensitive values such as credentials/auth material are not meant to become ordinary MCP tool output just because a page contains them.

See Agent Protocol security for the current redaction vectors and policy details.

Agents coordinate control through per-tab leases. If two sessions race for the same tab, the lease registry can reject/conflict rather than letting both mutate the tab concurrently. Long-running clients heartbeat their lease and release it when finished.

A permissive global tool policy does not imply permission to read Mail. Mail reads additionally require Allow AI to read Mail. Sensitive Mail write or account-changing actions go through their typed approval path.

A tool can exist in the product while being unavailable to a specific session because of feature flags, user settings, consent state, domain policy, or the current implementation status. MCP clients should handle tool errors instead of assuming discovery implies every invocation will succeed.

Maho follows the MCP tool-call shape. Tool results are returned as MCP content; Maho’s Browser tools use text content containing JSON for structured payloads. At the protocol level, a representative response is:

{
"jsonrpc": "2.0",
"id": 42,
"result": {
"content": [
{
"type": "text",
"text": "{\"tabs\":[{\"id\":\"tab_1a2b\",\"title\":\"Example\",\"url\":\"https://example.com/\",\"active\":true}]}"
}
],
"isError": false
}
}

MCP SDKs normally parse the outer protocol structure for you. If you are writing a raw client, parse the JSON string inside result.content[0].text before using the Browser payload.

Desktop GUI apps often inherit a smaller PATH than your terminal. Replace "command": "maho" with the absolute path to the executable.

Confirm Maho Browser is running, reload the MCP client, and inspect the client’s MCP logs. Tool enumeration happens during initialization, so a stale client session may need to reconnect.

That is not necessarily a connection failure. The requested domain may not be in the MCP session’s allowed-domain policy. Approve/set the domain through the normal Maho flow rather than trying to bypass the policy.

Check, in order: Mail enabled for the profile, Mail helper ready, global tool policy not deny-all, and Allow AI to read Mail enabled for read tools. See MCP and Agent access for stable denial reasons.

Another agent session may own the tab lease. Let that session release/expire its lease, or use the product’s explicit lease-control semantics rather than retrying mutating calls in a tight loop.

Use plain CLI commands when the shell is the orchestrator:

Terminal window
maho page markdown | llm 'Summarize this page.'

Use MCP when another AI host should decide which Browser tool to call:

{
"mcpServers": {
"maho": {
"command": "maho",
"args": ["mcp"]
}
}
}

The underlying Browser remains the policy boundary in both cases.