💬 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:
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"mcpServers": {
|
||||
"context": {
|
||||
"command": "node",
|
||||
"args": ["${CLAUDE_PLUGIN_ROOT}/dist/mcp.js"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -1,18 +1,8 @@
|
||||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"mcp__browse__goto",
|
||||
"mcp__browse__back",
|
||||
"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"
|
||||
"mcp__browse__*",
|
||||
"mcp__browse-dev__*"
|
||||
]
|
||||
},
|
||||
"enableAllProjectMcpServers": true
|
||||
|
||||
@@ -96,25 +96,46 @@ curl localhost:13373 -d '{"cmd":"screenshot","path":"screenshots/page.png"}'
|
||||
|
||||
## 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.
|
||||
|
||||
### 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
|
||||
- `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
|
||||
Tools are then accessible as `mcp__browse__*` (e.g., `mcp__browse__goto`, `mcp__browse__screenshot`).
|
||||
|
||||
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
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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.)
|
||||
@@ -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
|
||||
@@ -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.
|
||||
@@ -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
|
||||
@@ -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.
|
||||
@@ -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`.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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
@@ -10,7 +10,16 @@ import * as image from './image.js';
|
||||
import { stderrLogger as log } from './logger.js';
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
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 currentScreenshotBuffer = null;
|
||||
async function ensureLaunched() {
|
||||
@@ -43,6 +52,61 @@ const server = new McpServer({
|
||||
name: 'browse',
|
||||
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
|
||||
server.tool('goto', 'Navigate to a URL', { url: z.string().url() }, withLogging('goto', async ({ url }) => {
|
||||
await ensureLaunched();
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Generated
+59
@@ -24,6 +24,7 @@
|
||||
"@types/node": "^20.11.0",
|
||||
"@types/sharp": "^0.31.1",
|
||||
"@vitest/coverage-v8": "^4.0.18",
|
||||
"tsx": "^4.21.0",
|
||||
"typescript": "^5.3.0",
|
||||
"vitest": "^4.0.18"
|
||||
},
|
||||
@@ -2418,6 +2419,19 @@
|
||||
"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": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
|
||||
@@ -3011,6 +3025,16 @@
|
||||
"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": {
|
||||
"version": "4.57.1",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.57.1.tgz",
|
||||
@@ -3391,6 +3415,41 @@
|
||||
"license": "0BSD",
|
||||
"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": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz",
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
"@types/node": "^20.11.0",
|
||||
"@types/sharp": "^0.31.1",
|
||||
"@vitest/coverage-v8": "^4.0.18",
|
||||
"tsx": "^4.21.0",
|
||||
"typescript": "^5.3.0",
|
||||
"vitest": "^4.0.18"
|
||||
},
|
||||
|
||||
+76
-1
@@ -12,7 +12,16 @@ import { type CommandLike, type ResultLike, stderrLogger as log } from './logger
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
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 currentScreenshotBuffer: Buffer | null = null;
|
||||
|
||||
@@ -54,6 +63,72 @@ const server = new McpServer({
|
||||
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
|
||||
server.tool(
|
||||
'goto',
|
||||
|
||||
Reference in New Issue
Block a user