@thinkbrowse/mcp
v0.3.3
Published
Let your AI coding agent test its own frontend work. Connects Claude Code, Cursor, and any MCP client to your real Chrome browser — real sessions, real cookies, no headless conflicts.
Maintainers
Readme
@thinkbrowse/mcp
MCP (Model Context Protocol) server for ThinkBrowse. Gives AI agents the ability to control your actual Chrome browser — with all your cookies and active sessions — or a cloud browser for headless automation.
Why ThinkBrowse vs Playwright MCP
| Capability | ThinkBrowse MCP | Playwright MCP |
|---|---|---|
| Uses your real Chrome cookies | ✅ Local mode — browse as you | ❌ Fresh context, no auth |
| Access sites you're logged into | ✅ LinkedIn, Salesforce, internal tools | ❌ Requires scripted login every time |
| Cloud headless sessions | ✅ Isolated Playwright browser on demand | ❌ Local browser only (no ThinkBrowse cloud) |
| Runtime local ↔ cloud switching | ✅ set_mode tool, no restart | ❌ Single mode per server |
| Structured content extraction | ✅ Reader layer (articles, structured data) | ❌ Raw DOM access only |
| Session recording + sharing | ✅ Full video, screenshots, AI analysis | ❌ |
| Persistent sessions | ✅ Resume across agent invocations | ❌ Single-run only |
| Direct browser actions | ✅ Browser tools + local_action_* | ✅ Browser tools |
| AI task planning | ✅ task_create / task_execute | ❌ |
TL;DR: Use ThinkBrowse when you need to browse as yourself (authenticated sites, internal tools). Use Playwright MCP for stateless public-web automation.
Installation
Claude Code
claude mcp add thinkbrowse --transport stdio \
-e THINKBROWSE_API_KEY=your-key \
-- npx @thinkbrowse/mcpClaude Desktop / Cursor / VS Code
Add to your MCP config file:
| Tool | Config file |
|------|------------|
| Claude Desktop | ~/Library/Application Support/Claude/claude_desktop_config.json |
| Cursor | .cursor/mcp.json in project root |
| VS Code (Copilot) | .vscode/mcp.json in project root |
Auto mode (recommended) — tries local Chrome first, falls back to cloud:
{
"mcpServers": {
"thinkbrowse": {
"command": "npx",
"args": ["@thinkbrowse/mcp"],
"env": {
"THINKBROWSE_API_KEY": "your-key"
}
}
}
}Local only (Chrome extension, no API key needed):
{
"mcpServers": {
"thinkbrowse": {
"command": "npx",
"args": ["@thinkbrowse/mcp", "--mode", "local"]
}
}
}Cloud only:
{
"mcpServers": {
"thinkbrowse": {
"command": "npx",
"args": ["@thinkbrowse/mcp", "--mode", "cloud"],
"env": {
"THINKBROWSE_API_KEY": "your-key"
}
}
}
}Security note: MCP config files (.cursor/mcp.json, .vscode/mcp.json) are often committed to git. Use environment variable references where supported, or add these files to .gitignore to avoid leaking your API key.
Global install (alternative)
npm install -g @thinkbrowse/mcp
thinkbrowse-mcp --mode autoModes
| Mode | Backend | Requires |
|------|---------|----------|
| auto | Tries local first, falls back to cloud | Either of the below |
| local | Chrome extension + native host | Chrome with ThinkBrowse extension |
| cloud | ThinkBrowse REST API (Fly.io) | API key from thinkbrowse.io |
Page cache tools (page_cache_html, page_cache_text, page_cache_screenshot): stateless POST /api/cache/* on the service. In local mode, set THINKBROWSE_BASE_URL and THINKBROWSE_API_KEY (or pass --base-url / --api-key so the native host client can reach the API — the native host itself has no /api/cache routes).
Runtime switching: Use the set_mode tool to switch between local and cloud without restarting.
Local mode setup
MCP Server ──HTTP──> Native Host ──stdio──> Chrome Extension ──> Chrome tabs- Install the ThinkBrowse Chrome extension
- Set up the native host binary (extension guides you through this)
- Verify:
curl http://localhost:$(cat ~/.thinkbrowse/port)/health - Add MCP config above
Available Tools (48 + 1 optional)
48 tools are always registered.
set_modeis registered when the server is started with mode-switch support (the default CLI binary enables it).
Session Lifecycle
| Tool | Description | Modes |
|------|-------------|-------|
| session_create | Create a new browser session | all |
| session_status | Get session URL, title, action count | all |
| session_delete | Terminate session, preserve artifacts | all |
| session_list | List all active sessions | all |
| session_wait_ready | Poll until session is ready (use after create in cloud mode) | all |
| session_use | Set default session ID for subsequent tool calls | all |
| session_release | Release the current local session ownership without closing the tab | local |
| session_artifacts | List screenshots and recordings for a session | cloud |
Mode Switching
| Tool | Description | Modes |
|------|-------------|-------|
| set_mode | Switch between local/cloud/auto at runtime without restart | all |
Navigation
| Tool | Description | Modes |
|------|-------------|-------|
| navigate | Go to a URL, wait for page load | all |
| go_back | Navigate back in browser history | all |
| go_forward | Navigate forward in browser history | all |
| wait_for_element | Wait for a CSS selector to appear | all |
Interaction
| Tool | Description | Modes |
|------|-------------|-------|
| click | Click an element by CSS selector | all |
| type_text | Type text into an element (appends) | all |
| fill | Fill a form field (replaces content) | all |
| press_key | Press a keyboard key (Enter, Tab, Escape, etc.) | all |
| scroll | Scroll the page or a specific element | all |
| hover | Hover over an element (triggers tooltips/menus) | all |
| select_option | Select from a <select> dropdown | all |
Observation
| Tool | Description | Modes |
|------|-------------|-------|
| snapshot | Get accessibility tree (lightweight page overview) | all |
| screenshot | Capture page screenshot (png/jpeg/webp, full-page option) | all |
| extract | Extract text, HTML, or structured data from elements | all |
| evaluate | Run JavaScript in the page context | all |
| get_url | Return the current page URL | all |
| get_title | Return the current page title | all |
| get_html | Return current page HTML with explicit truncation metadata when large | all |
| sleep | Pause for a bounded duration in milliseconds | all |
Tab Management
| Tool | Description | Modes |
|------|-------------|-------|
| tab_list | List all open browser tabs | local |
| tab_new | Open a new tab (optionally with URL) | local |
| tab_close | Close a tab by ID | local |
| tab_attach | Attach to an existing local tab and bind it as the default session | local |
| tab_switch | Switch the active local browser tab without rebinding the default session | local |
| window_new | Open a new local browser window and bind it as the default session | local |
Dialog Handling
| Tool | Description | Modes |
|------|-------------|-------|
| get_dialog | Check for open alert/confirm/prompt dialogs | all |
| handle_dialog | Accept or dismiss a dialog with optional text | all |
Wait
| Tool | Description | Modes |
|------|-------------|-------|
| wait_for_text | Wait for specific text to appear on the page | all |
Monitoring
| Tool | Description | Modes |
|------|-------------|-------|
| console_messages | Get browser console messages (log, warn, error) | all |
| network_requests | Get network requests made by the page | all |
| clear_logs | Clear console and network logs for a clean capture | all |
Local Actions
| Tool | Description | Modes |
|------|-------------|-------|
| local_action_run | Run a direct native-host action against the currently attached local tab | local |
| local_action_status | Check the status of a previously started local action | local |
| local_action_cancel | Cancel a running local action | local |
Task Planning
| Tool | Description | Modes |
|------|-------------|-------|
| task_create | Create an AI task plan from natural language | cloud |
| task_execute | Execute a task plan | cloud |
| task_status | Check task execution status | cloud |
Local Session Semantics
The new local lifecycle tools intentionally distinguish between ownership-changing operations and focus-only operations:
tab_attachrebinding: attaches to an existing local Chrome tab and sets it as the default session for subsequent session-scoped tool calls.window_newrebinding: opens a fresh local window and sets the resulting tab as the default session.tab_switchfocus-only: changes the active local browser tab, but does not steal or rewrite the current default session just because browser focus changed.session_releaseclearing: releases the current local session ownership and clears the default session when that bound local context is released.
Lock safety follows the same high-level contract as the CLI:
- contested live local locks fail explicitly
- same-owner rebinds can succeed idempotently
- stale locks may be replaced only when the existing owner is no longer live
This package now exposes the CLI's local native-host execution flow as:
local_action_runlocal_action_statuslocal_action_cancel
The naming is intentional:
actionmeans a direct operation against a browser contexttaskmeans a higher-level cloud multi-step planning/execution workflow
CLI Options
thinkbrowse-mcp [options]
Options:
--mode <mode> cloud, local, or auto (default: auto)
--api-key <key> API key for cloud mode (or set THINKBROWSE_API_KEY)
--base-url <url> Cloud API URL (default: https://api.thinkbrowse.io)
--port <port> Override native host port
--session-id <id> Default session ID (enables session_use)
-h, --help Show help
-v, --version Show versionEnvironment Variables
| Variable | Description |
|----------|-------------|
| THINKBROWSE_API_KEY | API key for cloud mode |
| THINKBROWSE_BASE_URL | Cloud API base URL |
| THINKBROWSE_BRIDGE_PORT | Override native host port |
| THINKBROWSE_LOCAL | Set to true to force local mode |
Port Discovery
The native host writes its port to ~/.thinkbrowse/port on startup. The MCP server reads this automatically.
Priority: --port flag > THINKBROWSE_BRIDGE_PORT env > ~/.thinkbrowse/port > 3012
Testing
# Unit tests
bun test
# Smoke test — full session lifecycle against cloud
THINKBROWSE_API_KEY=your-key bun run scripts/smoke-mcp-parity.ts
# Smoke test — clear_logs only
bun run test:smokeProgrammatic Usage
Basic:
import { createServer, CloudClient } from '@thinkbrowse/mcp';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
const client = new CloudClient({
baseUrl: 'https://api.thinkbrowse.io',
apiKey: process.env.THINKBROWSE_API_KEY!,
});
const server = createServer(client);
await server.connect(new StdioServerTransport());With runtime mode switching:
import { createServer, CloudClient } from '@thinkbrowse/mcp';
import type { ClientRef } from '@thinkbrowse/mcp';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
const client = new CloudClient({
baseUrl: 'https://api.thinkbrowse.io',
apiKey: process.env.THINKBROWSE_API_KEY!,
});
const clientRef: ClientRef = { current: client };
const server = createServer(client, {
clientRef,
onSetMode: async (mode) => {
// Return a new client for the requested mode
return new CloudClient({ baseUrl: '...', apiKey: '...' });
},
});
await server.connect(new StdioServerTransport());License
MIT
