customaise
OfficialThis MCP server connects AI agents to a signed-in Chrome session to manage scripts, inspect/control browser tabs and pages, and invoke WebMCP tools.
List, import, export, create, update, delete, enable/disable UserScripts and AgentScripts, including forking shared scripts.
Bulk-sync owned scripts to a local workspace with a manifest; overwrites matching local files.
Read DOM snapshots and console logs, and retrieve visually selected elements with selectors and comments.
List, open, close, focus, and reload browser tabs.
Capture viewport or full-page screenshots, saved to file or returned inline.
List and call WebMCP tools registered by AgentScripts; prompt-gated calls wait for user consent and send progress notifications.
Show/hide the Customaise UI overlay and open specific panels.
Read and set Script Decisions providers and question lists, subject to user permission controls.
Check bridge status, sign-in, plan tier, quota, agent permissions, and save operation status.
Choose file or inline output for large payloads and long-running tool results.
Exposes Script Decisions provider management, letting an agent inspect and choose a script's provider (including OpenAI's Decisions API, "openai-decisions") and toggle its question lists on/off for @grant CM_decisions calls. The classification requests themselves run in the browser extension and are billed to the user's saved OpenAI key; agents can read provider/state and question-list hashes but cannot supply keys.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@customaiselist my user scripts"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
@customaise/mcp
MCP server and CLI that connect AI coding agents to the Customaise Chrome extension. Manage UserScripts, build AgentScripts, call WebMCP tools inside the user's signed-in browser session, select DOM elements visually, and drive tabs. Drive it over stdio from an IDE, or as a customaise command from a shell.
21 tools, 5 resources plus a script resource template, WebSocket bridge between your agent and a real Chrome session, whichever door it arrives through.
Two ways in. customaise-mcp is the MCP server an IDE spawns over stdio.
customaise is a CLI for agents that have a shell instead, driving the same
tools through a resident daemon. Both go through the same cap enforcement and
the same consent gate.
AI Agent ←(stdio)→ MCP Server ←(WebSocket)→ Customaise ExtensionSpeaks the MCP 2026-07-28 revision, negotiated per connection: a client on
that revision gets the stateless flow with cacheable tools/list, and a client
on the 2025 revisions keeps working unchanged. The package is 3.x precisely so
nobody has to guess this from a 2.x version number.
Quick Start
1. Install Customaise
Install the Customaise Chrome extension on Chrome 147 or later, sign in, and turn on Agent Bridge in Settings → MCP & Terminal. Chrome 147 is the tested release baseline for extension 1.3.9.
2. Add to your IDE
Cursor (.cursor/mcp.json):
{
"mcpServers": {
"customaise": {
"command": "npx",
"args": ["-y", "@customaise/mcp"]
}
}
}Claude Code (one command, no file to edit):
claude mcp add customaise -- npx -y @customaise/mcpClaude Desktop: install customaise.mcpb from the latest release. The bundle returns page content inline, which a chat client needs (see Chat clients and file-less agents). Or add it to claude_desktop_config.json with the same setting:
{
"mcpServers": {
"customaise": {
"command": "npx",
"args": ["-y", "@customaise/mcp"],
"env": { "CUSTOMAISE_MCP_OUTPUT": "inline" }
}
}
}Kiro (.kiro/mcp.json):
{
"mcpServers": {
"customaise": {
"command": "npx",
"args": ["-y", "@customaise/mcp"]
}
}
}Codex (~/.codex/config.toml):
[mcp_servers.customaise]
command = "npx"
args = ["-y", "@customaise/mcp"]Antigravity (mcp_config.json):
{
"mcpServers": {
"customaise": {
"command": "npx",
"args": ["-y", "@customaise/mcp"]
}
}
}3. Done
Your agent can now read and edit UserScripts, build AgentScripts that expose WebMCP tools to it, select DOM elements visually, inspect the console, and take screenshots of the live tab.
Related MCP server: LoopIn
Tools (21)
Script Lifecycle
Tool | Description |
| List every script (UserScripts and AgentScripts) managed by the extension |
| Pull a script to a local file for editing |
| Push a local file to Customaise (validates and installs) |
| Permanently delete a script |
| Enable or disable a script |
Browser Context
Tool | Description |
| DOM snapshot of the current page |
| Console logs, errors, and |
| List all open browser tabs |
Tab Control
Tool | Description |
| Open a new tab at a given URL |
| Close a tab by ID |
| Switch focus to a tab by ID |
| Reload a tab to re-inject scripts |
Visual DOM Targeting
Tool | Description |
| Get the DOM elements the user has visually selected, with stable, tiered selectors and screenshots |
| Capture any tab (not just the visible one) as a viewport or full-page image |
WebMCP Agent Tools
Tool | Description |
| List the WebMCP tools currently registered on a tab by AgentScripts |
| Call a WebMCP tool; prompt-gated tools block on user consent (see below) |
UI Control & Batch
Tool | Description |
| Show or hide the Customaise UI overlay |
| Bulk export all scripts to a local directory |
Script Decisions
Tool | Description |
| Read Script Decisions on this device: whether agents may manage it, saved provider keys, and each script's provider and state; with a script ID, its question lists and their hashes |
| Choose a script's provider (Jev or Decisions API) and which question lists are On, or switch it off. Needs the person to turn on Script Decisions under Full access, except off |
Diagnostics
Tool | Description |
| Report extension attachment, plan tier, sign-in, remaining quota and the browser's agent permission mode, including whether agents may manage Script Decisions, when supported. Costs no quota itself. |
Resources (5 plus a template)
Five resources and one script resource template that connected agents can read via resources/read. The two conventions handbooks define exactly how Customaise expects UserScripts and AgentScripts to be written. Agents should read the relevant handbook before touching a script.
URI | Description |
| Live JSON list of every script the extension manages (ID, name, enabled state, match patterns, shared flag) |
| Full source and metadata for a specific script |
| Points at the right handbook for the script type you're working on |
| Full UserScript reference: file structure, IIFE pattern, |
| Full AgentScript reference: the |
| Shared UserScript/AgentScript guide: Decisions API questions, the CM_decisions API, working example, device/provider setup, billing and failure handling |
Script Decisions in UserScripts and AgentScripts
Script Decisions is a Power User capability and needs extension 1.3.8 or later.
Read customaise://script-decisions over MCP or run:
customaise resource script-decisionsUse it for bounded text classification, relevance checks and scoring; use ordinary
code for extraction, exact rules and actions. Both script engines declare
@grant CM_decisions and call CM_decisions.create or createMany with
Decisions API questions written out in the code. The resource contains a complete
UserScript and instructions for wrapping the same helper in an AgentScript tool.
The user saves separate Jev/Decisions API keys on /account#script-decisions,
enables the device in Your Devices (from another device when that browser
is marked Operated by an AI agent), and selects a provider in the script's
Decisions menu (its branch icon, or Quick Actions → Script Decisions). Requests then run automatically. Settings
can pause the device without losing selections; Data & Analytics reports usage
by device/provider. Provider charges and budgets are separate from Customaise
browser AI tokens. MCP/CLI cannot supply keys or allow a device.
WebMCP approval still applies independently to the containing tool.
create and createMany wait for the answers themselves. Preserve refusals and
errors; do not resend uncertain work or switch providers automatically. Changing
a script's code asks for its provider to be chosen again, unless an agent saved
it under the grant below. See the
Script Decisions guide.
Agents choosing providers
Settings → Agent permissions → Full access has a second part, Script
Decisions. Only the person turns it on, through a protected confirmation in
the extension; no MCP tool or CLI command can. While it is on, connected agents
can choose a script's provider (Jev or Decisions API) on this device, switch its
question lists On or Off, and resume a script the loop guard paused for
repeating the same input (loop_repeat). Switching a script's provider off is
always allowed. Provider keys, the device's Allow Script Decisions switch, daily
limits, pausing the device, a runaway-loop pause (loop_runaway) and scripts
shared with the person stay with the person; those refusals carry error type
person_required (CLI exit 6), and the agent should tell the person the step
rather than retry.
MCP | CLI |
|
|
|
|
sets names the question lists to switch On by the hashes get_script_decisions
returns for one script; every other list goes Off. When an agent saves a script
with export_script while Script Decisions is on for agents, Customaise signs
its provider again for the new code if it was current for the code just
replaced, and scriptDecisions in the result says whether it was kept and, if
not, why. Without the grant the person chooses the provider again after the
edit. Both tools need extension 1.4.0 or later; an older extension answers
extension_outdated.
Updating to MCP/CLI 3.2.9 and extension 1.4.0
The CLI and Desktop bundle ship the same tested runtime dependencies. Runtime
dependencies are bundled in the npm tarball so fresh installs retain those
versions. Contributors should use npm ci; dependency updates belong in
package-lock.json and must pass the packaged-release checks before publication.
Update both the extension and the companion for the latest permission controls
and status reporting. The npm package contains both customaise-mcp
and the customaise CLI; Claude Desktop uses the matching 3.2.9 .mcpb bundle.
Restart all MCP clients and any running Customaise CLI daemon after updating.
Relay protocol 2 is unchanged from 3.2.3. The tool surface grows to 21 with
get_script_decisions and set_script_decisions.
The AgentScript handbook now teaches document.modelContext, the WebMCP
standard name that extension 1.4.0 provides; navigator.modelContext still
works in every version. Both handbooks note that Chrome withholds
secure-context APIs on plain http pages other than localhost, and the
UserScript handbook describes @connect as 1.4.0 reads it. Read
customaise://agentscript-conventions or customaise://userscript-conventions,
or run customaise resource <name>, before editing a script.
The migration reference
covers moving a library from Tampermonkey. Customaise provides every GM API and
metadata key Tampermonkey supports on Chrome.
Agent permissions and Full access
Settings → Agent permissions offers Use tool permissions (the default) and Full access. A user-confirmed Full access grant lets eligible Prompt tools run without repeated Customaise approvals in that browser profile, including new and updated tools. Saved Deny rules, undeclared tools, disabled scripts and URL restrictions still apply. Saved per-tool choices are preserved; turning Full access off restores them. The grant stays on until disabled or the user signs out, is not synced, and does not enable Chrome DevTools access. Browsers configured to accept approvals only from another device cannot enable Full access locally.
get_bridge_status and customaise doctor expose agentPermissions with
mode, revision, scope, locked and scriptDecisions (whether agents may
manage Script Decisions; false from an extension before 1.4.0). Older
extensions may return no status. There is no MCP/CLI command to grant Full
access or its Script Decisions part: the person controls both in the
extension. The interactive bottom bar exposes active permissions, DevTools,
bridge and sync controls; Appearance can keep them visible while off as well.
A temporary account-verification failure is reported as unknown/verifying,
not a confirmed Free subscription. Calls that cannot safely verify access fail
with retryable entitlement_unavailable and do not consume Free quota. Wait for
verification to recover before retrying; a genuine subscription change still
applies normally. Tool actions are never replayed automatically. Structured
permission refusal details and CLI exit codes survive leader/follower forwarding.
Customaise also syncs explicit per-tool Allow/Prompt/Deny choices with each script. Update and finish syncing the browser holding those choices before removing its profile, and use the updated extension when restoring. Previously discarded local-only choices cannot be recovered from older cloud snapshots. Resetting a tool to its script default syncs too; older clients without this field do not erase the saved choices.
Save deadlines and recovery
export_script reports an operation ID and stages such as normalization,
Monaco queue/setup, resources and persistence. The extension bounds the whole
save to 90 seconds, including waiting for the offscreen document. Cancellation
and transport timeouts propagate through both leader and follower processes.
Work cancelled before persistence cannot later publish. Concurrent preparations
and storage revisions are checked again at the commit boundary.
After a timeout, use get_bridge_status({ scriptId, operationId }), with the
IDs from the error, or customaise doctor --script ID --operation ID. This
authenticated read costs no quota, including when the normal quota is exhausted.
committed means there is a retained commit receipt; matchesCurrentCode says
whether that version remains current. not_committed identifies a known attempt
that has not written. unknown means there is insufficient retained proof:
inspect the current script before retrying. A submitted Chrome storage write
cannot be recalled. Its receipt is stored with the script and survives a browser
restart. Only the latest receipt per script is durable; recent operation stages
are retained in memory for up to 15 minutes (128 entries, 32 running saves).
For edits, pass the codeHash returned by import_script as
export_script.expectedCodeHash to reject a save based on an outdated import.
Update all MCP processes together: internal leader/follower relay protocol 2
adds cancellation ownership. The extension wire protocol is unchanged by it; the
full save contract requires extension 1.3.4.
WebMCP Tool Calls & Consent (HITL)
AgentScripts register tools on web pages via document.modelContext.registerTool(...), the WebMCP standard name; navigator.modelContext, its earlier name, also works and is the one Customaise before 1.4.0 accepts. Each tool is declared in the AgentScript's // @webmcp <toolName> <permission> header with one of three permissions:
allow: tool executes immediately. ~50 to 100ms round-trip per call (the extension still runs permission checks).prompt: in the default tool-permissions mode, each call surfaces an in-browser consent modal and blocks until the user approves or denies. User-enabled Full access lets eligible Prompt tools run without that modal; Deny rules and separate DevTools requirements still apply. Up to 5 minutes. Design for this. Don't chain prompt-gated calls in tight loops, and treat a longcall_webmcp_toolas normal.deny: tool is suppressed and calls fail immediately.
"Always allow" and "Always deny" buttons on the consent modal persist the decision per-script per-tool until the user resets it in extension Settings. These overrides are stored with the script and included in encrypted sync when enabled. The extension evaluates them for each call; MCP cannot set them or grant itself Full access.
Remote approvals (optional)
If the user has Power User and has enabled Remote HITL Approvals on their Customaise account page, prompt-gated calls are also mirrored there. They can approve or deny from any signed-in browser, including a phone. Either the extension modal or the remote surface can resolve; first signed decision wins. From the MCP client's perspective this is transparent: call_webmcp_tool simply returns the result when any authorised surface approves, or an error if denied or timed out.
What MCP clients see
A prompt-gated
call_webmcp_toolresponse may take up to 5 minutes. Surface a pending state to the end user rather than timing out aggressively.While it waits, the server sends
notifications/progresson any request that carried aprogressToken, one per extension of the consent budget. A client that resets its request timeout on progress (the MCP SDK does, so does Claude Code) waits with the user. Claude Desktop and Cursor cap a tool call at a fixed 60 seconds at the time of writing and will report the call failed while the user can still approve it; the tool description tells the agent not to blindly re-issue a call with side effects when that happens.If the user denies,
call_webmcp_toolreturns an error. The MCP server does not retry.Tool-call arguments transit HTTPS in plaintext to our backend and land KMS-encrypted at rest in Firestore. Metadata (toolName, scriptName, origin) stays plaintext. See the Customaise Privacy Policy.
Visual DOM Selection
Users can visually select elements in the browser, and the extension pushes context files to your workspace in real time:
.customaise/dom-context/<script-name>/
├── element-name.dom.md # Selectors, element context, user comments
├── element-name.screenshot.png # Cropped screenshot of the selected element
└── ...Where are the files saved?
The MCP server writes .customaise/ to its current working directory (usually your project root in Cursor).
If you are using a global IDE like Claude Desktop, it defaults to your home directory (~/.customaise/). To force a specific project folder, set CUSTOMAISE_WORKSPACE in your MCP config:
"env": { "CUSTOMAISE_WORKSPACE": "/absolute/path/to/your/project" }From the CLI, the directory you ran the command in wins over both. The
daemon is long-lived and was started from whatever directory you happened to
be in the first time, so it takes the caller's word for it on every command.
CUSTOMAISE_WORKSPACE still beats a plain cwd for IDE servers, unchanged.
Use get_selected_elements to retrieve selections programmatically, or read the pushed .dom.md files directly from the workspace.
Each selection includes stable, tiered selectors (stable IDs → data attributes → ARIA → semantic classes → structural positioning) so targeting is more likely to survive page updates.
Workflows
UserScript
1. get_page_context → understand the target page
2. User selects elements → .dom.md files auto-pushed to workspace
3. Write .user.js file → AI writes the script using IDE tools
4. export_script → Customaise validates and installs
5. reload_tab → re-inject the script
6. get_console_context → check for errors
7. take_screenshot → verify the visual resultAgentScript
1. Read customaise://agentscript-conventions → get the structure right before writing
2. get_page_context → find stable selectors on the target page
3. Write .agent.js file → declare tools via // @webmcp, register with document.modelContext.registerTool()
4. export_script → Customaise validates and injects
5. reload_tab → the AgentScript registers its tools in the page
6. list_webmcp_tools → confirm tools surfaced
7. call_webmcp_tool → invoke one; prompt-gated calls wait for user consentFile Sync
Use sync_scripts to bulk-export every script to a local directory:
sync_scripts({ directory: "~/customaise-scripts" })This creates:
One
.user.jsfile per script. Filename is derived from the script name (lowercase, hyphens, e.g.my-cool-script.user.js)..customaise-manifest.json: maps filenames to script IDs for round-trip editing.
Manifest format
{
"dark-mode-fix.user.js": "vm_script_1774225715376_lus75sdzn",
"my-cool-script.user.js": "vm_script_1774225800123_abc12defg"
}Round-trip
sync_scriptsexports all scripts to a directory.Edit any
.user.jsfile in your IDE.export_scriptwith the file path andscriptIdfrom the manifest updates that script.Omit
scriptIdwhen callingexport_scriptto create a new script instead.
File watcher (auto-export)
Once sync_scripts has been called, the MCP server watches the directory for .user.js changes. Saving a file in your IDE pushes it to Customaise automatically, no manual export_script needed.
Configuration
Environment Variable | Default | Description |
|
| WebSocket server port. The extension always connects to 4050, so change this only for tests |
| (empty) | Comma-separated list of extra extension IDs allowed to connect. Needed for unpacked dev builds with a non-standard extension ID |
| (unset) | Set to |
| (cwd) | Absolute path where |
|
| Where the CLI keeps its daemon connection file and remembered tab. Delete this directory to remove everything the CLI stores; uninstalling the extension does not, because these live outside the browser profile |
| (empty) | Optional Bot/session name separating remembered tabs within the same working directory. Remembered tabs are always scoped to the working directory; this adds isolation for Bots sharing one directory |
|
| Loopback port the daemon serves the CLI on. Distinct from |
|
| Where |
|
| Ceiling on an inline JSON payload. Over it, lists are shortened (never the JSON itself, so it still parses) and the response reports exactly what was dropped |
|
| Ceiling on an inline |
Chat clients and file-less agents
get_page_context, get_console_context and take_screenshot spool their
full payload to a file by default and hand back a summary plus a path. That is the right shape
for an IDE agent: a DOM snapshot is routinely hundreds of KB and belongs on
disk rather than in a context window.
It is a dead end for a chat client. Claude Desktop runs this server over stdio, so the write succeeds, but the model on the other end has no filesystem tool with which to open what was written. It receives a path it can never read.
Three ways out, in the order they are consulted:
Per call. Pass
output: "inline"and the full payload comes back in the response, with nothing written to disk. All three tools say so in their own descriptions and in every file-mode response, so an agent that hits the dead end can recover on its own in one extra call.Per install. Set
CUSTOMAISE_MCP_OUTPUT=inlinein the server's env. The.mcpbbundle ships with this set, because that bundle is installed into Claude Desktop and nowhere else. For an IDE, put it in theenvblock of your MCP config. For the CLI, exporting it in your shell is enough: thecustomaisebinary reads it and forwards it per call, so it does not matter that the resident daemon was started earlier without it.Default.
file, unchanged.
take_screenshot is the same flag with a different payload: output: "inline"
attaches the capture to the response as an MCP image block rather than writing
a PNG and returning its path, so a multimodal chat client can actually see it.
An image cannot be shortened the way a snapshot can, so a capture over
CUSTOMAISE_MCP_INLINE_IMAGE_MAX_KB (1536 KB of base64) falls back to a file
and tells the caller to retry with fullPage: false, which is usually small
enough, or to raise the ceiling.
call_webmcp_tool follows the same setting for a result too large to send
back, and only for one: a result within CUSTOMAISE_MCP_INLINE_MAX_KB always
comes back exactly as the page's tool returned it. Over it, file writes the
whole result to .customaise/tool-results/ in the workspace, which keeps the
newest 20, and returns the path with the result's small values (an id, a count,
a next step) so the agent can act without opening the file. inline returns it
in the response with long lists shortened. Neither asks for the tool to run
again, because running a page's tool again can repeat what it did.
Inline JSON responses are capped at CUSTOMAISE_MCP_INLINE_MAX_KB (64 KB by
default). Over the cap the payload is shortened by trimming lists, not by
truncating the JSON text, so what arrives still parses and still has every
key and nesting level. The response carries truncated: true and an
omitted array naming each shortened list and how many items it lost.
There is deliberately no client detection here. clientInfo.name is a
guessing game, and the roots capability says the client declares project
directories, not that the model can read them. It is also unavailable on
2026-07-28 connections. An explicit flag with a self-advertising
fallback beats a heuristic that is confidently wrong.
Source
This repository mirrors the package source from Customaise's own monorepo at each release.
Security Boundary
The MCP server listens on ws://localhost:4050 in plaintext on your loopback interface. The connection is authenticated by an HTTP Origin header allowlist:
Allowed:
chrome-extension://anmpijcpaobaabcdncjjmnhdeibipmko(production) andchrome-extension://ijjaffggglamocdapoihpkcpealflopp(staging). Chrome stamps this header automatically on WebSocket handshakes from extension service workers; you don't configure anything.Rejected: regular web pages (
https://...), unknown extension IDs, and handshakes with no Origin header. Returns HTTP 403.
What this stops: a malicious webpage opening new WebSocket('ws://localhost:4050') and calling WebMCP tools behind your back. This is the most likely abuse vector.
What this does NOT stop: a malicious native process running as your user. Node's ws client (and most HTTP libraries) lets callers forge any Origin header. If you can't trust processes running as your OS user, the threat model is already broader than this bridge.
Approval modes: tools whose effective permission remains prompt require your approval in the Customaise consent modal. The default mode follows saved tool rules. A user-enabled Full access grant can allow eligible Prompt tools in this browser profile, including new and updated tools, while saved Deny rules stay blocked.
Tools declared allow run without asking, with one exception that matters here: a script written through this bridge or the customaise CLI does not get to grant itself allow. Its self-declared allow resolves as prompt in the default mode. A saved user Allow override or a user-enabled Full access grant can permit the call without prompting; the script cannot create either grant itself. Choosing "Always allow" stores an override and it never prompts again. The MCP tool API cannot resolve the consent modal. Remote approvals route prompts away from the requesting browser, but the backend authenticates the signed-in account and accepts a client-supplied device claim; this is not proof of a separate human or physical device. An agent with account credentials or full OS access needs independent account/OS access restrictions.
Scripts you wrote yourself, and scripts you subscribed to from the marketplace, are unaffected: allow means allow. For marketplace scripts that means the old advice still holds, so only subscribe to AgentScripts from sources you trust.
Dev builds: if you load an unpacked extension with a custom key, set CUSTOMAISE_MCP_EXTRA_EXTENSION_IDS=<your-extension-id> in the MCP server's env.
Sharing scripts
Open Quick Actions → Share Script on an owned UserScript or AgentScript. Publish & share keeps the hosted, read-only subscription flow with publisher updates. Send creates a 24-hour link to an independent editable copy. Sending requires Power User; receiving works with a free signed-in account. There is no MCP/CLI Send or Publish command.
Send copies start disabled, keep their own edits and saved selectors, and remain after link expiry or Stop this send, without publisher updates. Refresh link for 24 hours replaces the active snapshot with the current saved script; merely opening or copying a URL does not extend its deadline. Anyone with the active link can preview source. Review source and selectors before sending: secrets embedded there remain included. Saved account keys, GM values, browser logins, tool approvals and Script Decisions provider choices are not copied. Each recipient configures their own access and provider. Fork a subscription before modifying or sending an independent copy.
CLI
Let an agent set up the CLI
In extension Settings → MCP & Terminal → Quick Setup → Terminal, copy the
setup prompt for Codex, Claude Code or another shell agent. The Grok Bot tab
has a prompt for installing the CLI on the Bot's own computer. Both prompts
verify Node.js, install the current published package, run doctor, add the
project primer with init, and read the conventions before script work.
The CLI guide and
Grok Bot guide provide the same prompts.
Terminal setup
For an agent with a terminal rather than an MCP client.
npm i -g @customaise/mcp # both binaries on PATH
customaise doctor # bridge, sign-in, tier, quota, and whether
# "Allow user scripts" is on. Costs no quota.
customaise init # writes AGENTS.md in this project, so the next
# agent finds the CLI without being toldcustomaise scripts list
customaise scripts install ./my-tool.agent.js
customaise scripts get mcp_script_123 -o ./my-tool.agent.js
customaise scripts enable mcp_script_123 # or disable
customaise scripts fork shared_abc -o ./mine.agent.js
customaise scripts rm mcp_script_123
customaise sync ./customaise-scripts # bulk export your scripts
customaise decisions # Script Decisions: agent access, keys, script states
customaise decisions set mcp_script_123 jev # needs Script Decisions on for agents; off always works
customaise tabs
customaise tab reload 42
customaise use --tab 42 # remember it for later commands
customaise tools # WebMCP tools on that tab
customaise call my_tool --args '{"q":"hi"}'
customaise context page # DOM snapshot
customaise shot -o ./page.png
customaise tab list # every short verb has a noun-verb form: tab list|shot|use
customaise schema # the whole command tree as JSON, for an agent to read
customaise daemon status | stopcustomaise use --tab N remembers the tab for the current working directory.
Bots sharing a directory can set distinct CUSTOMAISE_CLI_SCOPE values before
both use and later commands. Scheduled routines should pass --tab N explicitly
and verify the tab URL each run, since the browser itself remains shared and a
tab can close or navigate. This scoping does not isolate browser logins or files.
After upgrading from the former global remembered-tab file, select the tab once
in each workspace; the global choice is not copied into every Bot's workspace.
Without a global install, npx -p @customaise/mcp customaise <verb> works but
costs roughly half a second of package resolution per command against about
fifty milliseconds installed. For anything in a loop, install it.
Output contract. JSON on stdout, always, so it pipes. Diagnostics on
stderr. --pretty indents the JSON; -h or --help prints usage, and customaise schema prints the whole command tree as JSON for an agent to read. Exit codes are the interface:
Code | Meaning |
0 | success |
2 | usage error |
3 | daemon or extension unreachable, including after signing out or with "Allow user scripts" off |
4 | signed in, but the token expired or could not be refreshed |
5 | free-tier cap reached |
6 | consent denied, or a change only the person can make ( |
7 | consent expired unanswered |
8 | rejected by Customaise (diagnostics in the payload) |
Two things make 3 more common than it looks. Signing out of Customaise tears
the bridge down deliberately, so it reports 3, not 4. And the "Allow user
scripts" toggle on the Customaise card in chrome://extensions resets on every
Chrome restart; while it is off, scripts install fine and no tool ever
registers, so doctor reports 3 rather than claiming a healthy setup that
cannot run anything. 4 is the narrower case: the bridge is up and the token behind
it went stale. Both mean stop, and both are worth telling the user about, but
only 3 is worth checking Chrome over.
Codes 5, 6 and 7 are deliberately distinct: an agent that cannot tell a cap from a refusal from a timeout retries into a wall. Code 8 is the one to handle first when installing scripts: the sanitization pipeline refused the file and the diagnostics say what to change, where a 1 means something broke and rewriting the script will not help.
The daemon. Started on first use, and it holds the WebSocket to the
extension so commands do not each pay for a reconnect. It binds 127.0.0.1
only and authenticates the CLI with a token in a 0600 file that exists only
while the endpoint is live. customaise daemon stop ends it.
When several customaise-mcp processes share a machine, the first to bind
:4050 leads and the rest relay through it, so one extension serves every
IDE and every shell at once. That seam carries its own protocol version: a
process built against different frames is refused rather than served, with an
error naming both versions and which one to restart (-40033). Package
versions may differ freely; only a change to the frames themselves moves it.
A leader that sees a follower from a newer package steps down and rejoins
behind it, so a resident daemon can never pin the machine to an old version.
Custom HTTP clients: workspace and resource limits
The loopback daemon requires x-customaise-token and an absolute
x-customaise-workspace on every HTTP request, including negotiation.
The CLI supplies these automatically. A missing, relative or malformed workspace
returns HTTP 400 before dispatch; requests never inherit another caller's directory.
An explicitly declared filesystem root is honored, with ordinary filesystem
permissions still applying. This header chooses the output directory; it is not
an OS sandbox for clients that share the same daemon token.
For Unicode paths, send encodeURIComponent(absolutePath) as the workspace and
x-customaise-workspace-encoding: uri. The daemon decodes once; raw headers without
that encoding retain literal percent signs. New daemons advertise
workspaceEncoding: "uri" in daemon.json. The CLI uses that capability and asks
you to stop an older daemon before using a path it cannot represent safely.
The daemon admits at most 16 concurrent HTTP requests and remembers up to 256 workspaces active in the last 15 minutes. New requests above either limit receive HTTP 429 before tool dispatch. Uploads are limited to 8 MiB and 30 seconds; responses to 32 MiB cumulatively and requests to 10 minutes, including streamed output. These transport limits do not raise the smaller limits of individual tools. At most 64 TCP connections are accepted, with a 15-second header timeout. SSE progress streams immediately, and slow readers apply backpressure instead of causing the daemon to buffer the entire response.
An oversized upload receives HTTP 413; a stalled upload receives HTTP 408.
Pre-dispatch errors include outcome: "not_dispatched". Once a tool has been
submitted, a response failure or disconnect may leave its outcome unknown: check
what happened before retrying a mutating tool. If a response exceeds its limit
after streaming starts, the transport closes with an error rather than returning
a truncated success. Disconnects and the request deadline propagate cancellation;
a handler that ignores cancellation retains its admission slot until it settles,
so a stream of replacements cannot create unbounded background work.
Requirements
Node.js ≥ 20
Chrome 147 or later with Customaise (1.4.0 is the tested pair for 3.2.9), signed in, with Agent Bridge on.
Plan tiers
The Agent Bridge is free for any signed-in Customaise user. Free use is capped at 50 calls per UTC day and 150 calls per rolling 7-day window. Power User unlocks unlimited MCP. The cap covers every successful tool dispatch (built-in tools and WebMCP calls alike); failed calls and protocol-level traffic don't count.
When the cap fires, the server returns a JSON-RPC error with code -40029 and a human-readable message + structured data carrying scope, used/limit, and reset timestamp. IDEs that surface tool errors render the message verbatim. Sign-in is required regardless of tier; without a fresh Firebase ID token the server returns -40028 MCP_AUTH_REQUIRED. Branch on structuredContent.error.type, never on the number: the codes moved once already (3.2.0 took them out of the range the 2026-07-28 specification reserved for itself; the old -3202x values are still accepted from older extensions), the type strings did not.
Troubleshooting
"Customaise extension is not connected"
Make sure Chrome is running with the Customaise extension.
Check that Agent Bridge is on in Settings → MCP & Terminal.
The extension connects automatically within a few seconds.
Port conflict on 4050
The extension always connects to localhost:4050. Find what holds the port with
lsof -i :4050and stop it.CUSTOMAISE_WS_PORTis for tests.
Scripts not running after export
Call
reload_tabto trigger script re-injection.Check the
@matchpattern covers the current URL.
call_webmcp_tool hangs for minutes
The tool is
prompt-gated. The user has to approve in the browser, or remotely if Remote HITL Approvals is on. 5-minute budget before auto-deny. Surface a pending state rather than timing out.
call_webmcp_tool returned an error like "consent denied"
Expected when the user denied the modal, the 5-minute budget expired, or a previous "Always deny" override was set on that tool. The user can reset per-tool overrides in extension Settings.
list_webmcp_tools returns empty after a reload
Walk the conventions handbook's troubleshooting checklist. Check Chrome's Allow user scripts setting with
customaise doctor, the intended script's enable switch in Scripts, and whether its@matchcovers the URL. Reload the page after installing or changing the script. Seecustomaise://agentscript-conventionsfor the full list.
License
MIT
Available Tools
21 toolscall_webmcp_toolADestructive
Execute a registered WebMCP tool directly on the target browser tab. If the tool is interactive (trust level), the user will be natively prompted by CustomAIse to approve the execution before it returns. Approval can take minutes when the user is away from the browser (remote approvals on a phone). This server sends progress notifications while it waits, so a client that resets its timeout on progress will wait with it. A client that caps tool calls at a fixed 60 seconds regardless will report this call as failed while the user can still approve it and the tool can still run; if that happens, do not blindly re-issue a call with side effects. Check the outcome first with a read-only tool or the page itself. A result over 64 KB WRITES A FILE by default: the whole result goes to .customaise/tool-results/ in your workspace, which keeps the newest 20, and this call returns the path with the result's small values. If you have no filesystem tool, pass output: "inline" to get it in the response with long lists shortened instead.
| Name | Required | Description | Default |
|---|---|---|---|
| tabId | No | Tab ID to execute on. Defaults to active tab. | |
| output | No | Where a result over the inline budget (64 KB by default) goes; a smaller result always comes back in this response as the tool returned it. "file" (default) writes it whole to .customaise/tool-results/ in your workspace and returns its path, its small values and the size of the rest. "inline" writes nothing and returns it in this response, with long lists shortened to fit. Use it when you have no filesystem tool to read the file with, such as a chat client. "auto" follows the CUSTOMAISE_MCP_OUTPUT environment variable, falling back to "file". | |
| toolArgs | No | JSON object of arguments for the tool | |
| toolName | Yes | The EXACT name of the WebMCP tool to invoke |
close_tabADestructiveIdempotent
Close a specific browser tab. Defaults to the active tab if no tabId is provided.
| Name | Required | Description | Default |
|---|---|---|---|
| tabId | No | The ID of the tab to close |
delete_scriptADestructiveIdempotent
Permanently delete a script (UserScript or AgentScript) from Customaise. This action cannot be undone. NOTE: Shared/subscribed scripts cannot be deleted via MCP — the user must unsubscribe from the extension UI. Forks created via import_script(fork:true) are owned scripts and CAN be deleted via MCP.
| Name | Required | Description | Default |
|---|---|---|---|
| scriptId | Yes | The ID of the script to delete |
export_scriptADestructive
Export a script from a local file into Customaise. The file will be validated through Customaise's sanitization pipeline (syntax checking, AST validation, security analysis). If valid, the script is installed and ready to execute on matching pages. If invalid, detailed diagnostics explain exactly what to fix. Pass scriptId to update an existing script instead of creating a new one. Pass expectedCodeHash from import_script to reject stale edits. Save progress includes an operation ID and stage. A timeout may leave the outcome unknown: query get_bridge_status with the scriptId and operationId from the error before retrying. The extension enforces a 90-second save deadline and cancels work that has not reached persistence. A storage write already submitted cannot be recalled; its commit receipt resolves that uncertainty. For a script that uses CM_decisions, scriptDecisions in the result says whether its Script Decisions provider stays chosen for the new code, and if not, why and what to do. NOTE: You cannot overwrite a shared/subscribed script — they are read-only. If you need to edit a shared script, first call import_script with fork:true (creates an editable independent copy), then export to that copy's scriptId.
Reminder for new UserScripts: Prefer named functions in an IIFE for symbol-level editing; preserve valid imported source, `// @namespace https://customaise.com`, and standard directives (@name, @match, @grant).
Reminder for AgentScripts: MUST use `// ==AgentScript==` block, MUST explicitly declare tools via `// @webmcp <toolName> <permission>` (e.g. `// @webmcp my_tool prompt`). Permissions: allow (autonomous), prompt (interactive), deny (blocked). Prefer `prompt`: in a script you write, `allow` resolves as `prompt` before user grants are applied; a saved Allow rule or user-enabled Full access can permit it. Prefer named top-level functions and top-level tool registration for symbol editing; IIFEs are supported. CAN use GM_* APIs for persistence, networking, and observability alongside `document.modelContext.registerTool()`.| Name | Required | Description | Default |
|---|---|---|---|
| filePath | Yes | Local file path containing the userscript source code | |
| scriptId | No | ID of an existing script to update. Omit to create a new script. | |
| expectedCodeHash | No | SHA-256 from import_script. Reject the save if the installed source has changed since that read. |
focus_tabAIdempotent
Bring a specific browser tab to the front and make it active.
| Name | Required | Description | Default |
|---|---|---|---|
| tabId | Yes | The ID of the tab to focus |
get_bridge_statusARead-onlyIdempotent
Report the bridge's own state: whether the extension is attached, the plan tier, whether you are signed in, whether remote approvals are enabled, the browser's agent permissions (agentPermissions: Full access, and scriptDecisions, whether agents may choose Script Decisions providers), and how much of the MCP cap is left today and this week. Costs NO cap units. Without scriptId it reads cached bridge state; with scriptId it queries the browser for the latest save status and durable commit receipt. After a timeout, inspect that status before retrying. Unknown means no retained proof, not proof of failure. Check this before a long run so you find out you have three calls left now rather than mid-task.
| Name | Required | Description | Default |
|---|---|---|---|
| scriptId | No | Optionally inspect the latest save for this script; reads the browser without spending a cap unit. | |
| operationId | No | Save operation ID from export progress or a timeout. Requires scriptId. |
get_console_contextAIdempotent
Get console logs from the browser, including errors, warnings, and userscript GM_log output. Use after reload_tab to check for script runtime errors. WRITES A FILE by default: the full log data goes to .customaise/console-context.json in your workspace and this call returns counts plus the path. Read the file with view_file or grep_search. If you have no filesystem tool, pass output: "inline" to get the whole log in the response and write nothing to disk.
| Name | Required | Description | Default |
|---|---|---|---|
| level | No | Filter by log level. Default: all | |
| tabId | No | Tab ID to get logs from. Defaults to the active tab. | |
| output | No | Where the full payload goes. "file" (default) writes it to .customaise/ in your workspace and returns a summary plus the path, which keeps a large payload out of your context window. "inline" writes nothing and returns the whole payload in this response. Use it when you have no filesystem tool to read the file with, such as a chat client. "auto" follows the CUSTOMAISE_MCP_OUTPUT environment variable, falling back to "file". |
get_page_contextAIdempotent
Get a DOM snapshot of the current page including URL, title, page structure, and visible elements. Use this to understand the page layout before writing userscripts that manipulate it. WRITES A FILE by default: the full snapshot goes to .customaise/page-context.json in your workspace and this call returns a summary plus the path, so a large page does not fill your context window. Read the file with view_file or grep_search. If you have no filesystem tool, pass output: "inline" to get the whole snapshot in the response and write nothing to disk.
| Name | Required | Description | Default |
|---|---|---|---|
| tabId | No | Tab ID to inspect. Defaults to the active tab. | |
| output | No | Where the full payload goes. "file" (default) writes it to .customaise/ in your workspace and returns a summary plus the path, which keeps a large payload out of your context window. "inline" writes nothing and returns the whole payload in this response. Use it when you have no filesystem tool to read the file with, such as a chat client. "auto" follows the CUSTOMAISE_MCP_OUTPUT environment variable, falling back to "file". |
get_script_decisionsARead-onlyIdempotent
Read Script Decisions on this device: the typed decisions scripts make through @grant CM_decisions. Returns whether agents may manage it (agentAccess.scriptDecisions; the person turns it on under Full access in Customaise Settings, Agent permissions), sign-in and plan (Power User is required), whether this device is allowed (deviceEnabled) or paused (locallyPaused), which provider keys are saved, and every script that uses CM_decisions or has a provider: its provider (jev, openai-decisions or null) and state, one of ready, off, choose_again (its code or this device changed since the provider was chosen; reason says which), paused (pausedReason loop_repeat or loop_runaway) or invalid (issue). chosenByAgent marks a provider an agent chose. With scriptId it also returns that script's question lists (sets: hash, enabled, questions), the problems found in its code (issues, with line numbers) and today's decisions on this device (rowsToday). Use it before set_script_decisions, which names question lists by these hashes, and after export_script to check a script's provider. Reads only; nothing is sent to a provider. Needs extension 1.4.0 or later.
| Name | Required | Description | Default |
|---|---|---|---|
| scriptId | No | A script ID from list_scripts. Omit to list every script that uses CM_decisions or has a provider. |
get_selected_elementsAIdempotent
Get DOM elements that the user has visually selected in the browser for a specific script. Returns each selection's stable, tiered selectors, element context, and user comments. Returns the selections in this response, so it needs no filesystem access. WRITES FILES only when you pass writeFiles: true, which saves .dom.md context files under the directory you name. Use CM_findElement with the domId for precise targeting in scripts. When MCP is connected, .dom.md context files and screenshots are automatically pushed to the workspace (.customaise/dom-context//) in real-time as the user selects elements. Use this tool to retrieve selections if the auto-pushed files are missing or to get the raw JSON data.
| Name | Required | Description | Default |
|---|---|---|---|
| scriptId | No | Script ID to get selections for. Omit to get all scripts' selections. | |
| directory | No | Workspace directory for .dom.md files. Required if writeFiles is true. | |
| writeFiles | No | If true, writes .dom.md context files to the workspace directory. Default: false. |
import_scriptA
Import a Customaise script (UserScript or AgentScript) to a local file for editing. The file contains the full source with metadata block. After editing with your IDE tools, use export_script to push changes back.
Optional 'fork' flag (default false): when set to true, the script is FORKED into a new independent local copy BEFORE import, and the FORK is what gets written to the file. ALWAYS creates a new script — symmetric across source types, never a silent no-op:
Subscribed/shared sources: "Fork" verb. Clears the subscription link (no more publisher updates), captures forkedFrom lineage so a later publish can render "Forked from " on the marketplace.
Owned sources: "Duplicate" verb. Clears publishedShareId so the dup isn't tied to the original's published listing. Use when you want a remix while keeping the original intact. Forked/duplicated scripts land DISABLED in the user's library (D10 trust ceremony). The returned scriptId is the NEW script (not the original); the agent can immediately export back to it.
Without 'fork', subscribed scripts cannot be imported — they're read-only and the call refuses with a clear error pointing at fork:true. Owned scripts import normally (edit-in-place workflow).
IMPORTANT: Save files inside your current workspace or project directory (e.g., ./customaise-scripts/), never in /tmp.
| Name | Required | Description | Default |
|---|---|---|---|
| fork | No | When true, fork the script into a new editable copy and import THAT copy. Always creates a new script (Fork for shared sources, Duplicate for owned). Required for subscribed/shared scripts. Default false. | |
| filePath | Yes | Local file path inside your workspace to write the script to (e.g., ./customaise-scripts/my-script.agent.js). Do NOT use /tmp. | |
| scriptId | Yes | The ID of the script to import (get from list_scripts). When fork=true, this is the source script to fork from; the returned scriptId is the new fork. |
list_scriptsARead-onlyIdempotent
List all scripts (UserScripts & AgentScripts) installed in Customaise with their IDs, names, enabled status, match patterns, and whether they are shared (subscribed). Scripts marked isShared are read-only subscriptions — they cannot be imported, exported, or deleted directly. To edit a shared script, call import_script with fork:true (creates an independent editable copy). To uninstall a shared script, the user must unsubscribe from the extension UI.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
list_tabsARead-onlyIdempotent
List all open browser tabs with their IDs, URLs, titles, and active status. Use to find a specific tab ID for other tools like reload_tab or take_screenshot.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
list_webmcp_toolsARead-onlyIdempotent
List all WebMCP tools currently registered by AgentScripts for a specific browser tab. Use this to verify that an exported AgentScript is correctly registering its tools on the target page. Each entry carries a permission field (allow / prompt / deny) telling you what will happen BEFORE you call it: prompt blocks on an in-browser consent modal for up to 5 minutes, deny fails immediately. Read it and tell the user which calls will need their approval, rather than discovering it mid-run.
| Name | Required | Description | Default |
|---|---|---|---|
| tabId | No | Tab ID to query. Defaults to the active tab. |
open_tabA
Open a new browser tab with the specified URL. Defaults to opening in the background so the user is not snatched away from the tab they are currently viewing. Returns the new tab ID.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | The URL to open in the new tab | |
| active | No | Whether the new tab should become the active tab. Defaults to false (opens in background). Set to true only when the agent genuinely needs the new tab brought to focus. |
reload_tabAIdempotent
Reload a browser tab to re-inject updated userscripts. Use after export_script to see the effect of your changes. Waits for the page to fully load before returning. If the tab has AgentScript (WebMCP) tools registered, automatically waits for them to re-register before returning.
| Name | Required | Description | Default |
|---|---|---|---|
| tabId | No | Tab ID to reload. Defaults to the active tab. |
set_script_decisionsAIdempotent
Choose the Script Decisions provider for one script on this device: jev, openai-decisions (Decisions API), or off. Once a provider is chosen, the script's CM_decisions calls run without asking and are billed to the person's saved key for that provider, so choose one only when the person wants it. sets switches On exactly the question lists it names, by the hashes get_script_decisions returns for this scriptId, and every other list Off. Without sets, unchanged code keeps its On/Off choices and changed code switches every list On. Choosing a provider again also resumes a script the loop guard paused for repeating the same input (pausedReason loop_repeat).
Choosing jev or openai-decisions needs the person to have turned on Script Decisions under Full access in Customaise Settings, Agent permissions; only they can, in the extension. Switching a script off is always allowed. These stay with the person: provider keys, this device's Allow Script Decisions switch, daily limits, pausing this device, a script paused for a runaway loop (loop_runaway), and scripts shared with them. When the error type is person_required, tell the person the next step the message names and do not retry. Other refusals carry type rejected, not_found, auth_required or invalid_argument, with the precise reason in code. After service_unavailable or a timeout the outcome is uncertain: read the state with get_script_decisions before trying again. Returns the script's state as get_script_decisions does for one script. Needs extension 1.4.0 or later.
| Name | Required | Description | Default |
|---|---|---|---|
| sets | No | Hashes of the question lists to switch On, from get_script_decisions with this scriptId; every other list goes Off. Only with jev or openai-decisions. Omit to keep the current choices for unchanged code. | |
| provider | Yes | jev, openai-decisions (Decisions API), or off to switch the script provider off. | |
| scriptId | Yes | The script ID, from list_scripts or get_script_decisions. |
sync_scriptsADestructiveIdempotent
Bulk export all your own scripts from Customaise to a local directory as individual .user.js or .agent.js files. WRITES MANY FILES and OVERWRITES existing ones: a local file whose name matches a script is replaced by the copy held in Customaise, so unexported local edits in that directory are lost. Creates a .customaise-manifest.json mapping filenames to script IDs. Shared/subscribed scripts are excluded (they are read-only). Use this to set up a local workspace for editing scripts with your IDE.
| Name | Required | Description | Default |
|---|---|---|---|
| directory | Yes | Local directory to export scripts to (e.g., ./customaise-scripts/) |
take_screenshotA
Capture a screenshot of a browser tab without stealing focus from the user. Defaults to the visible viewport. Set fullPage: true to capture the entire scrollable page as one tall image. WRITES A FILE by default: the PNG is saved to filePath, or to an auto-generated path in the system temp directory when filePath is omitted, and this call returns that path rather than the image. If you have no filesystem tool, pass output: "inline" and the image is attached to this response instead, with nothing written to disk. For background tabs and full-page captures, Chrome briefly displays its standard yellow developer-tools notice at the top of the target tab during capture; it clears automatically when capture completes (typically under one second).
| Name | Required | Description | Default |
|---|---|---|---|
| tabId | No | Tab ID to screenshot. Defaults to the active tab. | |
| output | No | Where the full payload goes. "file" (default) writes it to filePath, or the system temp directory when filePath is omitted and returns a summary plus the path, which keeps a large payload out of your context window. "inline" writes nothing and returns the whole payload in this response. Use it when you have no filesystem tool to read the file with, such as a chat client. "auto" follows the CUSTOMAISE_MCP_OUTPUT environment variable, falling back to "file". | |
| filePath | No | Local file path to save the screenshot. Auto-generates a temp path if omitted. Ignored when output is "inline". | |
| fullPage | No | If true, capture the entire scrollable page (single tall PNG). If false or omitted, capture the visible viewport only. |
toggle_scriptAIdempotent
Enable or disable a userscript. Disabled scripts are not injected into matching pages. Use this to temporarily turn off a script without deleting it.
| Name | Required | Description | Default |
|---|---|---|---|
| enabled | Yes | true to enable, false to disable | |
| scriptId | Yes | The ID of the script to enable/disable |
toggle_uiAIdempotent
Show or hide the Customaise UI overlay on the active tab. Use this to make the Customaise interface visible or dismiss it — AI agents cannot click the extension icon directly. Optionally specify which panel to open.
| Name | Required | Description | Default |
|---|---|---|---|
| panel | No | Panel to open: "scripts", "chat", "settings" | |
| tabId | No | Tab ID to toggle UI on. Defaults to the active tab. |
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
3 tool updates
v3.2.9- Changed
call_webmcp_tool1 field changed- added
Input schema / properties / outputAdded value: +{ + "description": "Where a result over the inline budget (64 KB by default) goes; a smaller result always comes back in this response as the tool returned it. \"file\" (default) writes it whole to .customaise/tool-results/ in your workspace and returns its path, its small values and the size of the rest. \"inline\" writes nothing and returns it in this response, with long lists shortened to fit. Use it when you have no filesystem tool to read the file with, such as a chat client. \"auto\" follows the CUSTOMAISE_MCP_OUTPUT environment variable, falling back to \"file\".", + "enum": [ + "auto", + "file", + "inline" + ], + "type": "string" +}
- Added
get_script_decisions - Added
set_script_decisions
2 tool updates
v3.2.3- Changed
export_script1 field changed- added
Input schema / properties / expectedCodeHashAdded value: +{ + "description": "SHA-256 from import_script. Reject the save if the installed source has changed since that read.", + "pattern": "^[a-f0-9]{64}$", + "type": "string" +}
- Changed
get_bridge_status2 fields changed- added
Input schema / properties / operationIdAdded value: +{ + "description": "Save operation ID from export progress or a timeout. Requires scriptId.", + "maxLength": 128, + "minLength": 1, + "type": "string" +} - added
Input schema / properties / scriptIdAdded value: +{ + "description": "Optionally inspect the latest save for this script; reads the browser without spending a cap unit.", + "maxLength": 256, + "minLength": 1, + "type": "string" +}
19 tool updates
v3.2.0- First observed
call_webmcp_tool - First observed
close_tab - First observed
delete_script - First observed
export_script - First observed
focus_tab - First observed
get_bridge_status - First observed
get_console_context - First observed
get_page_context - First observed
get_selected_elements - First observed
import_script - First observed
list_scripts - First observed
list_tabs - First observed
list_webmcp_tools - First observed
open_tab - First observed
reload_tab - First observed
sync_scripts - First observed
take_screenshot - First observed
toggle_script - First observed
toggle_ui
TDQS
Scored across 21 tools
Most tools target a clearly distinct resource+action (tab ops, script lifecycle, context capture, Script Decisions, WebMCP). The main friction is the import_script/export_script pair, whose verbs are inverted relative to common intuition (import = download to local file, export = upload into Customaise), and sync_scripts is a bulk variant of the same flow, so an agent must read descriptions carefully. get_bridge_status vs get_script_decisions also overlap slightly on state reporting, but descriptions delineate them.
Every name is snake_case verb_noun (list_tabs, open_tab, close_tab, focus_tab, reload_tab, get_page_context, set_script_decisions, take_screenshot, call_webmcp_tool). The verb vocabulary is reused predictably across resources (list_/get_/toggle_/delete_). No camelCase or stylistic mixing anywhere.
21 tools is on the heavy side but the surface spans five genuine sub-domains (tab control, script lifecycle, page/console context, WebMCP execution, Script Decisions), roughly 4 tools each. Each tool maps to a distinct operation with no obvious redundancy, though the set is near the upper bound of comfortable scoping.
Script lifecycle is well covered (list, create/update via export, fork/duplicate via import, delete, toggle, bulk sync) and tab/context/WebMCP/Decisions all have read+act pairs. Minor gaps: no way to navigate an existing tab to a new URL, no publish/share-to-marketplace operation, and no direct inline source read without writing a file.
Maintenance
Related MCP Connectors
Dubsado MCP server for ChatGPT, Claude and any AI agent: create project, send form, send invoice, record payment and list unpaid invoices in your own Dubsado account. Cotlet works in the account through your Cloud Browser, a real Chrome where you sign in to Dubsado yourself; Cotlet does not store your password and you need no Dubsado API key. About the official Dubsado API: Dubsado has no public API (checked 11 Oct 2026). Its only official connection is Zapier, on the Premier plan: five triggers and one action, Create Project. Setup and FAQ: https://cotlet.dev/integrations/dubsado-api-mcp-server
ConnectWise MCP server for ChatGPT, Claude and any AI agent: list tickets, read ticket notes, update ticket, add ticket note, log time entry and create ticket in your own ConnectWise account. Cotlet works in the account through your Cloud Browser, a real Chrome where you sign in to ConnectWise yourself; Cotlet does not store your password and you need no ConnectWise API key. About the official ConnectWise API: ConnectWise PSA, formerly ConnectWise Manage, has a REST API, but no documented ConnectWise-hosted MCP server (checked 5 Nov 2026). To use the API you register on the ConnectWise Developer Network, get a ClientId and create an API member with a public and a private key. Setup and FAQ: https://cotlet.dev/integrations/connectwise-api-mcp-server
SuiteDash MCP server for ChatGPT, Claude and any AI agent: create contact, create project, create invoice, add task and send portal message in your own SuiteDash account. Cotlet works in the account through your Cloud Browser, a real Chrome where you sign in to SuiteDash yourself; Cotlet does not store your password and you need no SuiteDash API key. About the official SuiteDash API: SuiteDash has a Secure API for Super Admins and Admins, with monthly call caps, but its Zapier app only covers contacts, companies, projects and tasks (checked 11 Oct 2026). No official endpoint or Zapier action creates invoices, records payments, sends portal messages or shares files. Setup and FAQ: https://cotlet.dev/integrations/suitedash-api-mcp-server
Agile CRM MCP server for ChatGPT, Claude and any AI agent: get campaign report, add contacts to campaign, list contacts, add contact tags, list deals, move deal to milestone, add note and create task in your own Agile CRM account. Cotlet works in the account through your Cloud Browser, a real Chrome where you sign in to Agile CRM yourself; Cotlet does not store your password and you need no Agile CRM API key. About the official Agile CRM API: Yes, Agile CRM has a REST API on all plans, with a daily call cap by plan and no official MCP server (checked 22 Oct 2026). It covers contacts, companies, deals, tasks, notes, events, tracks and enrolling a contact in a campaign, but not campaign reports or bulk actions. Setup and FAQ: https://cotlet.dev/integrations/agile-crm-api-mcp-server
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceLets AI coding agents control and inspect a live Chrome browser via MCP, providing Chrome DevTools capabilities for automation, debugging, and performance analysis.17 npmApache 2.0
- AlicenseNot gradedqualityDmaintenanceBridges a browser extension with an AI agent via MCP, enabling the agent to capture and act on UI elements, styles, and accessibility data from web pages.18 npmISC
- AlicenseNot gradedqualityDmaintenanceLets AI coding assistants control and inspect a live Chrome browser through MCP, enabling reliable automation, debugging, and performance analysis using Chrome DevTools.1,868,745 npmApache 2.0
- AlicenseNot gradedqualityCmaintenanceConnects AI agents to your Chrome browser via MCP, enabling real-time control of existing tabs, sessions, and application state for development workflows.MIT