@codeinklingon/browser-mcp
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., "@@codeinklingon/browser-mcpgo to google.com and take a screenshot"
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.
@codeinklingon/browser-mcp
vibecoded port of oh-my-pi's browser tool as an mcp server
MCP server for headless browser automation via Puppeteer. Drop-in replacement for @playwright/mcp with enhanced stealth anti-detection and Playwright-format ARIA snapshots.
Usage
Add to your opencode.json:
{
"mcp": {
"browser-mcp": {
"type": "local",
"command": ["npx", "-y", "@codeinklingon/browser-mcp"],
"enabled": true
}
}
}Or install the skill (registers the MCP server + loads AI guidance):
npx skills install @codeinklingon/browser-mcpOr run directly:
npx @codeinklingon/browser-mcpRelated MCP server: Chrome MCP Stealth
Tools
Tool | Description |
| Open a tab, optionally navigate to a URL |
| Execute JS in the tab — has full |
| Close the tab and release resources |
The tab API
Every browser_tab_run call has tab, display, wait, assert in scope.
Navigation & Info
Method | Notes |
| Current URL (sync) |
| Page title |
|
|
| Wait for next page load |
Click & Input
Method | Notes |
| CSS, |
| Type into input |
| Clear then type |
|
|
| |
|
|
| Selector or |
| File input |
Scrolling & Visibility
Method | Notes |
| Scroll by pixels |
| Center element in viewport |
Page State
Method | Notes |
| Accessibility tree: |
| Playwright-format YAML with |
| Raw JS in page context |
|
|
| Base64 PNG |
Element Refs
Method | Notes |
| ElementHandleActions from |
| ElementHandleActions from |
| CSS, text, xpath, aria-ref |
| String substring or RegExp |
| String, RegExp, or function |
ElementHandleActions: { click, type, fill, hover, focus, screenshot, evaluate, scrollIntoView }
Important
display,wait,assertare bare globals — NOTtab.*methodsdisplay(x)✓ —tab.display(x)✗wait(2000)✓ —tab.wait(2000)✗
Navigation invalidates refs — re-run
ariaSnapshot()orobserve()aftergoto()Single-expression code auto-returns its value (no explicit
returnneeded)
Selector Syntax
Prefix | Example | Notes |
(none) |
| CSS selector |
|
| Visible text (retries 10x) |
|
| XPath |
|
| Ref from |
Example
await tab.goto('https://example.com/login')
const snap = await tab.ariaSnapshot()
display(snap)
await tab.fill('aria-ref=e5', 'admin')
await tab.fill('aria-ref=e8', 'password')
await tab.click('aria-ref=e12')
await tab.waitForNavigation()
display(tab.url())
const screenshot = await tab.screenshot()
display(screenshot)Install
# Quick start — installs the skill and registers the MCP server
npx skills install codeinklingon/browser-mcp
# Or manually add to opencode.json (see Usage above)Build from source
npm install
npm run buildPublish:
npm publishLicense
MIT
Available Tools
3 toolsbrowser_tab_closeA
Close the browser tab and release resources.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden of disclosure. It mentions resource release but does not specify whether the operation is instantaneous, requires confirmation, or affects state. Minimal but acceptable for a simple action.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise with one sentence, front-loading the action. It avoids unnecessary words but could be slightly more detailed without losing conciseness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a parameterless tool with no output schema, the description covers the basic purpose and resource release. It might be considered adequate, though more context about behavior (e.g., no prompts) would improve completeness.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There are no parameters, so schema coverage is 100%. The description adds no parameter information, but none is needed. Baseline for zero parameters is 4.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action: closing the browser tab and releasing resources. It uses a specific verb and resource, and distinguishes well from sibling tools like open and run.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is provided on when to use this tool versus alternatives, such as when to close versus leaving a tab open. It does not mention any prerequisites or side effects.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
browser_tab_openC
Open a browser tab, optionally navigating to a URL. Reuses existing tab by name.
| Name | Required | Description | Default |
|---|---|---|---|
| url | No | URL to navigate to | |
| viewport | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided. The description mentions reusing a tab by name but doesn't specify behavior when no URL is provided or what happens to the previous tab content. Side effects are unclear.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is very short (two sentences) but omits important information about the 'name' reuse mechanism and viewport parameter.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema and only 2 parameters, the description fails to explain how to specify a tab name for reuse, what the tool returns, or default behavior for optional parameters.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description adds no value beyond the schema for 'url' (schema already says 'URL to navigate to'). The 'viewport' parameter is not described at all, despite being a nested object with no schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states 'Open a browser tab, optionally navigating to a URL' which is clear, but it also says 'Reuses existing tab by name' without a 'name' parameter in the schema, causing confusion about how the reuse works.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance on when to use this tool versus siblings (browser_tab_close, browser_tab_run) or when to avoid it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
browser_tab_runA
Execute JavaScript code in the browser tab. The code runs as an async function body.
CRITICAL RULES:
MUST call browser_tab_open before browser_tab_run
ALWAYS await async tab methods
tab.observe() and tab.goto() invalidate previous element refs
Default to tab.observe() for page state; screenshot only when appearance matters
For reading static content (articles, docs, JSON, PDFs), prefer webfetch — browser is for JS execution, auth, interactive actions
Available variables in scope:
tab — TabApi object: tab.url(): string (sync) tab.title(): Promise tab.goto(url, { waitUntil? }) waitUntil: 'load' | 'domcontentloaded' | 'networkidle' tab.click(selector) CSS, "text/...", "xpath/...", "aria-ref=..." tab.type(selector, text) tab.fill(selector, value) clear + type into input tab.press(key, { selector? }) e.g. 'Enter', 'Escape' tab.hover(selector) tab.scroll(deltaX, deltaY) tab.scrollIntoView(selector) tab.screenshot({ fullPage?, selector? }) returns base64 PNG tab.evaluate(fn, ...args) raw JS in page context tab.observe() accessibility tree: { elements: [{ id, role, name, value, focused }] } tab.ariaSnapshot() Playwright-format YAML tree with [ref=eN] ids, [cursor=pointer] for clickables tab.id(n) ElementHandleActions from observe() id tab.ref("e5") ElementHandleActions from ariaSnapshot() ref tab.waitForSelector(selector, { timeout?, visible?, hidden? }) tab.waitForUrl(pattern, { timeout? }) string substring or RegExp tab.waitForResponse(pattern, { timeout? }) string, RegExp, or (res) => boolean tab.waitForNavigation({ waitUntil?, timeout? }) tab.select(selector, ...values) option(s) tab.drag(from, to) selector or { x, y } point tab.extract(format?) 'markdown' | 'text' | omitted (returns HTML) tab.uploadFile(selector, ...filePaths) file input
ElementHandleActions: { click, type, fill, hover, focus, screenshot, evaluate, scrollIntoView }
display(value) — emit structured output (NOT a tab.* method)
wait(ms) — delay (NOT a tab.* method; use bare wait(2000), not tab.wait(...))
assert(cond, msg?) — guard (NOT a tab.* method)
Selectors: CSS by default, "text/Sign in" for visible text, "xpath/...", "aria-ref=e5" from ariaSnapshot.
Single-expression code auto-returns its value (no explicit 'return' needed). Use display() for intermediate values.
| Name | Required | Description | Default |
|---|---|---|---|
| code | Yes | JavaScript code body to execute |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description fully bears the burden of behavioral disclosure. It details the async execution context, available methods, and important behaviors like invalidated element refs. No contradictions exist.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-structured with critical rules upfront and organized sections. Every sentence adds value for a powerful tool, though some details could be condensed.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity with many methods and no output schema, the description thoroughly explains all necessary context, including scope variables and usage patterns like single-expression auto-return.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The single parameter 'code' is fully described in the schema (100% coverage). The description adds useful context about auto-return and single-expression behavior, exceeding the schema's simple description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Execute JavaScript code in the browser tab' with a specific verb and resource. It distinguishes from sibling tools (browser_tab_close, browser_tab_open) by focusing on code execution.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit prerequisites (must call browser_tab_open first) and alternatives (prefer webfetch for static content), guiding the agent on when to use this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
TDQS
Each tool has a distinct action: open, run, close. No overlap; an agent can easily select the correct tool for each step of the browser lifecycle.
All names follow the exact pattern `browser_tab_<verb>`, with verbs being clear actions. Perfectly consistent.
Three tools cover the essential browser tab lifecycle: open, execute code, close. This is a well-scoped set for the server's purpose.
The tools cover the primary workflow (open, run, close). While additional tools for specialized actions (e.g., tab navigation) could be added, the API methods described in the critical rules provide sufficient interactivity, so no dead ends.
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 Connectors
MCP server for Mint — AI-powered QA that runs your app in a real browser on every PR.
Hosted real Google Chrome MCP with per-user persistent state. Navigate, click, type, screenshot.
Stealth web browser for agents: search, fetch, click, download and type in persistent MCP sessions.
MCP server to assist with JxBrowser development.
Related MCP Servers
- AlicenseBqualityNot gradedmaintenanceA MCP server that provides browser automation tools, allowing users to navigate websites, take screenshots, click elements, fill forms, and execute JavaScript through Playwright.82
- AlicenseNot gradedqualityDmaintenanceAn MCP server for stealth browser automation that uses human-like interaction patterns to bypass bot detection via the Chrome DevTools Protocol. It enables users to navigate, interact with elements, and capture data from websites using undetectable behaviors like Bezier mouse movements and Gaussian typing delays.1651MIT
- AlicenseNot gradedqualityDmaintenanceSelf-hosted MCP server for browser automation using Puppeteer, with tools for navigation, screenshots, mouse interactions, cookie management, and multiple transport protocols.2,35920MIT
- FlicenseNot gradedqualityDmaintenanceMCP server for headless browser automation using Puppeteer, enabling AI to navigate, click, fill forms, take screenshots, and execute JavaScript on web pages.
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/CodeInKlingon/browser-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server