browserkit
OfficialAllows interaction with Reddit to retrieve subreddit content, threads, search for posts, and get user information.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@browserkitsearch for remote AI engineer jobs on LinkedIn"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
browserkit
An open-source framework for building site-specific MCP servers that operate over real, authenticated user browser sessions — running locally on your machine.
Turn your logged-in browser sessions into composable, testable AI tools.
Why local sessions?
Cloud browser automation services work by running browsers on their servers and asking you to re-authenticate there. That model works well for anonymous or company-owned accounts, but breaks down for personal ones — you wouldn't hand your LinkedIn, Gmail, or bank credentials to a third-party server.
browserkit takes the opposite approach: your machine is already authenticated everywhere. It reuses the sessions that exist on your laptop right now, runs all browsers locally, and never sends cookies or credentials over the network. The AI gets access to your real identity on the web; nothing leaves localhost.
The trade-off is intentional — browserkit is single-user and local-only by design. If you need a cloud fleet or multi-tenant access, this is not that tool.
Related MCP server: Chrome MCP Server
Quick Start
# Install core + adapters
pnpm add @browserkit-dev/core @browserkit-dev/adapter-hackernews @browserkit-dev/adapter-linkedin
# Log in once per authenticated site (opens a browser window)
browserkit login linkedin
# Start the daemon
browserkit start --config browserkit.config.jsConfigure your MCP client (Cursor, Claude Desktop, etc.):
{
"mcpServers": {
"browserkit-hackernews": { "url": "http://localhost:3847/mcp" },
"browserkit-linkedin": { "url": "http://localhost:3848/mcp" }
}
}Available Adapters
Package | Site | Auth | Tools |
Hacker News | none |
| |
required |
| ||
none |
|
How It Works
Each adapter runs as a dedicated MCP HTTP server on its own port. Multiple AI agents can connect concurrently — requests are serialized per adapter to protect the browser session.
AI Agent (Cursor / Claude / custom)
↓ HTTP MCP
browserkit daemon
├── hackernews :3847 headless Chromium (public, no auth needed)
├── linkedin :3848 headless Chrome (authenticated, uses real Chrome)
└── ...Browsers run fully headless by default — no window, no Dock icon. They only surface visibly during login (browserkit login) or when you explicitly switch to watch or pause mode.
Configuration
// browserkit.config.js
export default {
host: "127.0.0.1", // bind address (non-localhost requires bearerToken)
basePort: 3847, // first adapter auto-assigns from here
bearerToken: process.env.BROWSERKIT_TOKEN, // optional auth
adapters: {
// key = npm package name (no naming convention required)
"@browserkit-dev/adapter-hackernews": {
port: 3847,
},
"@browserkit-dev/adapter-linkedin": {
port: 3848,
channel: "chrome", // use real Chrome — avoids bot detection on login
},
"@someone/my-custom-adapter": {
port: 3849,
debugPort: 4849, // optional: enables raw Playwright access via CDP
authStrategy: "persistent", // "persistent" | "storage-state" | "cdp-attach" | "extension"
rateLimit: { minDelayMs: 3000 },
},
},
};CLI
browserkit start [--adapter <pkg>] [--port <n>] [--config <path>]
browserkit login <site> # one-time login (opens browser)
browserkit status # show running adapters
browserkit config cursor # generate Cursor MCP settings JSON
browserkit create-adapter <name> # scaffold a new adapter packageTools on Every Adapter Server
Each adapter exposes its own domain tools plus these auto-registered tools:
Domain tools (adapter-specific)
Whatever the adapter declares — e.g. get_feed, search_people, get_top.
Browser control (auto-registered, bypass lock)
Tool | Description |
| Switch between |
| Capture current page as inline image — AI can see it directly |
| URL, title, mode, CDP endpoint for raw access |
| Navigate to a URL (within lock) |
| Browser alive, login status, selector validation report |
Browser Modes
headless → fully invisible, automation runs normally (default)
watch → browser becomes visible, automation continues (optional slowMoMs)
paused → browser visible, tool calls queue — user has manual controlSwitch modes via the set_mode MCP tool from any AI agent.
Extension Mode (Chrome via Playwriter)
Some sites aggressively block automated browsers — Google, LinkedIn, and others detect Playwright's Chromium and refuse login. Extension mode solves this by running adapter tools directly in your real, logged-in Chrome browser instead of launching a separate Patchright instance.
AI Agent (Cursor / Claude)
↓ HTTP MCP
browserkit daemon
├── hackernews :3847 headless Patchright (default — no login needed)
└── linkedin :3848 your Chrome (extension mode — inherits your session)
└── Playwriter relay → Chrome extension → authenticated tabSetup
1. Install the Playwriter Chrome extension from the Chrome Web Store.
2. Install the playwriter npm package:
pnpm add playwriter3. Click the Playwriter extension icon on the tab you want browserkit to use. The icon turns green when active.
4. Configure the adapter to use extension mode:
// browserkit.config.js
export default {
adapters: {
"@browserkit-dev/adapter-linkedin": {
authStrategy: "extension", // use Chrome extension backend
// extensionPort: 19988, // optional — Playwriter's default
},
"@browserkit-dev/adapter-hackernews": {
// defaults to "persistent" — headless Patchright as normal
},
},
};5. Start the daemon — no browserkit login needed:
browserkit startHow it works
browserkit starts Playwriter's local WebSocket relay server and connects Patchright to it via connectOverCDP(). The Chrome extension uses chrome.debugger to forward CDP commands to your active Chrome tab. Adapter tools receive a full Playwright Page object — page.goto(), page.evaluate(), page.route(), screenshots, locators — all work normally.
The Playwriter extension automatically creates a tab group named "playwriter" for automation tabs, and all new tabs open in the background (active: false) so your current tab is never interrupted.
What changes vs. default mode
Default ( | Extension mode | |
Browser | Headless Patchright | Your real Chrome |
Auth |
| Already logged in |
Bot detection | Patchright anti-detection | None needed (real Chrome) |
Headless | Yes | No |
Tab groups | N/A | Green "playwriter" group |
| headless/watch/paused | Not applicable |
Accepted tradeoffs
Chrome-only (not Brave, Arc, Firefox)
chrome.debuggershows "Chrome is being controlled by automated test software" banner on attached tabsRequires Chrome to be open and the Playwriter extension active
Shared browser: automation runs in your Chrome (CPU/memory shared with your browsing)
Raw Playwright Access (via CDP)
When debugPort is configured, get_page_state returns a cdpUrl. External agents — Claude Code, Cursor, custom scripts — can attach to the already-authenticated browser session and run arbitrary Playwright code:
// Script written by Claude Code, executed via shell
const { chromium } = require('playwright');
// Attach to the running session — already logged in, no auth needed
const browser = await chromium.connectOverCDP("http://127.0.0.1:4848");
const context = browser.contexts()[0];
const page = context.pages()[0];
// Full Playwright API — write any automation
await page.goto("https://my-site.com/data");
const results = await page.$$eval(".row", (els) => els.map((el) => el.textContent?.trim()));
console.log(JSON.stringify(results));
await browser.disconnect(); // disconnect only — session stays alivePattern: AI writes a script to /tmp/script.js, runs it via shell, reads stdout.
Enable in config: debugPort: adapterPort + 1000 (e.g. adapter on 3848 → debugPort 4848).
Building an Adapter
Reference implementations
browserkit-dev/adapter-hackernews— public site, no auth, 5 tools, full 4-layer test suite. The simplest starting point.browserkit-dev/adapter-linkedin— authenticated site, 7 tools,innerTextextraction strategy + ARIA-anchor feed scraping. Good reference for adapters that need login and work against DOM-churning JS apps.
Scaffold
npx @browserkit-dev/core create-adapter my-site
cd adapter-my-site
pnpm installThis generates the full package structure: src/index.ts, src/selectors.ts, vitest.config.ts, package.json, README.md.
SiteAdapter interface
import { defineAdapter } from "@browserkit-dev/core";
import { z } from "zod";
import type { Page } from "playwright";
export default defineAdapter({
// ── Required ────────────────────────────────────────────────────────────
site: "my-site", // unique ID, becomes the MCP server name
domain: "my-site.com", // used for profile scoping
loginUrl: "https://my-site.com/login", // where to navigate for login flow
async isLoggedIn(page: Page): Promise<boolean> {
// Return true when the page shows an authenticated state.
// Called before every tool call. If it returns false, browserkit
// triggers the human handoff flow (opens browser, waits for login).
// For public sites (no auth), always return true.
return page.getByRole("navigation", { name: "user menu" }).isVisible({ timeout: 3000 });
},
tools: () => [ /* see below */ ],
// ── Optional ────────────────────────────────────────────────────────────
rateLimit: { minDelayMs: 2000 }, // min delay between consecutive tool calls
selectors: { // exported CSS selectors for health_check reporting
mainContent: ".main-content", // health_check validates these on the live page
loginButton: "button[data-testid=login]",
},
});Tool definition
tools: () => [
{
name: "get_data",
description: "Get data from my-site",
// Zod schema — validated before handler is called
inputSchema: z.object({
query: z.string().describe("Search query"),
limit: z.number().int().min(1).max(50).default(10),
}),
// handler receives: the live authenticated Page + validated input
async handler(page: Page, input: unknown) {
const { query, limit } = mySchema.parse(input); // use schema.parse for type safety
await page.goto(`https://my-site.com/search?q=${encodeURIComponent(query)}`);
await page.waitForSelector(".result", { timeout: 10_000 });
const results = await page.evaluate(({ sel, n }) => {
return Array.from(document.querySelectorAll(sel))
.slice(0, n)
.map((el) => el.textContent?.trim() ?? "");
}, { sel: ".result", n: limit });
// Return value must have this shape:
return {
content: [{ type: "text" as const, text: JSON.stringify(results, null, 2) }],
// isError: true — set this if the tool failed but you want to return a message
};
},
},
],Tool handler contract:
pageis a live PlaywrightPage— already navigated, already authenticatedinputis the validated result of your Zod schema — always parse it inside the handler for type safetyReturn
{ content: [{ type: "text", text: string }] }for text resultsReturn
{ content: [{ type: "image", data: base64, mimeType: "image/png" }] }for imagesReturn
{ content: [...], isError: true }to signal a tool-level error without crashing
Testing your adapter
Use @browserkit-dev/core/testing to write tests that spin up a real in-process server:
// tests/mcp-protocol.test.ts
import { describe, it, expect, beforeAll, afterAll } from "vitest";
import myAdapter from "../src/index.js";
import { createTestAdapterServer, createTestMcpClient } from "@browserkit-dev/core/testing";
let server, client;
beforeAll(async () => {
server = await createTestAdapterServer(myAdapter);
client = await createTestMcpClient(server.url);
}, 30_000);
afterAll(async () => {
await client.close();
await server.stop();
});
it("get_data returns results", async () => {
const result = await client.callTool("get_data", { query: "test" });
expect(result.isError).toBeFalsy();
const data = JSON.parse(result.content[0].text);
expect(Array.isArray(data)).toBe(true);
});createTestAdapterServer launches the adapter with an isolated temp data directory (avoids pidfile conflicts with a running daemon). createTestMcpClient connects via the real MCP HTTP transport — the same path used by Cursor and Claude Desktop.
For a complete 4-layer example, see browserkit-dev/adapter-hackernews/tests/.
Publish
pnpm build
npm publish --access publicUsers add the package name to browserkit.config.js — no naming convention required. Any npm package name works.
Planned Adapters
Community contributions welcome — use browserkit create-adapter <name> to scaffold, see Building an Adapter above.
Site | Why browserkit | Proposed tools | Status |
Twitter / X | API is $100/mo+; most personal accounts have no API access |
| open |
Amazon | No consumer API at all |
| open |
Airbnb | No public API; useful for trip-planning agents |
| open |
Google Maps | Places API is expensive per-call; browser is free |
| open |
If you're interested in building one, open an issue on browserkit-dev/browserkit to coordinate.
Architecture
See ARCH.md for full architecture details.
Key properties:
Session-persistent: maintains auth across tool calls and process restarts
Site-specific: deterministic selector-based tools, not DOM-guessing agents
MCP-native: each adapter is a standard HTTP MCP server
Human-in-the-loop: opens browser for login, 2FA, CAPTCHA
Multi-client: multiple AI agents can connect to the same adapter concurrently
License
MIT
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseAqualityBmaintenanceOpen-source MCP server that gives AI agents access to 100+ web applications through the user's authenticated browser session. No API keys, no screenshots, no DOM scraping — talks directly to web app internal APIs via a Chrome extension. Supports Slack, Discord, GitHub, Jira, Notion, Reddit, X, and 100+ more services with ~2,000 tools. Works with Claude Code, Cursor, Windsurf, and any MCP client.Last updated42880MIT
- Alicense-qualityDmaintenanceAn extension-based MCP server that enables AI assistants to control your browser, leveraging existing sessions and login states for automation and content analysis. It provides over 20 tools for semantic tab search, interactive element manipulation, and network monitoring directly within your daily Chrome environment.Last updatedMIT
- Alicense-quality-maintenanceAn extension-based MCP server that enables AI assistants to control your existing Chrome browser, leveraging your active login states and settings for automation. It provides over 20 tools for tasks like semantic tab search, screen capture, network monitoring, and direct element interaction.Last updated

agentify-desktopofficial
Alicense-qualityCmaintenanceMCP server that enables AI tools to control local browser sessions for ChatGPT, Claude, and other AI services, supporting querying, navigation, file uploads, and artifact management.Last updated86491Mozilla Public 2.0
Related MCP Connectors
Browser MCP for logged-in tasks. Uses your Chrome — credentials stay local. Zero-token replay.
User-owned memory for AI agents, Copilot, Claude, IDEs, CLIs, and chat apps over remote MCP.
A paid remote MCP for AI agent browser approval MCP, built to return verdicts, receipts, usage logs,
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/browserkit-dev/browserkit'
If you have feedback or need assistance with the MCP directory API, please join our Discord server