Skip to main content
Glama

Why

Tampermonkey is great until you want your agent to help. graft keeps the userscript model (plain files, @match headers) and adds:

Tampermonkey

graft

Edit loop

edit in a browser box

edit a file in your editor β†’ page updates instantly

Coding agent can drive it

no

yes, via MCP (12 tools)

Agent can see the page

no

DOM outline, screenshot, console, network

Cross-origin fetch

GM_xmlhttpRequest

graft.fetch()

Intercept page fetch/XHR

no

graft.net.onRequest / onResponse

Strict-CSP sites

often blocked

persistent scripts ignore CSP

Old GM_* scripts

yes

yes, unchanged

Rebuild to change code

no

no

Related MCP server: browser-relay

Install (2 minutes)

git clone https://github.com/shahaklt/graft && cd graft && npm install
node bin/graft.mjs path        # prints the extension folder
  1. Open chrome://extensions, enable Developer mode, Load unpacked β†’ the extension/ folder. (One time. You never rebuild or repack after this.)

  2. On graft's extension card, switch on Allow User Scripts (lets persistent scripts ignore page CSP; without it graft falls back to eval).

  3. Add the MCP server to your agent:

# Claude Code
claude mcp add graft -- node /absolute/path/to/graft/bin/graft.mjs mcp
# or straight from GitHub
claude mcp add graft -- npx -y github:shahaklt/graft mcp

Cursor / Claude Desktop (mcpServers JSON):

{ "mcpServers": { "graft": { "command": "npx", "args": ["-y", "github:shahaklt/graft", "mcp"] } } }

Codex: codex mcp add graft -- npx -y github:shahaklt/graft mcp

  1. Try it. Open http://127.0.0.1:7777/playground (served by the hub once running) and ask your agent: "outline the playground page, add a todo, then make the heading green and keep it as a script."

No agent? Run just the hub and hand-write scripts: node bin/graft.mjs dev ./my-scripts.

Writing scripts

~/.graft/scripts/hello.graft.js (or any folder via graft dev <dir>):

// ==Graft==
// @name   Hello
// @match  https://*.example.com/*
// @run-at document-idle
// ==/Graft==
graft.css(`body{outline:3px solid #9fe870}`);
graft.on('a.buy', el => el.textContent = 'buy (graft)');   // current + future elements
graft.toast('hello 🌱');

Save the file β†’ every open matching tab re-runs it. graft.css, graft.on, graft.toast, graft.panel and graft.net.* handlers are auto-cleaned on hot reload; register your own with graft.cleanup(fn).

The graft object (in scope in every script, never on window)

API

graft.$ / $$

querySelector helpers

graft.css(text)

inject style, returns remover

graft.waitFor(sel, {timeout})

promise for an element

graft.on(sel, cb)

run for existing + future matches

graft.el(tag, props, ...kids)

build DOM

graft.toast(msg) / graft.panel({title, html})

shadow-DOM UI, immune to page CSS

graft.fetch(url, init)

cross-origin request via the extension (.ok .status .text() .json())

graft.net.onRequest(fn) / onResponse(fn) / log()

watch & rewrite page fetch/XHR

graft.store.get/set/del/keys

persistent per-script storage

graft.notify(title, msg)

desktop notification

graft.cleanup(fn)

run on hot reload

Tampermonkey headers (==UserScript==, @match, @exclude, @run-at) and GM_addStyle / GM_getValue / GM_setValue / GM_xmlhttpRequest / GM_notification / GM_log / unsafeWindow work too. See examples/scripts.

MCP tools

tool

what

graft_status

is the extension connected, which mode, where scripts live

graft_list_tabs

tabs + ids

graft_eval

run JS in the page, get JSON back (expression or statements + return, top-level await)

graft_dom

outline of interactive elements with selectors / html / text

graft_act

click, type (framework-safe), press, scroll

graft_screenshot

PNG of the tab

graft_navigate

go to a URL

graft_get_logs

console + uncaught errors, or network requests

graft_install_script

persist a script (hot-reloaded into open tabs)

graft_list_scripts / graft_read_script / graft_remove_script

manage scripts

How it fits together

 coding agent ──stdio/MCP──▢ graft mcp ─┐
                                        β”œβ”€β–Ά hub (127.0.0.1:7777) ──ws──▢ extension ──▢ your tabs
 ~/.graft/scripts/*.graft.js ──watchβ”€β”€β”€β”€β”˜

Multiple agents can share one hub: the first process starts it, later ones attach over /rpc.

Security model

  • Hub binds 127.0.0.1 only. The extension socket rejects any browser Origin other than chrome-extension://; /rpc rejects every browser origin.

  • Privileged calls (graft.fetch, store, notify) cross from the page to the extension over CustomEvents whose names contain a per-session secret. The graft object is never exposed on window.

  • Residual risk: a hostile page that monkey-patches EventTarget before graft loads could try to sniff that secret. Don't run graft-privileged scripts on pages you don't trust.

  • Scripts you install run with full access to every site they match. Read them. graft_eval gives your agent the same power on any open tab, so only connect agents you trust.

  • Optional debugger permission (requested from the popup) lets one-off eval work on strict-CSP pages; Chrome shows a "debugging" banner while it runs.

Limits

Chrome / Chromium (MV3, β‰₯120) only for now. No chrome:// pages or the Web Store. Page eval on strict-CSP sites needs the debugger permission or a persistent script.

Develop

npm test                     # protocol smoke test (fake extension)
node scripts/make-icons.mjs  # regenerate extension icons

Branding and UI spec for designers: docs/DESIGN-BRIEF.md. Landing page: docs/index.html.

MIT

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    An MCP server for browser automation and console log capture via a Chrome extension, enabling AI-driven DOM interaction, navigation, and screenshot capabilities.
    2
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    MCP server that drives a user's real Chrome browser via a WebSocket-connected MV3 extension, enabling tab management, navigation, page interaction, screenshots, and script evaluation through natural language.
    15 npm
    MIT
  • F
    license
    Not graded
    quality
    A
    maintenance
    Enables AI agents to control a persistent local browser with live tabs, navigation, interaction, inspection, and state management through MCP.
    6
    -