💬 Commit message: Update 2026-02-11 18:40:23, 20 files, 434 lines

📁 Files changed: 20
📝 Lines changed: 434

  • .mcp.json
  • plugin.json
  • settings.json
  • CLAUDE.md
  • analyze.md
  • compare.md
  • end.md
  • extract.md
  • fill.md
  • goto.md
  • restore.md
  • save.md
  • scrape.md
  • screenshot.md
  • start.md
  • mcp.js
  • mcp.js.map
  • package-lock.json
  • package.json
  • mcp.ts
This commit is contained in:
Adam Ladachowski
2026-02-11 18:40:23 +01:00
parent 749868241d
commit d9f88a37c9
20 changed files with 239 additions and 197 deletions
-8
View File
@@ -1,8 +0,0 @@
{
"mcpServers": {
"context": {
"command": "node",
"args": ["${CLAUDE_PLUGIN_ROOT}/dist/mcp.js"]
}
}
}
-22
View File
@@ -1,22 +0,0 @@
{
"name": "browse",
"description": "Browser automation and image processing tools for Claude Code using Playwright WebKit",
"version": "0.2.13-pre.0",
"author": {
"name": "aladac",
"url": "https://github.com/aladac"
},
"repository": "https://github.com/saiden-dev/browse",
"license": "MIT",
"keywords": [
"browser",
"automation",
"playwright",
"webkit",
"screenshot",
"scraping",
"image-processing"
],
"mcpServers": "./.mcp.json",
"commands": "./commands"
}
+2 -12
View File
@@ -1,18 +1,8 @@
{ {
"permissions": { "permissions": {
"allow": [ "allow": [
"mcp__browse__goto", "mcp__browse__*",
"mcp__browse__back", "mcp__browse-dev__*"
"mcp__browse__forward",
"mcp__browse__reload",
"mcp__browse__click",
"mcp__browse__type",
"mcp__browse__query",
"mcp__browse__url",
"mcp__browse__html",
"mcp__browse__screenshot",
"mcp__browse__eval",
"mcp__browse__wait"
] ]
}, },
"enableAllProjectMcpServers": true "enableAllProjectMcpServers": true
+35 -14
View File
@@ -96,25 +96,46 @@ curl localhost:13373 -d '{"cmd":"screenshot","path":"screenshots/page.png"}'
## MCP Server ## MCP Server
Run as MCP server for Claude Code integration:
```bash
browse-mcp
```
The MCP server (`src/mcp.ts`) exposes all browser commands as tools. It uses stdio transport and auto-launches the browser on first command. The MCP server (`src/mcp.ts`) exposes all browser commands as tools. It uses stdio transport and auto-launches the browser on first command.
### Plugin Integration ### Production Setup
When installed as a Claude Code plugin (`browse@saiden`), the MCP server is named `context`. Tools are accessed as: Add to your project's `.mcp.json`:
```json
{
"mcpServers": {
"browse": {
"command": "npx",
"args": ["browse-mcp"]
}
}
}
```
- `mcp__context__goto` - Navigate to URL Tools are then accessible as `mcp__browse__*` (e.g., `mcp__browse__goto`, `mcp__browse__screenshot`).
- `mcp__context__query` - Query elements by CSS selector
- `mcp__context__click` - Click an element
- `mcp__context__type` - Type into an input field
- `mcp__context__screenshot` - Take a screenshot
- `mcp__context__close` - Close the browser
The plugin also provides slash commands: `/browse:start`, `/browse:goto`, `/browse:end`, etc. ### Development (this project only)
This project uses a local `.mcp.json` pointing to `dist/mcp.js` for development. Use `npm run dev` for hot-reload during development.
### Launch Options
Use the `launch` tool to configure browser mode before navigating:
| Option | Default | Description |
|--------|---------|-------------|
| `headed` | `false` | Show browser window |
| `fullscreen` | `false` | Native fullscreen mode (macOS, implies headed) |
| `preview` | `false` | Highlight elements before actions with visual overlay |
| `previewDelay` | `2000` | Duration of preview highlight in ms |
| `width` | `1280` | Viewport width |
| `height` | `800` | Viewport height |
Example: Launch in fullscreen with preview mode:
```
mcp__browse__launch({ fullscreen: true, preview: true })
mcp__browse__goto({ url: "https://example.com" })
```
### Debugging Tools ### Debugging Tools
-13
View File
@@ -1,13 +0,0 @@
---
description: Analyze the current page content and structure
---
Use the analyze_page MCP prompt to analyze the current browser page.
If the browser is not launched, first navigate to a URL using the goto tool, then analyze the page structure, content, and interactive elements.
Provide:
1. A summary of the page purpose
2. Key interactive elements (forms, buttons, links)
3. Notable structure or patterns
4. Suggestions for useful actions
-13
View File
@@ -1,13 +0,0 @@
---
description: Compare page states with screenshots before and after an action
---
Compare page states:
1. Take an initial screenshot of the current page
2. Ask what action to perform (click, navigate, submit, etc.)
3. Perform the requested action
4. Take another screenshot
5. Describe the visual and structural differences
What action would you like to perform between screenshots? $ARGUMENTS
-12
View File
@@ -1,12 +0,0 @@
---
description: End the current browsing session and close the browser
---
End the current browsing session.
Use the `close` tool to close the browser. This will:
1. Close all browser pages
2. Clear the browser state
3. Free up system resources
The browser can be relaunched with any navigation command (goto, start, etc.)
-13
View File
@@ -1,13 +0,0 @@
---
description: Extract structured data from the current page
---
Extract structured data from the current browser page.
Selector (optional): $ARGUMENTS
Steps:
1. If a selector is provided, use the query tool to find matching elements
2. Analyze the page structure to identify data patterns
3. Extract and structure the data in a useful format (JSON, table, etc.)
4. Identify patterns that could help with similar pages
-13
View File
@@ -1,13 +0,0 @@
---
description: Help fill out a form on the current page
---
Fill form with data: $ARGUMENTS
Steps:
1. Use the query tool to find form inputs (input, textarea, select)
2. Identify required fields and their types
3. If data is provided, parse it and fill the matching fields using the type tool
4. Report what was filled and any issues encountered
If no data provided, describe the form fields found and ask what to fill in.
-12
View File
@@ -1,12 +0,0 @@
---
description: Navigate to a URL and describe what you find
---
Navigate to: $ARGUMENTS
Steps:
1. Use the goto tool to navigate to the URL
2. Take a screenshot to see the page
3. Describe what you see
4. Identify the main interactive elements
5. Suggest what actions might be useful
-13
View File
@@ -1,13 +0,0 @@
---
description: Restore a previously saved browsing session
---
Restore session from: $ARGUMENTS
Use the `session_restore` tool to restore a previously saved session:
- Navigate to the saved URL
- Restore all cookies
- Restore localStorage data
- Restore sessionStorage data
If no path is specified, restore from `session.json` in the current directory.
-15
View File
@@ -1,15 +0,0 @@
---
description: Save the current browsing session state to a file
---
Save the current session state to: $ARGUMENTS
Use the `session_save` tool to save:
- Current URL and page title
- All cookies
- localStorage data
- sessionStorage data
If no path is specified, save to `session.json` in the current directory.
This allows you to restore the session later with `/browse:restore`.
-14
View File
@@ -1,14 +0,0 @@
---
description: Scrape content from a webpage
---
Scrape and extract content from: $ARGUMENTS
Steps:
1. Navigate to the URL using `goto`
2. Wait for the page to load
3. Query the page structure to understand the layout
4. Extract the relevant content using `query` and `eval` tools
5. Return the structured data
Focus on extracting meaningful content (text, links, data) rather than raw HTML.
-9
View File
@@ -1,9 +0,0 @@
---
description: Take a screenshot of the current page
---
Take a screenshot of the current browser page and analyze its contents.
If the browser hasn't been started yet, ask for a URL first, navigate there, then take the screenshot.
Use the `screenshot` tool with fullPage=$ARGUMENTS if specified (true/false), otherwise use default viewport.
-11
View File
@@ -1,11 +0,0 @@
---
description: Start an interactive browsing session
---
Start an interactive browser session. Use the browser tools to:
1. Navigate to URLs with `goto`
2. Take screenshots to see page content
3. Query elements with CSS selectors
4. Click and type to interact with pages
The browser is headless WebKit (Safari engine). Start by asking what URL to visit.
Vendored
+65 -1
View File
@@ -10,7 +10,16 @@ import * as image from './image.js';
import { stderrLogger as log } from './logger.js'; import { stderrLogger as log } from './logger.js';
const __dirname = dirname(fileURLToPath(import.meta.url)); const __dirname = dirname(fileURLToPath(import.meta.url));
const pkg = JSON.parse(readFileSync(resolve(__dirname, '../package.json'), 'utf-8')); const pkg = JSON.parse(readFileSync(resolve(__dirname, '../package.json'), 'utf-8'));
const browser = new ClaudeBrowser({ headless: true, width: 1280, height: 800 }); // Browser options configurable via launch tool
let browserOptions = {
headless: true,
width: 1280,
height: 800,
fullscreen: false,
preview: false,
previewDelay: 2000,
};
let browser = new ClaudeBrowser(browserOptions);
let launched = false; let launched = false;
let currentScreenshotBuffer = null; let currentScreenshotBuffer = null;
async function ensureLaunched() { async function ensureLaunched() {
@@ -43,6 +52,61 @@ const server = new McpServer({
name: 'browse', name: 'browse',
version: pkg.version, version: pkg.version,
}); });
// Launch configuration
server.tool('launch', 'Launch the browser with specific options. Call before goto to configure headed/fullscreen/preview modes.', {
headed: z
.boolean()
.optional()
.default(false)
.describe('Show browser window (default: false, headless)'),
fullscreen: z
.boolean()
.optional()
.default(false)
.describe('Launch in native fullscreen mode (macOS only, implies headed)'),
preview: z
.boolean()
.optional()
.default(false)
.describe('Highlight elements before actions with visual overlay'),
previewDelay: z
.number()
.optional()
.default(2000)
.describe('Preview highlight duration in ms'),
width: z.number().optional().default(1280).describe('Viewport width'),
height: z.number().optional().default(800).describe('Viewport height'),
}, withLogging('launch', async ({ headed, fullscreen, preview, previewDelay, width, height }) => {
// Close existing browser if launched
if (launched) {
await browser.close();
launched = false;
}
// Update options - fullscreen/preview imply headed
browserOptions = {
headless: fullscreen || preview ? false : !headed,
width,
height,
fullscreen,
preview,
previewDelay,
};
// Create new browser with updated options
browser = new ClaudeBrowser(browserOptions);
await browser.launch();
launched = true;
return textResult(JSON.stringify({
ok: true,
message: 'Browser launched',
options: {
headed: !browserOptions.headless,
fullscreen,
preview,
previewDelay,
viewport: { width, height },
},
}));
}));
// Navigation // Navigation
server.tool('goto', 'Navigate to a URL', { url: z.string().url() }, withLogging('goto', async ({ url }) => { server.tool('goto', 'Navigate to a URL', { url: z.string().url() }, withLogging('goto', async ({ url }) => {
await ensureLaunched(); await ensureLaunched();
+1 -1
View File
File diff suppressed because one or more lines are too long
+59
View File
@@ -24,6 +24,7 @@
"@types/node": "^20.11.0", "@types/node": "^20.11.0",
"@types/sharp": "^0.31.1", "@types/sharp": "^0.31.1",
"@vitest/coverage-v8": "^4.0.18", "@vitest/coverage-v8": "^4.0.18",
"tsx": "^4.21.0",
"typescript": "^5.3.0", "typescript": "^5.3.0",
"vitest": "^4.0.18" "vitest": "^4.0.18"
}, },
@@ -2418,6 +2419,19 @@
"node": ">= 0.4" "node": ">= 0.4"
} }
}, },
"node_modules/get-tsconfig": {
"version": "4.13.6",
"resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.6.tgz",
"integrity": "sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw==",
"dev": true,
"license": "MIT",
"dependencies": {
"resolve-pkg-maps": "^1.0.0"
},
"funding": {
"url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
}
},
"node_modules/gopd": { "node_modules/gopd": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
@@ -3011,6 +3025,16 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/resolve-pkg-maps": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
"integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
"dev": true,
"license": "MIT",
"funding": {
"url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
}
},
"node_modules/rollup": { "node_modules/rollup": {
"version": "4.57.1", "version": "4.57.1",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.57.1.tgz", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.57.1.tgz",
@@ -3391,6 +3415,41 @@
"license": "0BSD", "license": "0BSD",
"optional": true "optional": true
}, },
"node_modules/tsx": {
"version": "4.21.0",
"resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz",
"integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==",
"dev": true,
"license": "MIT",
"dependencies": {
"esbuild": "~0.27.0",
"get-tsconfig": "^4.7.5"
},
"bin": {
"tsx": "dist/cli.mjs"
},
"engines": {
"node": ">=18.0.0"
},
"optionalDependencies": {
"fsevents": "~2.3.3"
}
},
"node_modules/tsx/node_modules/fsevents": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/type-is": { "node_modules/type-is": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz",
+1
View File
@@ -59,6 +59,7 @@
"@types/node": "^20.11.0", "@types/node": "^20.11.0",
"@types/sharp": "^0.31.1", "@types/sharp": "^0.31.1",
"@vitest/coverage-v8": "^4.0.18", "@vitest/coverage-v8": "^4.0.18",
"tsx": "^4.21.0",
"typescript": "^5.3.0", "typescript": "^5.3.0",
"vitest": "^4.0.18" "vitest": "^4.0.18"
}, },
+76 -1
View File
@@ -12,7 +12,16 @@ import { type CommandLike, type ResultLike, stderrLogger as log } from './logger
const __dirname = dirname(fileURLToPath(import.meta.url)); const __dirname = dirname(fileURLToPath(import.meta.url));
const pkg = JSON.parse(readFileSync(resolve(__dirname, '../package.json'), 'utf-8')); const pkg = JSON.parse(readFileSync(resolve(__dirname, '../package.json'), 'utf-8'));
const browser = new ClaudeBrowser({ headless: true, width: 1280, height: 800 }); // Browser options configurable via launch tool
let browserOptions = {
headless: true,
width: 1280,
height: 800,
fullscreen: false,
preview: false,
previewDelay: 2000,
};
let browser = new ClaudeBrowser(browserOptions);
let launched = false; let launched = false;
let currentScreenshotBuffer: Buffer | null = null; let currentScreenshotBuffer: Buffer | null = null;
@@ -54,6 +63,72 @@ const server = new McpServer({
version: pkg.version, version: pkg.version,
}); });
// Launch configuration
server.tool(
'launch',
'Launch the browser with specific options. Call before goto to configure headed/fullscreen/preview modes.',
{
headed: z
.boolean()
.optional()
.default(false)
.describe('Show browser window (default: false, headless)'),
fullscreen: z
.boolean()
.optional()
.default(false)
.describe('Launch in native fullscreen mode (macOS only, implies headed)'),
preview: z
.boolean()
.optional()
.default(false)
.describe('Highlight elements before actions with visual overlay'),
previewDelay: z
.number()
.optional()
.default(2000)
.describe('Preview highlight duration in ms'),
width: z.number().optional().default(1280).describe('Viewport width'),
height: z.number().optional().default(800).describe('Viewport height'),
},
withLogging('launch', async ({ headed, fullscreen, preview, previewDelay, width, height }) => {
// Close existing browser if launched
if (launched) {
await browser.close();
launched = false;
}
// Update options - fullscreen/preview imply headed
browserOptions = {
headless: fullscreen || preview ? false : !headed,
width,
height,
fullscreen,
preview,
previewDelay,
};
// Create new browser with updated options
browser = new ClaudeBrowser(browserOptions);
await browser.launch();
launched = true;
return textResult(
JSON.stringify({
ok: true,
message: 'Browser launched',
options: {
headed: !browserOptions.headless,
fullscreen,
preview,
previewDelay,
viewport: { width, height },
},
})
);
})
);
// Navigation // Navigation
server.tool( server.tool(
'goto', 'goto',