Stop copy-pasting from Cursor into web forms.

How MCP and Chrome extensions unlock agentic form filling

FormFill AI · · 11 min read

Browser agents that click pixels are brittle. A tab code plus a field list gives Cursor or Claude a small, named capability instead of the whole browser.

Agentic form filling sounds like "let the model use the browser." That version is brittle. It clicks the wrong window, misses a label inside a web component, and treats Submit as just another button in the screenshot. The version that holds up is narrower: an assistant calls a tool, the tool returns the live fields for one tab, and a Chrome extension applies the values where you can see them.

What MCP is doing in this flow

MCP is the tool protocol Cursor, Claude, and similar clients already speak. FormFill's surface stays small on purpose. Identify a tab. Read its fields. Propose values. Later, the extension commits the fill. The model does not receive a general "control this user's browser" capability.

That limit is the product. A tool that can return a field list for a code you typed is easy to explain to a teammate. A tool that can click anything on screen is not, and you will not want to leave it running while you are signed into payroll.

Why a tab code, not "the current tab"

People keep many windows. "Fill the form" is ambiguous the moment a docs tab and an admin tab are both in front of you. The extension popup shows a short code, such as 4F2K, tied to one URL. You say that code in chat. The agent repeats the host it is about to touch. If the code and the URL disagree, the fill pauses.

The code is also a capability boundary. Knowing 4F2K lets the agent read that session. It does not let the agent enumerate every tab you have open. When the session expires or you close the tab, the code stops meaning anything.

A small tool shape

You do not need a large schema to get a useful proposal. Three calls cover the v1 loop. Names here are illustrative of the contract, not a promise that every client spells them the same way.

get_session
  tab_code: 4F2K
  -> url, created_at

propose_fill
  tab_code: 4F2K
  page_url: https://partners.shopify.com/...
  instructions: use only URLs from README.md
  fields: [{ name, label, type, required }]
  -> values[{ field, value, confidence }]
  -> pauses[{ field, reason }]

commit_fill
  handled in the extension after you press Fill form
  the model does not submit the page

The worker stores the session and the fill job. It checks the license that Lemon Squeezy or Gumroad wrote. It does not need to see your Chrome cookies. The model key, whether you brought it or Pro routes it, stays off the page.

Split the work on purpose

  • The model maps intent and source text onto field names, and it marks confidence. It is good at that and bad at knowing which DOM node will accept a change event.
  • The extension detects inputs, dispatches input and change events, scrolls fields into view, animates the fill, shows undo, and refuses captcha widgets.
  • You confirm the host, edit low-confidence rows in the side panel, and decide to submit. That last step is not a tool.

Confirm the URL before any keystroke

Lookalike admin panels are common enough that "the tab I think this is" is not a check. The extension should show the host in the popup and again in the side panel. If the tab navigated after the session was created, that is a url_mismatch pause, not a best-effort fill. Phishing pages love a tool that types as soon as it sees a password field. FormFill treats password-shaped fields as sensitive and leaves them empty.

Pause reasons worth showing in the panel

  • low_confidence: a draft exists, but you should read it. Over-long taglines land here.
  • missing_required: the source text never answered this question. Do not let the model improvise.
  • captcha: a human, on this page, right now.
  • sensitive: passwords, API keys, card numbers, government IDs.
  • url_mismatch: the tab is not the host the session was opened on.
  • unknown_tab: the code was never registered by the extension.

Cursor, Claude, and Codex can share the code

The tab code is not a Cursor feature. It is a name for a Chrome tab. Any client that can call the MCP tools can request a proposal. Claude can do that when the connector is installed. Codex and ChatGPT can do it when an MCP connector is available. Until a given client speaks MCP, the side panel still lets a person apply a proposal they pasted from chat. The extension does not care which window the sentences came from.

If you want a concrete page to try the loop on, the Shopify Partner walkthrough stays on public listing copy and spells out what not to send.

What v1 deliberately does not do

There is no websocket relay yet. A Durable Object is the planned home for a live channel between the extension and a waiting agent, so field changes could stream instead of round-tripping through propose. v1 is request and response: the extension registers a session, the agent proposes, the extension fills. That is enough to delete the paste loop. It is not enough to justify giving an agent a long-lived browser socket.