Let your AI run the browser.
Connect Claude, Cursor or any MCP client to SmartMacros. The AI writes macros, runs them with your data, reads the results and fixes steps when a page changes.
- Your AI clientClaude Desktop, Claude Code, Cursor
- MCP
- smartmacros-mcpSmall bridge the client starts with npx
- 127.0.0.1 + token
- SmartMacros in ChromeRecords, runs and repairs on your pages
Set up in three steps
You need Node.js 18 or newer. The bridge installs itself the first time your AI client starts it.
Switch on AI access
SmartMacros side panel, Settings, AI access, Allow AI clients. A pairing token appears.
Copy the config
Press the config button next to the token. Your token is already filled in.
Paste and restart
Put it into your AI client, below, and restart it. Settings shows "connected".
Settings, Developer, Edit config. Paste into claude_desktop_config.json, then restart Claude.
{
"mcpServers": {
"smartmacros": {
"command": "npx",
"args": [
"-y",
"smartmacros-mcp"
],
"env": {
"SMARTMACROS_TOKEN": "paste your token"
}
}
}
}Run once in a terminal.
claude mcp add smartmacros -e SMARTMACROS_TOKEN=<your token> -- npx -y smartmacros-mcp
Paste into .cursor/mcp.json in your project, or Settings, MCP, Add server.
{
"mcpServers": {
"smartmacros": {
"command": "npx",
"args": [
"-y",
"smartmacros-mcp"
],
"env": {
"SMARTMACROS_TOKEN": "paste your token"
}
}
}
}Any client that starts MCP servers over stdio takes the same block in its MCP servers file.
{
"mcpServers": {
"smartmacros": {
"command": "npx",
"args": [
"-y",
"smartmacros-mcp"
],
"env": {
"SMARTMACROS_TOKEN": "paste your token"
}
}
}
}Then just ask
You do not call commands yourself. Say what you want and the AI picks them. Click a prompt to copy it.
Create
Run
Drive the browser
Check up
Command reference
The 16 commands the AI can call, in four groups. Open one to see its arguments and an example.
Macros
Read and write the macros saved in SmartMacros.
list_macrosAll macros saved in SmartMacros with id, name, start URL, step count, data rows and last run status.
You sayWhat macros do I have in SmartMacros?
All macros saved in SmartMacros with id, name, start URL, step count, data rows and last run status.
No arguments.
Call
{}Result
[
{
"id": "m_k2f9",
"name": "Add lead to CRM",
"startUrl": "https://crm.northwind.io/leads/new",
"steps": 7,
"rows": 6,
"lastRun": {"status": "fix"}
}
]get_macroFull JSON of one macro: steps with their locators, data source, variables, triggers.
You sayShow me the steps of the Add lead to CRM macro.
Full JSON of one macro: steps with their locators, data source, variables, triggers.
| Argument | Type | Meaning | |
|---|---|---|---|
id | string | required | Macro id from list_macros |
Call
{"id": "m_k2f9"}Result
{
"id": "m_k2f9",
"name": "Add lead to CRM",
"steps": [
{"type": "navigate", "value": "https://crm.northwind.io/leads/new"},
{
"type": "type",
"label": "Enter '{{email}}' in Email",
"target": {
"locators": [{"kind": "id", "value": "#email"}]
}
}
]
}create_macroSaves a new macro.
You sayMake a macro that adds a lead to crm.northwind.io from a name and an email.
Saves a new macro. Read smartmacros://guide first. Steps need only type, target (locators), value and options; ids, labels and defaults are filled in by SmartMacros.
| Argument | Type | Meaning | |
|---|---|---|---|
name | string | required | Name shown in SmartMacros |
startUrl | string | optional | Page where the task starts |
steps | step[] | required | Steps in order; usually begins with a navigate step |
dataSource | table | optional | Table of rows to repeat the macro over |
vars | object | optional | Fixed variables, used as {{name}} |
tags | string[] | optional | Labels for searching in the side panel |
Call
{
"name": "Add lead to CRM",
"startUrl": "https://crm.northwind.io/leads/new",
"steps": [
{"type": "navigate", "value": "https://crm.northwind.io/leads/new"},
{
"type": "type",
"target": {
"locators": [{"kind": "label", "value": "Email"}]
},
"value": "{{email}}"
},
{
"type": "click",
"target": {
"locators": [
{"kind": "text", "value": "Save lead", "tag": "button"}
]
}
}
],
"dataSource": {
"columns": ["email"],
"rows": [["jane@brightsupply.co"]]
}
}Result
{
"saved": {"id": "m_k2f9", "name": "Add lead to CRM", "steps": 3, "rows": 1},
"steps": [
"1. Open crm.northwind.io/leads/new",
"2. Enter '{{email}}' in Email",
"3. Click on 'Save lead' button"
]
}update_macroReplaces the given fields of an existing macro.
You sayAdd a step to that macro that ticks the consent box before saving.
Replaces the given fields of an existing macro. Pass steps to replace the whole step list; pass dataSource to replace the data rows.
| Argument | Type | Meaning | |
|---|---|---|---|
id | string | required | Macro id from list_macros |
name | string | optional | New name |
startUrl | string | optional | New start page |
steps | step[] | optional | Replaces the whole step list |
dataSource | table | optional | Replaces the data rows |
vars | object | optional | Replaces the fixed variables |
tags | string[] | optional | Replaces the tags |
Call
{"id": "m_k2f9", "name": "Add lead to CRM (EU)"}Result
{
"saved": {"id": "m_k2f9", "name": "Add lead to CRM (EU)", "steps": 3}
}delete_macroDeletes a macro permanently.
You sayDelete the macro called Old price check.
Deletes a macro permanently.
| Argument | Type | Meaning | |
|---|---|---|---|
id | string | required | Macro id from list_macros |
Call
{"id": "m_k2f9"}Result
{"deleted": "m_k2f9"}Runs
Start a macro, follow it, answer when it waits, stop it.
run_macroRuns a saved macro in Chrome.
You sayRun Add lead to CRM for these five people.
Runs a saved macro in Chrome. mode 'once' runs it one time, 'rows' once per data row. With wait=true (default) the call returns when the run finishes or needs the user, with per-row results, variables and repairs.
| Argument | Type | Meaning | |
|---|---|---|---|
id | string | required | Macro id from list_macros |
mode | "once" | "rows" | default "once" | once = one run, rows = once per data row |
data | table | optional | Rows to use for this run only; leaves the saved macro unchanged |
wait | boolean | default true | false returns at once; follow the run with run_status |
timeoutSeconds | number | default 600 | How long to wait for the run to finish |
Call
{"id": "m_k2f9", "mode": "rows"}Result
{
"status": "finished",
"rows": 6,
"rowStatus": ["done", "done", "healed", "done", "done", "done"],
"repairs": 1,
"results": [
{
"row": 1,
"status": "done",
"values": {"ticket": "T-1042"}
}
],
"log": ["ok: Run finished, 1 repair"]
}run_statusState of the current or last run: status, row, step, repairs, variables, whether it waits for the user, last log lines.
You sayHow is the run going?
State of the current or last run: status, row, step, repairs, variables, whether it waits for the user, last log lines.
No arguments.
Call
{}Result
{
"status": "running",
"macroName": "Add lead to CRM",
"row": 3,
"rows": 6,
"stepIndex": 4,
"stepCount": 7,
"repairs": 1,
"needsUser": null
}answer_runWhen run_status shows status waiting_user: retry the step, skip it, skip the row, continue after a pause, or stop.
You saySkip that row and keep going.
When run_status shows status waiting_user: retry the step, skip it, skip the row, continue after a pause, or stop. Picking an element on the page needs the user.
| Argument | Type | Meaning | |
|---|---|---|---|
choice | "retry" | "skip" | "skipRow" | "continue" | "stop" | required | retry the step, skip it, skip the rest of this row, continue after a pause, or stop the run |
Call
{"choice": "skipRow"}Result
{"status": "running", "row": 4, "rows": 6}stop_runStops the current run.
You sayStop the run.
Stops the current run. Rows already finished stay finished.
No arguments.
Call
{}Result
{"status": "finished", "aborted": true}Browser
Look at the open page and act on it without saving a macro.
open_tabOpens a URL in a new tab and makes it active.
You sayOpen the supplier portal.
Opens a URL in a new tab and makes it active. Returns the tab id for page_snapshot and find_elements.
| Argument | Type | Meaning | |
|---|---|---|---|
url | string | required | Address to open |
Call
{"url": "https://portal.brightsupply.co/catalog"}Result
{
"tabId": 412,
"title": "Catalog",
"url": "https://portal.brightsupply.co/catalog"
}page_snapshotTitle, URL, visible text and the interactive elements of the active tab (or tabId), each with a ready-to-use locator.
You sayLook at the page I have open. What can you fill in?
Title, URL, visible text and the interactive elements of the active tab (or tabId), each with a ready-to-use locator. Use it before writing steps for a page.
| Argument | Type | Meaning | |
|---|---|---|---|
tabId | number | optional | Tab from open_tab; the active tab when omitted |
maxElements | number | default 120 | Most interactive elements to return |
textChars | number | default 3000 | How much of the visible page text to return |
Call
{"maxElements": 40}Result
{
"title": "New lead",
"url": "https://crm.northwind.io/leads/new",
"text": "New lead Full name Email ...",
"elements": [
{
"tag": "input",
"type": "email",
"label": "Email",
"locators": [
{"kind": "id", "value": "#email"},
{"kind": "label", "value": "Email"}
]
}
]
}find_elementsFinds elements on the active tab (or tabId) that match a description such as 'email field' or 'Save button', scored, each with locators to put into a step target.
You sayFind the Export button on this page.
Finds elements on the active tab (or tabId) that match a description such as 'email field' or 'Save button', scored, each with locators to put into a step target.
| Argument | Type | Meaning | |
|---|---|---|---|
description | string | required | Plain words, e.g. 'email field' or 'Save button' |
tabId | number | optional | Tab from open_tab; the active tab when omitted |
max | number | default 5 | Most candidates to return |
Call
{"description": "Save button"}Result
[
{
"score": 1,
"kind": "button",
"text": "Save lead",
"locators": [
{"kind": "id", "value": "#save-lead"},
{"kind": "text", "value": "Save lead", "tag": "button"}
]
}
]run_stepsRuns a list of steps in the active tab (or at url) without saving a macro.
You sayFill this form with my details and press Save. Do not save a macro.
Runs a list of steps in the active tab (or at url) without saving a macro. Use it to control the browser directly: open a page, fill a form, read values. Same executor and repairs as saved macros.
| Argument | Type | Meaning | |
|---|---|---|---|
steps | step[] | required | Steps to run now, in order |
url | string | optional | Open this URL first |
vars | object | optional | Variables for {{name}} in the steps |
timeoutSeconds | number | default 300 | How long to wait for the steps to finish |
Call
{
"url": "https://example.com/search",
"steps": [
{
"type": "type",
"target": {
"locators": [{"kind": "css", "value": "input[type=search]"}]
},
"value": "smartmacros",
"options": {"pressEnter": true}
},
{
"type": "extractList",
"target": {
"locators": [{"kind": "css", "value": ".results h3"}]
},
"value": "titles"
}
]
}Result
{
"status": "finished",
"repairs": 0,
"vars": {"titles": ["First result", "Second result"]}
}History and status
What ran, what was repaired, and whether the link is up.
list_runsRecent runs with macro name, rows done, repairs and results.
You sayWhat ran today, and did anything fail?
Recent runs with macro name, rows done, repairs and results.
| Argument | Type | Meaning | |
|---|---|---|---|
limit | number | default 20 | Most runs to return, newest first |
Call
{"limit": 2}Result
[
{
"macroName": "Add lead to CRM",
"rows": 6,
"done": 6,
"failed": 0,
"repairs": 1,
"aborted": false
}
]list_repairsSteps SmartMacros repaired: macro, step, old and new locator, who solved it, confidence.
You sayWhich steps did SmartMacros repair this week?
Steps SmartMacros repaired: macro, step, old and new locator, who solved it, confidence.
| Argument | Type | Meaning | |
|---|---|---|---|
limit | number | default 30 | Most repairs to return, newest first |
Call
{"limit": 1}Result
[
{
"macroName": "Add lead to CRM",
"step": 3,
"stepLabel": "Enter '{{email}}' in Email",
"by": "heuristic",
"from": "#email",
"to": "#fld-7f3a",
"confidence": 0.79,
"status": "saved"
}
]connection_statusWhether the SmartMacros extension is connected to this bridge, and its build.
You sayAre you connected to SmartMacros?
Whether the SmartMacros extension is connected to this bridge, and its build.
No arguments.
Call
{}Result
{"connected": true, "extensionBuild": "0.4.0", "port": 37421}You stay in control
- Off until you switch it on, off again in one click
- Only clients with your token connect. A new token locks everyone out.
- Steps that delete, pay or confirm always ask you first
- Every run is in History, every repair can be undone
When it does not connect
Settings says "waiting for the bridge"
The AI client has not started the bridge yet. Restart the client after adding the config and check node --version shows 18 or newer.
The AI says SmartMacros is not connected
Chrome must be open with AI access switched on, and the token in the client config must match the one in Settings. After making a new token, update the config.
Port already in use
Another bridge is running. Close it, or set SMARTMACROS_PORT in the client config and the same number under Settings, AI access, Port.
Does it work with ChatGPT?
Not yet. ChatGPT only accepts hosted MCP servers, and SmartMacros keeps everything on your machine.
For AI agents and developers
The same reference in formats a model can read. All three are generated from the bridge's own tool definitions.
mcp-guide.md
How to work with the server, every command in one line, the step format with examples. Also served by the bridge as smartmacros://guide.
mcp-tools.json
Every command with its full JSON Schema, grouped, plus the install block.
llms.txt
Index of this site for language models, pointing at the two files above.