https://mcp.surfsky.io/mcp, so nothing is installed on your machine.
To build Surfsky into your own project instead, give your agent the setup prompt.
Connect to the hosted server
Add the server by its URL, with no token. The app opens a Surfsky page in your browser: sign in or sign up, check which app is asking, and click Allow. The app receives its own expiring token and never sees your API token.- Claude Code
- Cursor
- Codex
Claude and ChatGPT
Both apps add the server as a custom connector with the URLhttps://mcp.surfsky.io/mcp and send you through the same sign-in.
- Claude (claude.ai and Claude Desktop): in Customize > Connectors click Add, then Add custom connector, and enter a name and the URL. A connector added on claude.ai is available in Claude Desktop under the same account. In a Team or Enterprise organization an owner adds it under Organization settings > Connectors, and each member then clicks Connect.
- ChatGPT: on chatgpt.com/plugins click the plus button, choose Add custom MCP server, and enter a name and the URL. Your workspace’s policies decide whether custom servers are allowed.
With an API token
Scripts, CI and clients without the login send your API token as a bearer header. The server finds your account’s API host itself. ReplaceYOUR_API_TOKEN:
- Grok
- Claude Code
- Cursor
- Codex
- Other clients
Accounts on a development cluster are not served by the hosted server.
Connected apps
Every app you allowed is listed in the Connected apps card of the dashboard, under the API key, with the date you allowed it and when it was last used. The same app allowed on two machines is two entries.- Revoke cuts one app off. It is refused within an hour, and a browser it left running stops after five minutes without a tool call. The app can connect again by going through the sign-in.
- Regenerating the API key does not disconnect apps.
- An app that goes unused for 90 days expires and has to sign in again.
Run it locally
The local server runs on your machine withuvx and needs uv; uv downloads Python itself. Replace ... with your API token and base URL.
- Claude Code
- Claude Desktop, Cursor
- Codex
Tools
Steps
surfsky_act with steps runs a known sequence, such as filling a form and submitting it, in one call.
- It stops at the first step that fails. The error names the step and returns the page state and a snapshot.
- A call runs for up to 45 seconds, then stops and names the step it reached.
@Nreferences come from the snapshot before the call. After a step that changes the page, target later steps by CSS selector ortext=words. A reference whose element changed fails withstale_ref.
Bot challenges
surfsky_navigate makes one solve of a bot challenge page’s own widget before it returns. The result’s note says what happened:
Navigation never solves a captcha on an ordinary page.
Result size
find matches part of an element’s role, name, link or selector; a|b matches either term. surfsky_read with selector and limit returns the first matching elements, up to 100, as separate items.
Snapshots
A snapshot is text, one row per element:[@12] button "Search", with value, checked, options and disabled where present. A link’s href is listed only when another link has the same name. surfsky_snapshot with details: true adds every href and each row’s CSS selector.
Sessions
A session is one running browser. It is billed like any other browser, idle time included, and counts against your plan’s parallel browsers.surfsky_scrape goes through the Scraping API and starts no session.
On the hosted server:
- A session starts only when the agent calls
surfsky_session_start. Browser tools called before that fail withno_session. - A browser tool called without
session_iduses the session this connection last started. A client that keeps no connection uses the session its connected app started, or with an API token the only one running. With several sessions running, passsession_idon every browser call. - A session ends on
surfsky_session_stop, or after five minutes without a tool call, whether or not the client is still connected.idle_timeoutonsurfsky_session_startchanges the five minutes, up to an hour.
surfsky_session_start returns a live_url, a live view of the browser. When a page needs you (a login, a 2FA code, a captcha), the agent gives you this URL and waits instead of asking for credentials in chat. Anyone with the URL controls the browser.
To keep a login between runs, pass a persistent profile UUID to surfsky_session_start as profile_uuid.
Errors
Page content reaches the model inside an
<untrusted-page-content> block marked as data, not instructions. That does not stop every prompt injection: check what an action does before it submits a form or spends money.