Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Ollama can control a browser through MCP, but the connection is a loop rather than a single prompt. Ollama runs the local model, an MCP client connects to Playwright MCP, and the client executes the model’s browser tool calls. The resulting page data is then sent back to Ollama as tool messages until the model produces a final answer.

The shortest supported setup is Node.js 20 or newer, an MCP-capable client, Ollama with a tool-calling model, and Playwright MCP launched with npx @playwright/mcp@latest.

How the Ollama–MCP browser connection works

There are three separate components:

  • Ollama: the local model runtime. Its chat API is available at http://localhost:11434/api/chat and accepts a model, messages, and optional tool schemas.
  • Playwright MCP: the browser tool server. It exposes navigation and interaction capabilities through MCP and returns structured accessibility snapshots, allowing a model to choose controls by semantic references instead of pixel coordinates.
  • MCP client: the host application that starts or connects to the server, presents its tools to Ollama, executes requested calls, and appends the results to the conversation.

The runtime sequence is:

  1. Send the user request and the browser tool schemas to Ollama.
  2. Ollama returns an assistant message containing one or more tool_calls.
  3. The MCP client executes each requested browser function.
  4. Append each result as a tool message.
  5. Call Ollama again. Repeat until the assistant message contains no tool calls.

Without that iterative exchange, Ollama can describe browser actions but cannot perform them.

Prerequisites and a safe starting configuration

Install the required software

  • Install Node.js 20 or newer. Playwright MCP’s documented launch command uses npx.
  • Install Ollama and download a model that explicitly supports tool calling. The API accepts a tools field, but a model that lacks tool-call capability will usually answer in text instead of emitting usable calls.
  • Install or choose an MCP-capable host such as VS Code, Cursor, Windsurf, Claude Desktop, Claude Code, Codex, Copilot CLI, or another compatible client.

Check Ollama before adding the browser

Start Ollama, then make a plain chat request. Replace YOUR_MODEL with the local model you installed:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
curl http://localhost:11434/api/chat 
  -H 'Content-Type: application/json' 
  -d '{
    "model": "YOUR_MODEL",
    "messages": [{"role": "user", "content": "Reply with the word ready."}],
    "stream": false
  }'

A JSON response confirms that the local API is reachable. It does not prove that the model supports tools; test that after the MCP client is configured.

Launch Playwright MCP locally

Default headed browser

Run this in a terminal:

npx @playwright/mcp@latest

The default local process starts a browser that can be observed while the model works. Your MCP client normally launches this command itself, so you usually do not keep a separate terminal process running when using a client configuration.

Headless mode for CI

npx @playwright/mcp@latest --headless

Use headless mode on build agents or servers without a display. Headed mode is easier to debug because you can see navigation, consent dialogs, and failed pages.

Select a browser engine

Choose an engine with --browser:

npx @playwright/mcp@latest --browser chrome
npx @playwright/mcp@latest --browser firefox
npx @playwright/mcp@latest --browser webkit
npx @playwright/mcp@latest --browser msedge

The executable must be available on the machine. Selecting an engine does not change Ollama’s message loop.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Run a standalone HTTP server

For a container, shared service, or remote client, start Playwright MCP on a known port:

npx @playwright/mcp@latest --port 8931

Configure the MCP client URL as http://localhost:8931/mcp. If the client and server are in different containers or hosts, replace localhost with a reachable hostname and allow the port through the relevant network boundary.

Register the server in an MCP client

The standard local-process configuration is:

{
  "mcpServers": {
    "playwright": {
      "command": "npx",
      "args": ["@playwright/mcp@latest"]
    }
  }
}

Paste this object into the MCP settings for your client, using that client’s configuration file or UI. Restart or reload the client, then ask it to list available tools. The exact display name varies by client, but the server should expose browser navigation, page inspection, interaction, and capture operations.

For an HTTP deployment, use the client’s remote-server entry and set its URL to http://localhost:8931/mcp instead of specifying a command. Do not configure both modes for the same server unless you intentionally want two browser sessions.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Make the first browser request

With the server connected, give the host a bounded instruction such as:

Open https://example.com, read the page title and the first heading, and report both. Do not submit forms or follow external links.

Playwright MCP returns an accessibility-oriented representation of the page. The model can use the returned semantic references for clicks, typing, and navigation. This is more reliable than asking a model to guess screen coordinates, particularly when the viewport or layout changes.

For a first test, use a public page and a read-only task. Once that succeeds, test a controlled form or authenticated workflow.

Passing MCP tool results back to Ollama

If your MCP host already supports Ollama as a model provider, it performs the loop automatically. If you are writing your own bridge, preserve the assistant tool-call message exactly, execute every call through your MCP client, and append one tool message per result.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Python message-loop example

The following uses Ollama’s HTTP API. The execute_mcp_tool function is the adapter to your MCP client; it must return the text or structured result received from Playwright MCP.

import json
import requests

OLLAMA_URL = "http://localhost:11434/api/chat"
MODEL = "YOUR_TOOL_CALLING_MODEL"

tools = [{
    "type": "function",
    "function": {
        "name": "browser_action",
        "description": "Perform one browser operation through the connected MCP server.",
        "parameters": {
            "type": "object",
            "properties": {
                "action": {"type": "string"},
                "url": {"type": "string"},
                "ref": {"type": "string"},
                "text": {"type": "string"}
            },
            "required": ["action"]
        }
    }
}]

def execute_mcp_tool(name, arguments):
    # Call the tool named by your MCP client and return its result.
    # Keep the returned text, accessibility snapshot, or JSON intact.
    raise NotImplementedError("Connect this adapter to your MCP client")

messages = [{
    "role": "user",
    "content": "Open https://example.com and tell me the page title."
}]

while True:
    response = requests.post(
        OLLAMA_URL,
        json={"model": MODEL, "messages": messages, "tools": tools, "stream": False},
        timeout=90,
    )
    response.raise_for_status()
    assistant = response.json()["message"]
    messages.append(assistant)
    calls = assistant.get("tool_calls") or []
    if not calls:
        print(assistant.get("content", ""))
        break

    for call in calls:
        name = call["function"]["name"]
        arguments = call["function"].get("arguments", {})
        result = execute_mcp_tool(name, arguments)
        messages.append({
            "role": "tool",
            "tool_name": name,
            "content": json.dumps(result) if not isinstance(result, str) else result,
        })

The function name and argument shape in this example are deliberately generic. Use the actual tool schemas advertised by your Playwright MCP connection; do not invent a tool name when the server has supplied one.

Node.js loop skeleton

Node.js 20 or newer includes fetch. This is the same protocol in JavaScript:

const OLLAMA_URL = 'http://localhost:11434/api/chat';
const MODEL = 'YOUR_TOOL_CALLING_MODEL';
const tools = [{
  type: 'function',
  function: {
    name: 'browser_action',
    description: 'Perform one browser operation through the connected MCP server.',
    parameters: {
      type: 'object',
      properties: {
        action: { type: 'string' },
        url: { type: 'string' },
        ref: { type: 'string' },
        text: { type: 'string' }
      },
      required: ['action']
    }
  }
}];

async function executeMcpTool(name, args) {
  // Replace with your MCP client's call-tool method.
  throw new Error(`No MCP adapter configured for ${name}`);
}

const messages = [{ role: 'user', content: 'Open https://example.com and report its title.' }];
for (;;) {
  const res = await fetch(OLLAMA_URL, {
    method: 'POST',
    headers: { 'content-type': 'application/json' },
    body: JSON.stringify({ model: MODEL, messages, tools, stream: false })
  });
  if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
  const assistant = (await res.json()).message;
  messages.push(assistant);
  const calls = assistant.tool_calls ?? [];
  if (!calls.length) {
    console.log(assistant.content ?? '');
    break;
  }
  for (const call of calls) {
    const name = call.function.name;
    const args = call.function.arguments ?? {};
    const result = await executeMcpTool(name, args);
    messages.push({ role: 'tool', tool_name: name,
      content: typeof result === 'string' ? result : JSON.stringify(result) });
  }
}

Inspecting the loop with cURL

You can manually verify the two most important message transitions. First send a tool schema:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
curl http://localhost:11434/api/chat 
  -H 'Content-Type: application/json' 
  -d '{
    "model": "YOUR_TOOL_CALLING_MODEL",
    "messages": [{"role":"user","content":"Open https://example.com and report its title."}],
    "tools": [{"type":"function","function":{"name":"browser_action","description":"Use the connected browser","parameters":{"type":"object","properties":{"action":{"type":"string"}},"required":["action"]}}}],
    "stream": false
  }'

After your MCP client executes the returned call, append the assistant object and a tool result to the next request. The tool result’s content should contain the actual Playwright MCP output, not a summary invented by the bridge.

Streaming and multiple tool calls

With streaming enabled, Ollama may deliver partial thinking, content, and tool_calls fields across several response chunks. Accumulate the assistant message before appending it to the conversation. Execute every completed call, then send all corresponding tool messages in the next request.

Some models request independent browser operations in parallel. Your MCP adapter may execute those concurrently when the server and workflow allow it; preserve each call’s name and result separately. Sequential execution is safer when one action changes the page state needed by the next.

Authentication, profiles, and browser state

Persistent profile

Playwright MCP’s normal profile preserves cookies, local storage, and login state. That is convenient for a personal workflow, but it also means a later model action may inherit accounts and permissions from an earlier session.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Isolated profile

Use an isolated context for a fresh session:

npx @playwright/mcp@latest --isolated

This is the safer default for shared machines, demonstrations, and CI jobs that must not reuse personal credentials.

Controlled stored state

When a workflow needs known authentication, load an explicitly managed state file with --storage-state. Protect that file like a password: it can contain cookies and other session material.

Existing browser sessions

If the required login already exists in another browser, use a supported CDP endpoint, Playwright endpoint, or browser extension connection. This avoids copying credentials into a new profile, but it gives the automation access to the existing session, so restrict the model’s instructions and network exposure.

Choose the deployment mode

Decision Recommended mode Why
Local development and debugging Local process, headed You can watch the browser and inspect failures immediately.
Continuous integration Local process, --headless, usually --isolated No display is required and state does not leak between jobs.
Container or shared service Standalone HTTP on port 8931 The MCP client connects through http://localhost:8931/mcp or a deliberately routed host.
Reuse an already logged-in browser CDP, Playwright endpoint, or extension Automation attaches to existing state rather than creating another profile.

Reliability, security, and cost considerations

  • Verify tool support first: a server can advertise schemas while a non-tool-capable model emits no calls.
  • Constrain permissions: begin with read-only prompts, limit navigation targets, and require confirmation before purchases, account changes, or form submissions.
  • Protect state: persistent profiles and storage-state files can expose cookies and local storage. Use isolation or explicit state management on shared systems.
  • Control timeouts: browser navigation can take longer than a normal chat request. Set an HTTP timeout that covers page loading and the model’s response, and report failures as tool results so Ollama can recover.
  • Keep the loop bounded: impose a maximum number of tool rounds and stop when the task is complete. This prevents a model from repeatedly revisiting a page.
  • Plan network reachability: in remote or containerized deployments, confirm that the MCP client can reach the server host and port and that the browser can reach the target website.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshooting

Ollama returns text but no tool_calls

Confirm that the selected model supports tool calling, that the request includes a valid tools array, and that the client is actually sending the schemas. Try a simpler task such as reading a title. A model may decline a complex action even when it supports tools.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The MCP server will not start

Check Node.js with node --version; install Node.js 20 or newer. Run npx @playwright/mcp@latest directly to expose package or browser-install errors before debugging the client configuration.

The client cannot connect to HTTP MCP

Verify that the server was started with --port 8931 and that the client URL includes the /mcp path. Replace localhost with a routable hostname when the client runs in another container or machine, and check firewall rules.

The browser opens but actions fail

Ask for a fresh page snapshot, then use the current semantic reference rather than a stale one. Dynamic pages can replace controls after navigation. Wait for a selector, a delay, or network idle when the page is still loading.

Login state is missing

Check whether the client launched an isolated profile, whether the persistent profile is locked by another browser, and whether the expected --storage-state file is readable. For an existing session, use the appropriate CDP or extension mode instead of assuming a new profile can see it.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The model loops indefinitely

Add a maximum tool-round count, return clear error text from failed MCP calls, and instruct the model what constitutes completion. For state-changing workflows, execute actions sequentially and include the latest snapshot after each change.

Or skip the browser setup

If your goal is a clean screenshot rather than interactive browser control, ScreenshotNeo provides a single HTTP request and an MCP server for AI agents. Before capture it accepts cookie or consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and the response identifies the page verdict and billing status in X-Page-Verdict and X-Billed headers.

cURL (full API options are in the ScreenshotNeo documentation):

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

Python:

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)

Node.js:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

ScreenshotNeo also exposes an MCP server with take_screenshot, get_page_info, and capture_pdf tools, so Claude, Cursor, or another MCP client can request captures without managing Playwright locally. It supports full-page and element captures, device and viewport settings, dark mode, custom CSS and JavaScript, click and wait actions, request blocking, headers and cookies, geolocation, PDF output, resizing, TTL-based caching, signed links, asynchronous jobs, bulk capture of up to 100 URLs per call, and a usage API. Every feature is on every plan: 1,000 screenshots per month are free with no card, and paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Frequently Asked Questions

Can I use Ollama without an MCP client?

You can call Ollama’s chat endpoint directly, but you must implement the MCP session, tool discovery, browser execution, and result-message loop yourself. An MCP-capable host handles those protocol details for you.

Should I use a persistent or isolated Playwright profile?

Use a persistent profile only when retaining a controlled login is intentional. Choose --isolated or explicit storage state for shared machines, CI, and workflows with authentication boundaries.

When is standalone HTTP preferable to the local command?

Use standalone HTTP when the browser server must run in a container, on another host, or as a shared service. A local command is simpler when the MCP client and browser run on the same machine.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.