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.

Runs on your computer onlyPaired with a tokenOff until you switch it on
  1. Your AI clientClaude Desktop, Claude Code, Cursor
  2. MCP
  3. smartmacros-mcpSmall bridge the client starts with npx
  4. 127.0.0.1 + token
  5. 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.

1

Switch on AI access

SmartMacros side panel, Settings, AI access, Allow AI clients. A pairing token appears.

2

Copy the config

Press the config button next to the token. Your token is already filled in.

3

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.

ArgumentTypeMeaning
idstringrequiredMacro 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.

ArgumentTypeMeaning
namestringrequiredName shown in SmartMacros
startUrlstringoptionalPage where the task starts
stepsstep[]requiredSteps in order; usually begins with a navigate step
dataSourcetableoptionalTable of rows to repeat the macro over
varsobjectoptionalFixed variables, used as {{name}}
tagsstring[]optionalLabels 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.

ArgumentTypeMeaning
idstringrequiredMacro id from list_macros
namestringoptionalNew name
startUrlstringoptionalNew start page
stepsstep[]optionalReplaces the whole step list
dataSourcetableoptionalReplaces the data rows
varsobjectoptionalReplaces the fixed variables
tagsstring[]optionalReplaces 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.

ArgumentTypeMeaning
idstringrequiredMacro 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.

ArgumentTypeMeaning
idstringrequiredMacro id from list_macros
mode"once" | "rows"default "once"once = one run, rows = once per data row
datatableoptionalRows to use for this run only; leaves the saved macro unchanged
waitbooleandefault truefalse returns at once; follow the run with run_status
timeoutSecondsnumberdefault 600How 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.

ArgumentTypeMeaning
choice"retry" | "skip" | "skipRow" | "continue" | "stop"requiredretry 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.

ArgumentTypeMeaning
urlstringrequiredAddress 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.

ArgumentTypeMeaning
tabIdnumberoptionalTab from open_tab; the active tab when omitted
maxElementsnumberdefault 120Most interactive elements to return
textCharsnumberdefault 3000How 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.

ArgumentTypeMeaning
descriptionstringrequiredPlain words, e.g. 'email field' or 'Save button'
tabIdnumberoptionalTab from open_tab; the active tab when omitted
maxnumberdefault 5Most 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.

ArgumentTypeMeaning
stepsstep[]requiredSteps to run now, in order
urlstringoptionalOpen this URL first
varsobjectoptionalVariables for {{name}} in the steps
timeoutSecondsnumberdefault 300How 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.

ArgumentTypeMeaning
limitnumberdefault 20Most 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.

ArgumentTypeMeaning
limitnumberdefault 30Most 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.