This commit is contained in:
ray zhou
2026-05-29 11:21:40 +08:00
parent 5d6d482efe
commit f71a5c59af
447 changed files with 32245 additions and 116 deletions

View File

@@ -0,0 +1,46 @@
The cursor-ide-browser MCP server provides a Cursor-owned browser tab plus a raw Chrome DevTools Protocol command tool.
CORE WORKFLOW:
1. Start by understanding the user's goal and what success looks like on the page.
2. Use browser_tabs with action "list" to inspect open tabs and URLs before acting.
3. Use browser_navigate to create or navigate the target tab. Omit the position parameter for background automation so focus is preserved.
4. Use browser_lock before longer automation on an existing tab, then browser_lock with action "unlock" when finished.
5. Use browser_snapshot for accessibility context and browser_take_screenshot for visual verification.
6. Use browser_click, browser_type, browser_fill, browser_select_option, browser_press_key, browser_scroll, and browser_drag for page interactions.
7. Use browser_highlight and browser_get_bounding_box for visual grounding and coordinate diagnostics.
8. Use browser_cdp for page inspection, profiling, runtime evaluation, DOM/CSS queries, and performance data.
AVOID RABBIT HOLES:
1. Do not repeat the same failing action more than once without new evidence such as a fresh snapshot, a different ref, a changed page state, or a clear new hypothesis.
2. IMPORTANT: If four attempts fail or progress stalls, stop acting and report what you observed, what blocked progress, and the most likely next step.
3. Prefer gathering evidence over brute force. If the page is confusing, use browser_snapshot, browser_take_screenshot, or CDP inspection before trying more actions.
4. If you encounter a blocker such as login, passkey/manual user interaction, permissions, captchas, destructive confirmations, missing data, or an unexpected state, stop and report it instead of improvising repeated actions.
5. Do not get stuck in wait-action-wait loops. Every retry should be justified by something newly observed.
CRITICAL - Lock/unlock workflow:
1. browser_lock requires an existing browser tab - you CANNOT call browser_lock with action: "lock" before browser_navigate
2. Correct order: browser_navigate -> browser_lock({ action: "lock" }) -> (interactions) -> browser_lock({ action: "unlock" })
3. If a browser tab already exists (check with browser_tabs list), call browser_lock with action: "lock" FIRST before any interactions
4. Only call browser_lock with action: "unlock" when completely done with ALL browser operations for this turn
IMPORTANT - Waiting strategy:
When waiting for page changes, prefer short CDP polling loops with Runtime.evaluate, DOM queries, Page lifecycle signals, or browser_snapshot checks rather than a single long wait.
CDP USAGE:
- Use browser_cdp with a DevTools Protocol method and params object, for example Runtime.evaluate, DOM.getDocument, CSS.getComputedStyleForNode, Profiler.start/stop, Performance.getMetrics, Log.enable, and Network.enable.
- Do not use browser_cdp with CDP Input.* methods. They are denied because they are focus-sensitive in Electron webviews and can route input to Cursor UI instead of the browser page.
- Use browser_click, browser_type, browser_fill, browser_select_option, browser_press_key, browser_scroll, and browser_drag for clicks, typing, filling inputs, selecting options, keyboard actions, scrolling, and drag-and-drop.
- Use Runtime.evaluate for advanced DOM-scoped interactions that the dedicated browser tools do not cover.
- For profiling, call Profiler.enable, Profiler.start, reproduce the behavior, then Profiler.stop. The profile is saved to a file and returned as a log_file; read that file only when you need to inspect details.
- For JavaScript evaluation, prefer Runtime.evaluate with returnByValue when possible.
- Some browser-wide or sensitive CDP methods are denied, especially cookie, storage, permission, download, target-management, filesystem-backed file-input commands, system-level commands, and CDP navigation/history navigation commands.
- Large CDP responses are saved to files instead of being inlined. Prefer using the returned file path over immediately stuffing large payloads into context; read focused sections only when needed.
VISION:
- browser_take_screenshot attaches an image result that the model can inspect. CDP Page.captureScreenshot returns data inside JSON and should not replace browser_take_screenshot when visual verification is needed.
NOTES:
- browser_snapshot returns snapshot YAML and is the main source of truth for page structure.
- Refs are opaque handles tied to the latest browser_snapshot for that tab.
- Iframe content is not accessible - only elements outside iframes can be interacted with.
- When you stop to report a blocker, include the current page, the target you were trying to reach, the blocker you observed, and the best next action. If the blocker requires manual user interaction, ask the user to take over at that point rather than assuming it in advance.

View File

@@ -0,0 +1,4 @@
{
"serverIdentifier": "cursor-ide-browser",
"serverName": "cursor-ide-browser"
}

View File

@@ -0,0 +1,28 @@
{
"name": "browser_cdp",
"description": "Send a Chrome DevTools Protocol command to the target browser tab. Do not use CDP Input.* methods; use dedicated browser tools for clicks, text input, key presses, scrolling, and drag-and-drop. Browser-wide, storage, cookie, permission, download, target-management, and system-level commands are denied.",
"arguments": {
"type": "object",
"properties": {
"method": {
"type": "string",
"description": "CDP method name, for example Runtime.evaluate, DOM.getDocument, Profiler.start, or Performance.getMetrics."
},
"params": {
"type": "object",
"description": "CDP params object. Omit or pass {} when the command takes no params."
},
"viewId": {
"type": "string",
"description": "Target browser tab ID. If omitted, uses the last interacted tab."
},
"take_screenshot_afterwards": {
"type": "boolean",
"description": "When true, takes a screenshot after the CDP command completes. Defaults to false."
}
},
"required": [
"method"
]
}
}

View File

@@ -0,0 +1,67 @@
{
"name": "browser_click",
"description": "Click an element by ref from browser_snapshot. Use this instead of CDP Input.* methods.",
"arguments": {
"type": "object",
"properties": {
"ref": {
"type": "string",
"description": "Element ref from browser_snapshot."
},
"element": {
"type": "string",
"description": "Human-readable description of the element."
},
"offsetX": {
"type": "number",
"description": "Optional x offset from the element center."
},
"offsetY": {
"type": "number",
"description": "Optional y offset from the element center."
},
"doubleClick": {
"type": "boolean",
"description": "When true, double-click the element."
},
"button": {
"type": "string",
"enum": [
"left",
"right",
"middle"
],
"description": "Mouse button. Defaults to left."
},
"modifiers": {
"type": "array",
"items": {
"type": "string",
"enum": [
"Control",
"Shift",
"Alt",
"Meta",
"ControlOrMeta"
]
},
"description": "Optional modifier keys."
},
"holdDurationMs": {
"type": "number",
"description": "Optional mouse hold duration before release."
},
"viewId": {
"type": "string",
"description": "Target browser tab ID. If omitted, uses the last interacted tab."
},
"take_screenshot_afterwards": {
"type": "boolean",
"description": "When true, takes a screenshot after the click completes. Defaults to false."
}
},
"required": [
"ref"
]
}
}

View File

@@ -0,0 +1,36 @@
{
"name": "browser_drag",
"description": "Drag an element by ref to another ref or viewport coordinates.",
"arguments": {
"type": "object",
"properties": {
"sourceRef": {
"type": "string",
"description": "Source element ref from browser_snapshot."
},
"targetRef": {
"type": "string",
"description": "Optional target element ref from browser_snapshot."
},
"targetX": {
"type": "number",
"description": "Optional target viewport x coordinate."
},
"targetY": {
"type": "number",
"description": "Optional target viewport y coordinate."
},
"viewId": {
"type": "string",
"description": "Target browser tab ID. If omitted, uses the last interacted tab."
},
"take_screenshot_afterwards": {
"type": "boolean",
"description": "When true, takes a screenshot after drag completes. Defaults to false."
}
},
"required": [
"sourceRef"
]
}
}

View File

@@ -0,0 +1,33 @@
{
"name": "browser_fill",
"description": "Set the value of an input, textarea, or contenteditable element by ref.",
"arguments": {
"type": "object",
"properties": {
"ref": {
"type": "string",
"description": "Element ref from browser_snapshot."
},
"value": {
"type": "string",
"description": "Value to set."
},
"element": {
"type": "string",
"description": "Human-readable description of the element."
},
"viewId": {
"type": "string",
"description": "Target browser tab ID. If omitted, uses the last interacted tab."
},
"take_screenshot_afterwards": {
"type": "boolean",
"description": "When true, takes a screenshot after filling completes. Defaults to false."
}
},
"required": [
"ref",
"value"
]
}
}

View File

@@ -0,0 +1,24 @@
{
"name": "browser_get_bounding_box",
"description": "Get the viewport bounding box for an element ref.",
"arguments": {
"type": "object",
"properties": {
"ref": {
"type": "string",
"description": "Element ref from browser_snapshot."
},
"element": {
"type": "string",
"description": "Human-readable description of the element."
},
"viewId": {
"type": "string",
"description": "Target browser tab ID. If omitted, uses the last interacted tab."
}
},
"required": [
"ref"
]
}
}

View File

@@ -0,0 +1,28 @@
{
"name": "browser_highlight",
"description": "Highlight an element by ref in the browser page for visual grounding.",
"arguments": {
"type": "object",
"properties": {
"ref": {
"type": "string",
"description": "Element ref from browser_snapshot."
},
"element": {
"type": "string",
"description": "Human-readable description of the element."
},
"durationMs": {
"type": "number",
"description": "Highlight duration in milliseconds. Defaults to 2000."
},
"viewId": {
"type": "string",
"description": "Target browser tab ID. If omitted, uses the last interacted tab."
}
},
"required": [
"ref"
]
}
}

View File

@@ -0,0 +1,24 @@
{
"name": "browser_lock",
"description": "Lock or unlock the browser to control whether the user can interact while you work. Set action to \"lock\" or \"unlock\". When locked, the user can still click \"Take Control\" to unlock if needed.",
"arguments": {
"type": "object",
"properties": {
"action": {
"type": "string",
"enum": [
"lock",
"unlock"
],
"description": "Whether to lock or unlock the browser for user interaction."
},
"viewId": {
"type": "string",
"description": "Target browser tab ID. If omitted, uses the last interacted tab."
}
},
"required": [
"action"
]
}
}

View File

@@ -0,0 +1,38 @@
{
"name": "browser_mouse_click_xy",
"description": "Click at viewport coordinates. Prefer browser_click with refs when possible.",
"arguments": {
"type": "object",
"properties": {
"x": {
"type": "number",
"description": "Viewport x coordinate."
},
"y": {
"type": "number",
"description": "Viewport y coordinate."
},
"button": {
"type": "string",
"enum": [
"left",
"right",
"middle"
],
"description": "Mouse button. Defaults to left."
},
"viewId": {
"type": "string",
"description": "Target browser tab ID. If omitted, uses the last interacted tab."
},
"take_screenshot_afterwards": {
"type": "boolean",
"description": "When true, takes a screenshot after the click completes. Defaults to false."
}
},
"required": [
"x",
"y"
]
}
}

View File

@@ -0,0 +1,36 @@
{
"name": "browser_navigate",
"description": "Navigate to a URL. By default reuses an existing tab; set newTab: true to open in a new tab.",
"arguments": {
"type": "object",
"properties": {
"url": {
"type": "string",
"description": "The URL to navigate to"
},
"viewId": {
"type": "string",
"description": "Target browser tab ID. If omitted, uses the last interacted tab."
},
"position": {
"type": "string",
"enum": [
"active",
"side"
],
"description": "Only set when the user explicitly asks to reveal, show, focus, or open the browser visibly. Set to \"active\" for visible/revealed browser UI, or \"side\" if the user mentions \"side\", \"beside\", \"side panel\", or \"side by side\". Omit this parameter for background automation so focus is preserved."
},
"take_screenshot_afterwards": {
"type": "boolean",
"description": "When true, takes a screenshot after navigation completes. Defaults to false."
},
"newTab": {
"type": "boolean",
"description": "When true, creates a new tab before navigating instead of reusing an existing tab. Defaults to false."
}
},
"required": [
"url"
]
}
}

View File

@@ -0,0 +1,24 @@
{
"name": "browser_press_key",
"description": "Press a key in the browser page using DOM keyboard events.",
"arguments": {
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "Key to press, for example Enter, Escape, Tab, ArrowDown, or a single character."
},
"viewId": {
"type": "string",
"description": "Target browser tab ID. If omitted, uses the last interacted tab."
},
"take_screenshot_afterwards": {
"type": "boolean",
"description": "When true, takes a screenshot after the key press completes. Defaults to false."
}
},
"required": [
"key"
]
}
}

View File

@@ -0,0 +1,48 @@
{
"name": "browser_scroll",
"description": "Scroll the page, a scrollable container, or an element into view. Use this instead of CDP Input.* wheel events.",
"arguments": {
"type": "object",
"properties": {
"ref": {
"type": "string",
"description": "Optional element ref from browser_snapshot."
},
"direction": {
"type": "string",
"enum": [
"up",
"down",
"left",
"right"
],
"description": "Scroll direction."
},
"amount": {
"type": "number",
"description": "Scroll amount in pixels. Defaults to 300."
},
"deltaX": {
"type": "number",
"description": "Explicit horizontal scroll delta."
},
"deltaY": {
"type": "number",
"description": "Explicit vertical scroll delta."
},
"scrollIntoView": {
"type": "boolean",
"description": "When true, scroll the ref into view."
},
"viewId": {
"type": "string",
"description": "Target browser tab ID. If omitted, uses the last interacted tab."
},
"take_screenshot_afterwards": {
"type": "boolean",
"description": "When true, takes a screenshot after scrolling completes. Defaults to false."
}
},
"required": []
}
}

View File

@@ -0,0 +1,36 @@
{
"name": "browser_select_option",
"description": "Select one or more options in a select element by ref.",
"arguments": {
"type": "object",
"properties": {
"ref": {
"type": "string",
"description": "Element ref from browser_snapshot."
},
"values": {
"type": "array",
"items": {
"type": "string"
},
"description": "Option values or labels to select."
},
"element": {
"type": "string",
"description": "Human-readable description of the element."
},
"viewId": {
"type": "string",
"description": "Target browser tab ID. If omitted, uses the last interacted tab."
},
"take_screenshot_afterwards": {
"type": "boolean",
"description": "When true, takes a screenshot after selection completes. Defaults to false."
}
},
"required": [
"ref",
"values"
]
}
}

View File

@@ -0,0 +1,38 @@
{
"name": "browser_snapshot",
"description": "Capture accessibility snapshot of the current page, this is better than screenshot",
"arguments": {
"type": "object",
"properties": {
"viewId": {
"type": "string",
"description": "Target browser tab ID. If omitted, uses the last interacted tab."
},
"interactive": {
"type": "boolean",
"description": "When true, only include interactive elements in the snapshot. Defaults to false."
},
"maxDepth": {
"type": "number",
"description": "Maximum depth for snapshot output. Defaults to 20."
},
"compact": {
"type": "boolean",
"description": "When true, outputs a more compact snapshot format. Defaults to false."
},
"selector": {
"type": "string",
"description": "Optional CSS selector to scope the snapshot to a subtree."
},
"includeDiff": {
"type": "boolean",
"description": "When true, include a diff vs the previous snapshot for this tab. Defaults to false."
},
"take_screenshot_afterwards": {
"type": "boolean",
"description": "When true, takes a screenshot after snapshot completes. Defaults to false."
}
},
"required": []
}
}

View File

@@ -0,0 +1,34 @@
{
"name": "browser_tabs",
"description": "List, create, close, or select a browser tab",
"arguments": {
"type": "object",
"properties": {
"action": {
"type": "string",
"enum": [
"list",
"new",
"close",
"select"
],
"description": "Operation to perform"
},
"index": {
"type": "number",
"description": "Tab index. Required for \"select\". Optional for \"close\" (defaults to current tab)."
},
"position": {
"type": "string",
"enum": [
"active",
"side"
],
"description": "Only set for action \"new\" when the user explicitly asks to reveal, show, focus, or open the browser visibly. Set to \"active\" for visible/revealed browser UI, or \"side\" if the user mentions \"side\", \"beside\", \"side panel\", or \"side by side\". Omit this parameter for background automation so focus is preserved."
}
},
"required": [
"action"
]
}
}

View File

@@ -0,0 +1,34 @@
{
"name": "browser_take_screenshot",
"description": "Take a screenshot of the current page. You can't perform actions based on the screenshot, use browser_snapshot for actions.",
"arguments": {
"type": "object",
"properties": {
"type": {
"type": "string",
"description": "Image format for the screenshot. Default is png."
},
"filename": {
"type": "string",
"description": "File name to save the screenshot to. Defaults to page-{timestamp}.{png|jpeg} if not specified."
},
"element": {
"type": "string",
"description": "Description of the element, if taking a screenshot of an element"
},
"ref": {
"type": "string",
"description": "CSS selector for the element, if taking a screenshot of an element"
},
"fullPage": {
"type": "boolean",
"description": "When true, takes a screenshot of the full scrollable page, instead of the currently visible viewport. Cannot be used with element screenshots."
},
"viewId": {
"type": "string",
"description": "Target browser tab ID. If omitted, uses the last interacted tab."
}
},
"required": []
}
}

View File

@@ -0,0 +1,45 @@
{
"name": "browser_type",
"description": "Type text into an input, textarea, or contenteditable element by ref.",
"arguments": {
"type": "object",
"properties": {
"ref": {
"type": "string",
"description": "Element ref from browser_snapshot."
},
"text": {
"type": "string",
"description": "Text to type."
},
"element": {
"type": "string",
"description": "Human-readable description of the element."
},
"clear": {
"type": "boolean",
"description": "When true, clear existing text first."
},
"submit": {
"type": "boolean",
"description": "When true, press Enter after typing."
},
"slowly": {
"type": "boolean",
"description": "When true, type character by character."
},
"viewId": {
"type": "string",
"description": "Target browser tab ID. If omitted, uses the last interacted tab."
},
"take_screenshot_afterwards": {
"type": "boolean",
"description": "When true, takes a screenshot after typing completes. Defaults to false."
}
},
"required": [
"ref",
"text"
]
}
}

View File

@@ -0,0 +1,4 @@
{
"serverIdentifier": "plugin-figma-figma",
"serverName": "plugin-figma-figma"
}

View File

@@ -0,0 +1 @@
The MCP server needs authentication. You must call the `mcp_auth` tool for server "plugin-figma-figma" through your MCP tool-calling interface using an empty arguments object `{}` soon so the user can access all of the tools this MCP server offers.

View File

@@ -0,0 +1,9 @@
{
"name": "mcp_auth",
"description": "Authenticate this MCP server so the user can access all of its tools. When STATUS.md indicates this server needs authentication, you must call this tool soon through your MCP tool-calling interface.",
"arguments": {
"type": "object",
"properties": {},
"additionalProperties": false
}
}