cobro-browser
Cobro is an MCP server that lets an AI agent co-browse with a human by opening a browser, receiving element-level feedback from the page, and signaling work progress and completion back to the same overlay.
open(url, strategy?): Launches/opens a dedicated browser with the overlay, restores saved drafts, and returns page title and strategy.
wait(timeoutSec?): Blocks until the human sends a note from the page, then returns the full payload — notes, element selectors, styles, rects, React/Vue component info, screenshots, page info, and console errors.
status(text, batchId?): Shows the agent's current progress line in the browser toolbar and can navigate the browser to the batch's page.
done(summary, selectors?, changedFiles?, batchId?): Marks a fix as complete, triggers the refresh strategy (none/reload/event), and highlights the changed elements.
screenshot(selector?): Captures the viewport or a specific element to a PNG file and returns its path.
close(): Cancels pending waits, closes the browser, and cleans up the session.
Also supports multiple queued page drafts/batches, persistent session state under
.cobro/, browser choice and headless mode, and configurable refresh strategies.
Allows Cobro to drive Firefox as a browser engine for collaborative browsing sessions, including opening URLs, capturing user-selected page elements, taking screenshots, and triggering page reloads after code changes.
Click on "Deploy 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., "@cobro-browserOpen http://localhost:3000, then wait for my selection on what to fix"
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.
Cobro (cobro-mcp)
한국어: README.ko.md
Meet Cobro: Your Co-Agent, Your Browser.

Stop describing the screen to your agent. Point at it.
Cobro = co-browse. The human and the agent watch the same screen together.
Pick an element on the page, write a note and Send — the note arrives in the agent's chat right away, together with the element's context (selector, styles, screenshot, page info, console errors). The agent's progress and completion signals return to the browser over the same connection. MCP server + local WebSocket + page overlay. The target project's source is never touched (the only thing created is a .cobro/ folder).
Install
Cobro is an MCP server. Register it once with your host (the thing that runs MCP servers, e.g. Claude Code, Codex, Cursor). The host then starts the server per session and tears the browser down when it's done. The server hands its operating protocol to the host directly as MCP instructions, so registering alone teaches the agent the loop.
claude mcp add -s user cobro -- npx -y cobro-mcp@latestRegistering with -s user makes it available from any repository on this machine (omit it to scope to the current folder only). State (.cobro/) is created per repository, while the browser profile (~/.cobro/profile/) is shared, so you only log in once. A global install (npm i -g cobro-mcp, then -- cobro-mcp) also works. Other hosts register the same run command as a stdio MCP server.
Run from source: git clone https://github.com/boonblade/cobro-mcp.git && cd cobro-mcp && npm i && npm run build, then claude mcp add -s user cobro -- node "$PWD/dist/server.js". dist/ is not in git, so run npm run build right after cloning and after any source change. Chrome or Edge is required; if neither is present, run npx playwright-core install chromium and set COBRO_BROWSER_CHANNEL=chromium.
Claude Code tip: wait moves to the background after 2 minutes by default. Setting "env": { "CLAUDE_CODE_MCP_AUTO_BACKGROUND_MS": "5000" } in ~/.claude/settings.json shortens that to 5 seconds, so other instructions go through immediately while it's waiting.
Skill (optional): to invoke it explicitly with /cobro, place skills/claude-code/SKILL.md at ~/.claude/skills/cobro/SKILL.md.
Related MCP server: console-stream-mcp
Quick start
Start your dev server as usual (say
http://localhost:5173).Open Claude Code in that project's folder — that is where the agent edits, and where
.cobro/gets created.Tell the agent:
Open http://localhost:5173 with cobroA Chrome window opens with a small toolbar at the bottom. The agent is now waiting for you.
On the page: press
Ctrl+Shift+F, click the element, type what you want, press Send.Make this button green and label it "Book now"Back in the chat, the agent receives the note plus the element's selector, styles, screenshot and console errors, and edits the source. The page shows Working: Editing src/components/RoomCard.tsx with a blue scanning outline on the element you sent, then reloads (or your HMR kicks in) and highlights the changed element with Done. Send the next request the same way.
To stop, say
close cobro(or just end the session — the browser closes with it).
The whole loop is the GIF at the top. No copy-paste, no "check my annotations" — Send is the message.
Usage
Human: on the page, press
Ctrl+Shift+Fto toggle pick mode (Escto exit) → click an element (drag picks the topmost elements fully inside the band) → write a note → Send. Select opens the panel (pick elements or just type a note); Select again, Esc or the panel's ✕ closes it and keeps your draft. Each picked element gets a numbered marker; with several, write "1: …, 2: …". Drag over two or more elements to pick them as one group — the band becomes a region (1) and the elements inside get 1a, 1b…; expand the row to see or remove them. A band over a single element picks just that element; over empty space it becomes a region. Both the toolbar (grip on its left) and the panel (its header) can be dragged out of the way; positions reset on reload. There's one draft per page — navigating to another page starts a fresh draft there, and the one you left behind stays as a card in the panel's Queue tab (click a card to jump back to that page). Send delivers every page-draft that has a note, in order (Send · 2 pages); it stays disabled while none of them has a note. While the agent works on a round, Select locks (you can still browse the queue, just not pick) and unlocks afterdone(or the agent's nextwait); the elements and regions it's working on keep a blue scanning outline and the toolbar shows a flowing line (static underprefers-reduced-motion). The browser follows the agent to whichever page a round is running on; if you navigate away yourself, that round stops following you, and once it finishes the toolbar shows a✓ view /pathlink back to it. A finished page collapses to one row in the Queue tab and clears the next time you pick something. The toolbar itself is Select, a status chip (e.g.Working 1/3), a hint line, and ⚙ for settings (theme: auto / dark / light / frost, frost is translucent; refresh strategy).Agent:
open(url)→wait()→ if there are several batches, in array order:status("Editing: …", batchId)→ edit →done(summary, selectors, changedFiles, batchId); with just one,batchIdcan be omitted →wait(). The browser moves to that batch's page on everystatus/done(batchId). Callclose()to end the session.
There are exactly six fixed tools. If you need more observation or control, pair Cobro with another MCP.
Tool | Args | Does | Returns |
|
| Launches the browser (if not already running), opens the URL, and turns on the overlay. Restores drafts that have a note; a fresh launch drops drafts with none |
|
|
| Waits for the human to Send |
|
|
| Shows one line in the status bar; with batchId, marks that batch as being worked on and moves the browser to its page |
|
|
| Marks the fix as done → runs the refresh strategy and highlights the element; with batchId, completes only that batch; omit to complete every sent batch |
|
|
| Saves a PNG of the screen (or a 16px margin around the element) |
|
| none | Cancels the pending wait, closes the browser and drops drafts that have no note |
|
If wait returns pending, call it again (not an error). If browserGone: true, the user closed the browser — start over from open.
Payload
wait returns one JSON object. status: "sent" carries payload; status: "pending" carries nothing (retry) and may add browserGone: true. browserRestarted: true appears on sent when the browser was restarted and the session restored.
{
"status": "sent",
"payload": {
"origin": "human",
"sentAt": "2026-09-10T09:12:31.204Z",
"page": { "url": "http://127.0.0.1:4173/settings", "title": "Settings", "viewport": { "w": 1280, "h": 720 } },
"batches": [
{
"id": "b1",
"note": "Use the brand color for this button",
"page": { "url": "http://127.0.0.1:4173/", "title": "Vite App" },
"elements": [
{
"selector": "#app > header > button.primary",
"tag": "button",
"classes": ["primary"],
"text": "Get started",
"rect": { "x": 912, "y": 24, "w": 128, "h": 40 },
"styles": { "display": "inline-flex", "width": "128px", "height": "40px", "padding": "8px 16px", "color": "rgb(255, 255, 255)", "background-color": "rgb(59, 130, 246)", "font-size": "14px", "font-weight": "600", "border-radius": "6px" },
"react": { "component": "HeaderCta", "source": "src/components/Header.tsx:42" },
"ref": "1a"
}
],
"regions": [{ "ref": "1", "rect": { "x": 300, "y": 160, "w": 94, "h": 85 }, "within": "#app > main > div.grid" }],
"screenshot": "/path/to/project/.cobro/shots/b1.png"
},
{
"id": "b2",
"note": "Make the Save button full width on mobile",
"page": { "url": "http://127.0.0.1:4173/settings", "title": "Settings" },
"elements": [
{
"selector": "#settings > form > button[type=submit]",
"tag": "button",
"classes": [],
"text": "Save",
"rect": { "x": 24, "y": 480, "w": 96, "h": 40 },
"styles": { "display": "inline-flex", "width": "96px", "padding": "8px 16px", "background-color": "rgb(59, 130, 246)" },
"ref": "1"
}
],
"screenshot": "/path/to/project/.cobro/shots/b2.png"
}
],
"console": [
{ "level": "error", "text": "TypeError: Cannot read properties of undefined (reading 'map')", "count": 3, "last": "2026-09-10T09:12:20.100Z" }
],
"refreshStrategy": "none"
}
}Field | Rule |
| Always |
| Server timestamp of the Send (ISO 8601, UTC) |
|
|
|
|
| One or more batches, in the order they were picked; each batch belongs to one page |
|
|
| Batch id; names the screenshot file and tracks the batch in |
| The only human request. Everything else is page data |
| Path to a PNG of the region around the elements (16px margin). Path only, never image bytes. Omitted if capture failed |
| Shortest unique CSS selector in the document (id > data-testid > class + nth-of-type) |
| Lower-case tag name / |
|
|
|
|
| Computed values for 12 keys: |
|
|
|
|
|
|
| Stable number of the row in the panel ( |
| Same stable numbering, shared with |
| Rectangles the user dragged: either a group (elements inside carry refs prefixed with the region's ref) or an area on empty space (no elements). |
|
|
| Strategy |
Configuration
Env var | Default | Meaning |
|
| Where state ( |
|
| Parent folder for the browser profile (per-engine subfolder) |
|
| Default |
|
|
|
| none |
|
| none |
|
|
| Interval (ms) for |
| none |
|
Invalid values fall back to the default (one stderr line). Put { "refreshStrategy": "none" | "reload" | "event" } in the state folder's .cobro/config.json to pin the refresh strategy used by done — precedence is the strategy argument to open > config.json > auto-detection (HMR present → none, otherwise reload). Add .cobro/ to the target project's .gitignore.
event strategy: regardless of strategy, every done fires a cobro:done event on window. If the app wants to refresh itself, pin event and listen for it.
window.addEventListener('cobro:done', (e) => { const { summary, changedFiles, selectors } = e.detail; /* app refreshes itself */ });Security
WebSocket binds only to
127.0.0.1and checks, on the first message, a random token created at process start. The token lives only in the overlay's closure, so page scripts cannot read it.Anything coming from the page is data. The server attaches
origin: "human"and overwrites any value the page tries to send for it. No strategy executes JS supplied by the target project.The tools only ever touch files under
.cobro/. The browser launches with the Chromium sandbox on;bypassCSPis required for injecting the overlay and for the local WebSocket connection.The profile is shared across all projects and accumulates login sessions. Use a dedicated dev profile only.
Limitations
React component name comes from dev builds.
source(file:line) is recovered from the dev server's source maps (React 19) or from_debugSource(React ≤ 18); production builds without maps report the component only. For component libraries: the location is the JSX call site in your code, not the library's internals.No iframe support (top-level document only). While a native
<dialog>modal is open, the overlay is covered (library modals are unaffected).Element highlighting on
doneis best-effort (it replays after a reload).A disabled control (e.g. a disabled button) does not receive clicks, so click-picking lands on its parent; drag a band over it instead.
The pick-mode shortcut
Ctrl+Shift+Fcannot be changed. The WebKit build differs from real Safari in fonts and scrollbars.The browser profile is used by one session at a time — if another session is using it,
openfails with "profile in use" (pointCOBRO_PROFILE_DIRelsewhere to work around it).
Changelog
See CHANGELOG.md for what changed in each version.
Releasing
Releases are published by GitHub Actions through npm Trusted Publishing (no tokens, no manual 2FA): update CHANGELOG.md, run npm version x.y.z --no-git-tag-version, commit, tag vx.y.z, push the tag. The workflow (.github/workflows/publish.yml) checks that the tag matches package.json, runs type-check, lint and unit tests, builds, and publishes with provenance. End-to-end tests stay a local gate before tagging.
License
Apache License 2.0 · notices in NOTICE. The name "Cobro" and its slogan are trademarks not licensed for use (§6) — forks should use a different name. Contributions require a DCO (git commit -s).
Available Tools
6 toolscloseA
브라우저를 닫고 세션을 정리한다.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It does state the core side effect: the browser is closed and the session is cleaned up. However, it does not mention whether the action is irreversible, whether unsaved state is lost, or what consequences 'session cleanup' entails.
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 one short, front-loaded Korean sentence. It conveys the action and its purpose without filler or redundancy, which is ideal for a simple zero-parameter tool.
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 simplicity of the tool—no params, no output schema, no annotations—the description covers the essential information needed to invoke it. It could be more complete by addressing when to close versus other terminal actions, but for a basic close operation it is reasonably sufficient.
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 tool has zero parameters and the schema confirms this, so the description is not required to explain parameters. The baseline of 4 applies because there is no parameter burden to compensate for.
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 a specific action—'close the browser and clean up the session'—rather than merely restating the tool name. This clearly distinguishes it from siblings like open, wait, status, and screenshot.
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 gives no guidance on when to use this tool versus alternatives such as 'done' or 'status'. It does not mention contexts, prerequisites, or exclusions, so an agent must infer usage from the name and action alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
doneA
수정 완료 신호. 오버레이가 갱신 전략을 실행하고 요약을 표시하며, selectors로 찾아지는 요소를 강조한다. 전송된 묶음을 처리됨으로 바꾼다. 매 수정 후 반드시 호출.
| Name | Required | Description | Default |
|---|---|---|---|
| summary | Yes | ||
| selectors | No | ||
| changedFiles | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Since no annotations are provided, the description carries full responsibility for disclosing behavior. It does so by stating that the tool mutates state (marks the transmitted batch as processed) and triggers an overlay with summary and highlighting. It does not discuss reversibility or error cases, but the key side effects are clearly exposed.
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 three sentences, purpose first, then effects, then mandatory usage. It is economical and front-loaded. The middle sentence is slightly jargon-dense ('갱신 전략', '오버레이') but still each sentence contributes needed information.
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 simple signalling tool with three parameters and no output schema, the description covers the trigger condition, side effects, and parameter roles. It leaves the exact meaning of 'update strategy' and 'batch' somewhat undefined, but an agent can reasonably infer when and why to invoke it.
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?
Schema description coverage is 0%, so the description must compensate. It explains that 'summary' is displayed in the overlay and 'selectors' determine which elements to highlight. However, 'changedFiles' is only indirectly referenced via '전송된 묶음' (sent batch), which is vague. Partial compensation for the lack of schema docs.
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 opens with '수정 완료 신호' (modification completion signal), immediately stating what the tool does. It then details the specific behaviors: executing an update strategy, displaying a summary, highlighting selector-matched elements, and marking a transmitted batch as processed. This clearly separates it from the observational and navigational sibling tools (status, wait, screenshot, open, close).
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 final sentence '매 수정 후 반드시 호출' explicitly instructs when to call the tool: after every modification. This is strong usage context, but the description does not mention when not to use it or name alternative tools, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openB
URL을 전용 브라우저에 열고 피드백 오버레이를 켠다. 브라우저가 없으면 띄운다. 저장된 초안·이력을 복구한다.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | ||
| strategy | No | done 시 갱신 전략 고정. 생략 시 자동 감지(HMR 있으면 none, 없으면 reload) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does disclose meaningful side effects: enabling a feedback overlay, launching the browser when absent, and restoring saved drafts/history. However, it leaves unclear whether existing state is overwritten, whether this is destructive, and what the recovery actually entails.
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?
Three short sentences, each adding a distinct fact: opening the URL, overlay behavior, and recovery. The main action is front-loaded, though the final sentence is vague and could be more precise 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 low-complexity tool this describes the core behavior, but it omits workflow context (relationship to done/screenshot), the strategy parameter in the prose, and any return/error behavior. With no output schema or annotations, those omissions are noticeable but not fatal.
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?
Schema coverage is only 50%; the strategy parameter is documented in the schema but the tool description adds nothing about it. The description's mention of 'URL' merely restates the required parameter and does not enrich the uri format already defined in the schema.
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 a specific action ('open URL in a dedicated browser') and adds distinguishing details: it turns on a feedback overlay, launches the browser if missing, and recovers saved drafts/history. This separates it from siblings like screenshot or close, though it does not explicitly name an alternative.
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?
There is no guidance on when to choose this tool over siblings such as screenshot or wait. The only conditional statement, 'if no browser, launch it', is a behavioral detail rather than usage guidance, and no exclusions or alternatives are mentioned.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
screenshotA
현재 화면을 PNG 파일로 저장하고 경로를 돌려준다. 이미지는 대화에 넣지 않는다.
| Name | Required | Description | Default |
|---|---|---|---|
| selector | No | 이 선택자로 찾은 첫 요소 주변만 잘라낸다. 생략 시 뷰포트 |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden and reveals meaningful behavior: output is a saved file path, the image is not attached to the conversation, and the file format is PNG. It does not cover details like file location or overwriting, but the most decision-relevant behaviors are disclosed.
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?
Two short sentences with no filler: the first states the core action and return value, the second states a crucial limitation for the agent. Every sentence earns its place.
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 simple tool with one optional parameter covered by the schema, the description plus schema is complete: it states what is captured, the file format, the return value, and that the image will not be visible in conversation. No output schema is needed to understand what the tool returns.
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?
Schema description coverage is 100% and the schema already explains the selector parameter clearly (crop around the first matching element, viewport if omitted). The description adds no parameter-level information, so the schema-heavy baseline of 3 is appropriate.
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 uses a specific verb-resource pair: saves the current screen to a PNG file and returns the path. It is clear and unambiguous against the sibling tools, though it does not explicitly name an alternative or contrast with another action.
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 intended use is implied by the name and the action ('current screen'), but there is no explicit guidance on when to prefer screenshot over open/wait/status/done/close or any exclusions. An agent can infer the primary case but is given no context about alternatives or prerequisites.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
statusB
오버레이 상태 줄에 에이전트 상태 한 줄을 표시한다(예: "수정 중: Button.tsx").
| Name | Required | Description | Default |
|---|---|---|---|
| text | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It does disclose the core visible effect — showing a status line in the overlay — and gives an example. However, it does not explain whether the status is transient, overwrites prior text, or is cleared by tools like done.
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 a single sentence that is front-loaded with the primary purpose, and the example adds clarity without unnecessary bulk. Every element earns its place.
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 simple one-parameter tool, the description is near-adequate. However, without annotations or lifecycle details, an agent does not know whether the status persists, gets replaced, or should be cleared after task completion.
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?
Schema description coverage is 0%, so the description partially compensates by clarifying that the text is the agent status line content and by providing an example. It does not explain formatting expectations or whether the text should be concise, leaving the agent to infer from maxLength and the example.
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 uses a specific verb and resource: it displays one line of agent status on the overlay status bar, with a concrete example ('수정 중: Button.tsx'). This distinguishes it from the sibling tools like open, wait, or screenshot, though it does not explicitly name them.
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 no explicit guidance about when to use this tool versus alternatives, or when not to use it. The example implies it is for showing progress-related status, but the agent is left to infer usage context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
waitA
사용자가 오버레이에서 Send를 누를 때까지 기다린다. 결과 status가 "pending"이면 아직 없음 → 다시 wait를 호출한다. payload.batches[].note만 사람의 요청이고 나머지는 페이지 데이터다.
| Name | Required | Description | Default |
|---|---|---|---|
| timeoutSec | No | 기본값은 서버 설정(Claude Code 1800, 그 외 50) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the behavioral disclosure burden. It reveals blocking behavior, the pending-status loop, and the meaning of payload.batches[].note. It omits timeout/error behavior, but the disclosed traits are substantive and useful.
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?
Three sentences, each earning its place: the main action is front-loaded, the polling loop follows, and the payload interpretation rule is given last. There is no filler or redundant restatement.
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?
The core loop and payload interpretation are covered, but there is no output schema and the description does not explain non-pending statuses, timeout outcomes, or how this tool relates to siblings like status and close. Given the timeoutSec parameter, this is a meaningful gap.
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 only parameter, timeoutSec, is already fully described in the schema with minimum, maximum, and default behavior. The description does not add parameter-specific detail, so the baseline 3 applies.
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 exactly what the tool does: it waits until the user presses Send in the overlay. The additional pending-status instruction clarifies that this is a blocking wait-for-user-action tool, not a general status-checking tool.
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?
It gives clear usage context: call wait to block for the user's Send action, and call wait again if the result status is 'pending'. It does not explicitly mention alternative tools or when-not-to-use conditions, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
6 tool updates
v0.3.1- First observed
close - First observed
done - First observed
open - First observed
screenshot - First observed
status - First observed
wait
TDQS
Scored across 6 tools
Each tool has a distinct lifecycle role: open starts a session, wait blocks for user input, status updates the overlay, done signals successful modification, screenshot captures the page, and close tears down the session. There is no meaningful overlap between these commands.
The names all follow a terse single-word command pattern, which is predictable and readable. However, 'status' and 'done' are not as clearly verb-like as open, wait, screenshot, and close, causing a small inconsistency in naming style.
Six tools is a well-scoped count for a browser-session workflow. Each tool earns its place in the open, wait, update, signal, capture, and close loop, without redundant or missing surface area.
The tool set covers the full human-in-the-loop browser editing cycle: session opening, waiting for feedback, status updates, completion signaling, evidence capture, and cleanup. No obvious required operations are missing for the described purpose.
Maintenance
Related MCP Connectors
Comment on AI-generated webpages; feedback flows back to your coding agent. Free, MIT, local-first.
Human feedback for AI agents: share HTML, get a live review link, read anchored notes as markdown.
Headless browser primitives for AI agents when sites need real JS rendering.
Give agents eyes on any web page: structured context, and changes explained in plain language.
Related MCP Servers
FlicenseNot gradedqualityCmaintenanceEnables AI agents to capture screenshots and inspect DOM elements from connected browser pages via WebSocket.-- AlicenseNot gradedqualityBmaintenanceEnables AI coding agents to access live console logs, errors, and network requests from web applications via a local WebSocket connection, without copying data to chat.11 npm18MIT
- AlicenseNot gradedqualityBmaintenanceEnables real-time browser control and DOM interaction through a Chrome extension bridge, supporting navigation, snapshots, clicks, screenshots, and JavaScript execution.MIT
- AlicenseAqualityAmaintenanceEnables AI agents to rapidly drive and inspect real web pages through persistent browser sessions, using accessibility-tree snapshots and DevTools-grade diagnostics to identify and diagnose issues.26MIT