Concepts
What Is an MCP Server for Web Browsing?
MCP (Model Context Protocol) is an open protocol that lets an AI agent call tools rather than only generate text. An MCP server for web browsing applies the protocol to websites. It exposes a small tool set that an agent uses to open a site, act on it, and read results as structured data while the browser runs behind the server.
This page defines the category, describes what the server does, and identifies the difference between a demo and production infrastructure. Rindler's hosted server at mcp.rindler.ai is the running example because it is live and available for agent connections today. The same anatomy applies to the category as a whole.
MCP, defined
The Model Context Protocol is an open standard for connecting AI agents to tools and data outside the model. An MCP server is a service that exposes tools an AI agent can call over the protocol. The agent can take actions instead of only chatting. Each tool has a name, a description, and a typed parameter schema. The agent's runtime, the MCP client, lists the tools, reads the schemas, and calls them like functions.
MCP does not define what the tools must do. There are MCP servers for databases, file systems, ticket queues, and internal APIs. A web-automation MCP server is one type: its tools operate websites. It is a server, not an SDK, so there is no client library to install, and any MCP-capable agent can connect. Rindler's runs at https://mcp.rindler.ai. Your agent connects over HTTP and authenticates on first use with OAuth 2.0 PKCE. No API key, no manual credential paste.
What a web-automation MCP server does
Servers in this category have three core responsibilities.
First, the server turns a website into tools an agent can call. Rindler's session loop uses four tools. start_session opens a site and returns the landing screen with a session_id and an available_actions array. Each action carries a name, a description, and a params schema. dispatch_action executes one of those actions. extract_content re-reads the current screen as structured records. close_session releases the browser when the task is done. The loop is explicit: read available_actions, dispatch one, read the new screen's actions, repeat.
Second, the server returns structured results instead of pages. Every response carries a screen identifier, persistent context such as cart contents or a delivery address, screen-specific data, and the actions valid from that screen. Your agent reads fields, not markup. A Rindler tool call typically returns structured JSON sized in the hundreds of tokens. A raw fetch of the same page is typically 50,000+ tokens of nav, footer, sidebar, and tracking noise around the actual data. Here is a dispatch_action call and its response:
// Request
{
"name": "dispatch_action",
"arguments": {
"session_id": "sess_a1b2c3",
"action": "search",
"params": { "query": "bean boots" }
}
}
// Response
{
"data": {
"listings": [
{ "title": "Bean Boots", "price": "$109", "url": "/p/bean-boots" }
]
}
}
Third, the server holds session state. The session_id names a live browser session managed on the server. State your agent needs later, such as what is in the cart, persists in context across calls instead of being re-scraped from each page. When the task is finished, close_session frees the browser immediately. It is a safe no-op if the session already ended.
The running example: Rindler's tool surface
The four session tools cover most tasks. The rest of the surface handles documents, sign-in, and continuity:
- extract_document reads the text of a PDF linked from a page, returning text per page plus page_count, with query and pages parameters to narrow a long catalog before reading. It fetches anonymously and sends no cookies, so it reads only what a signed-out visitor could read.
- get_auth_url generates an OAuth 2.0 PKCE authorization URL for a site.
- await_auth blocks until the user has finished signing in to a gated site. Each call long-polls up to a bounded wait (default 30 seconds, max 120) and returns status "pending" or "captured".
- manage_cookies lists the sites a user is signed into and clears saved logins. It returns only metadata, never credential or cookie values.
- memory stores and recalls durable agent memory across runs: remember, recall, forget.
- synthesize_schema converts recorded overlay telemetry into a stored action schema, the machinery for teaching the server a new action.
The surface has no click(x, y), no fill-a-selector, and no run-JavaScript. The server manages browser sessions and structured data extraction so agents never touch raw HTML or CSS selectors.
What makes a web MCP server production-grade
Any wrapper around a browser can expose a click tool. The gap between a demo and infrastructure shows up in four areas.
Deterministic actions. The same call against the same site should return the same response shape across runs, independent of DOM changes, popups, or A/B-tested layouts. Rindler enforces this on both sides. The agent may only use action names from the most recent response, must pass params exactly as each action's schema describes, and never invents action names, constructs URLs, or references CSS selectors. A site mapping ships only after an automated verifier has passed it against the real site.
Extraction schemas instead of raw page dumps. A production server defines, per screen, what the records on that screen are. Rindler's extract_content returns parsed records, such as listings for a list screen or listing for a detail screen, when the site config defines an extraction schema. It falls back to a raw ARIA accessibility tree only when no schema is registered for that screen. The internal rule is direct: every screen exposes structured records via extraction_schema, ARIA is fallback only. The same discipline applies to filters. A screen's filter controls come back live as a filters array read from the current page, never hardcoded, because filters change with context. A marketplace's Vehicles category adds Make, Model, and Year.
Sign-in handling. Real tasks live behind logins, so auth belongs in the protocol, not in a wiki page. A Rindler response carries an auth_context that classifies the login lane for the current site and action. Where the flow is a hosted handoff, the response includes a capture_url. You open it, sign in on the real site inside a managed browser, and the single-use link expires in 15 minutes. The agent calls await_auth to wait for the sign-in to complete instead of guessing. When a stored session later expires, the response says so with auth_status "expired" and routes the agent back to the right lane. You can audit or revoke saved logins at any time with manage_cookies. Bot evasion is managed for you. Agents do not control it.
Tool annotations. MCP defines per-tool hints (readOnlyHint, destructiveHint, idempotentHint, openWorldHint) so a client runtime can reason about risk before calling, and Rindler ships them across the tool surface. extract_content, extract_document, and await_auth are annotated read-only and idempotent. dispatch_action is annotated destructive because it is the one tool that changes external site state. It can submit forms, orders, messages, and applications, and replays re-execute. manage_cookies and memory are destructive too, since their forget actions delete stored state, and close_session is idempotent. Your runtime can use these hints to decide when a call needs a confirmation step.
Production-grade servers also return honest failure signals. An unmapped site returns screen "unsupported_site" so the agent stops and falls back to its own browsing instead of retrying forever. A modal that blocks the page returns blocked_by_dialog naming the dialog and its safe dismiss candidates, and the dismiss_dialog escape hatch refuses any button that spends money or removes items. A file export that could not be captured returns an explicit error rather than a false success. Because the server is agent-agnostic, these behaviors live in tool descriptions, schemas, and the server's MCP Instructions, not in prompt hacks for one particular agent.
How it differs from scraping, raw automation, and per-site APIs
- Web scraping returns raw HTML. DOM scrapers break when a site's UI changes because they chase selectors. A web-automation MCP server returns structured, deterministic records, and Rindler's site configs adapt when a layout changes.
- Raw browser automation drives or scrapes the page live on every run, with an LLM re-reading the DOM each time. A pre-mapped, verified config replaces that with deterministic typed actions.
- Per-site APIs are the right answer where they exist, but most of the web never got one. This category exists for those surfaces: legacy portals, private SaaS dashboards, government systems, and multi-step forms. Rindler is horizontal here: any website, not limited to stores.
Where to go next
Connecting takes one command: curl https://rindler.ai/install | sh writes the .mcp.json entry pointing your runtime at https://mcp.rindler.ai. It works with any MCP-capable agent, including Claude Code, Cursor, Devin Desktop, Claude Desktop, and Codex.
- Quickstart: install, authenticate over OAuth, and run your first task at /docs/quickstart.
- Sign-in flows in depth, including what the agent sees and how session lifetime works, at /docs/auth.
- How a site becomes a set of tools in the first place: if the site you need is not in the catalog yet, map it yourself in a couple of minutes at /docs/mapping.
- The tool-by-tool reference for the session loop at /docs/browser-mcp.