UNPKG

claude-flow

Version:

Ruflo - Enterprise AI agent orchestration for Claude Code. Deploy 60+ specialized agents in coordinated swarms with self-learning, fault-tolerant consensus, vector memory, and MCP integration

550 lines 19.7 kB
/** * Browser MCP Tools * * CLI integration for @claude-flow/browser package. * Provides browser automation tools for web navigation, interaction, and data extraction. */ // Session registry for multi-session support const browserSessions = new Map(); /** * Execute agent-browser CLI command */ async function execBrowserCommand(args, session = 'default') { const { execSync } = await import('child_process'); try { const fullArgs = ['--session', session, '--json', ...args]; const result = execSync(`agent-browser ${fullArgs.join(' ')}`, { encoding: 'utf-8', timeout: 30000, }); let data; try { data = JSON.parse(result); } catch { data = result.trim(); } // Update session activity const sessionInfo = browserSessions.get(session); if (sessionInfo) { sessionInfo.lastActivity = new Date().toISOString(); } return { content: [{ type: 'text', text: JSON.stringify(data, null, 2), }], }; } catch (error) { return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: error instanceof Error ? error.message : String(error), }), }], isError: true, }; } } /** * Browser MCP Tools */ export const browserTools = [ // ========================================================================== // Navigation Tools // ========================================================================== { name: 'browser_open', description: 'Navigate browser to a URL', category: 'browser', tags: ['navigation', 'web'], inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'URL to navigate to' }, session: { type: 'string', description: 'Session ID (default: "default")' }, waitUntil: { type: 'string', enum: ['load', 'domcontentloaded', 'networkidle'], description: 'Wait condition', }, }, required: ['url'], }, handler: async (input) => { const { url, session, waitUntil } = input; const args = ['open', url]; if (waitUntil) args.push('--wait-until', waitUntil); // Create session if new const sessionId = session || 'default'; if (!browserSessions.has(sessionId)) { browserSessions.set(sessionId, { sessionId, createdAt: new Date().toISOString(), lastActivity: new Date().toISOString(), }); } return execBrowserCommand(args, sessionId); }, }, { name: 'browser_back', description: 'Navigate back in browser history', category: 'browser', tags: ['navigation'], inputSchema: { type: 'object', properties: { session: { type: 'string', description: 'Session ID' }, }, }, handler: async (input) => { const { session } = input; return execBrowserCommand(['back'], session); }, }, { name: 'browser_forward', description: 'Navigate forward in browser history', category: 'browser', tags: ['navigation'], inputSchema: { type: 'object', properties: { session: { type: 'string', description: 'Session ID' }, }, }, handler: async (input) => { const { session } = input; return execBrowserCommand(['forward'], session); }, }, { name: 'browser_reload', description: 'Reload the current page', category: 'browser', tags: ['navigation'], inputSchema: { type: 'object', properties: { session: { type: 'string', description: 'Session ID' }, }, }, handler: async (input) => { const { session } = input; return execBrowserCommand(['reload'], session); }, }, { name: 'browser_close', description: 'Close the browser session', category: 'browser', tags: ['navigation'], inputSchema: { type: 'object', properties: { session: { type: 'string', description: 'Session ID' }, }, }, handler: async (input) => { const { session } = input; const sessionId = session || 'default'; browserSessions.delete(sessionId); return execBrowserCommand(['close'], sessionId); }, }, // ========================================================================== // Snapshot Tools (AI-Optimized) // ========================================================================== { name: 'browser_snapshot', description: 'Get AI-optimized accessibility tree snapshot with element refs (@e1, @e2, etc.)', category: 'browser', tags: ['snapshot', 'ai'], inputSchema: { type: 'object', properties: { session: { type: 'string', description: 'Session ID' }, interactive: { type: 'boolean', description: 'Only interactive elements (-i flag)' }, compact: { type: 'boolean', description: 'Remove empty structural elements (-c flag)' }, depth: { type: 'number', description: 'Limit tree depth (-d flag)' }, selector: { type: 'string', description: 'Scope to CSS selector (-s flag)' }, }, }, handler: async (input) => { const { session, interactive, compact, depth, selector } = input; const args = ['snapshot']; if (interactive) args.push('-i'); if (compact) args.push('-c'); if (depth) args.push('-d', String(depth)); if (selector) args.push('-s', selector); return execBrowserCommand(args, session); }, }, { name: 'browser_screenshot', description: 'Capture screenshot of the page', category: 'browser', tags: ['snapshot', 'screenshot'], inputSchema: { type: 'object', properties: { session: { type: 'string', description: 'Session ID' }, path: { type: 'string', description: 'Save path (returns base64 if not specified)' }, fullPage: { type: 'boolean', description: 'Capture full page' }, }, }, handler: async (input) => { const { session, path, fullPage } = input; const args = ['screenshot']; if (path) args.push(path); if (fullPage) args.push('--full'); return execBrowserCommand(args, session); }, }, // ========================================================================== // Interaction Tools // ========================================================================== { name: 'browser_click', description: 'Click an element using ref (@e1) or CSS selector', category: 'browser', tags: ['interaction'], inputSchema: { type: 'object', properties: { target: { type: 'string', description: 'Element ref (@e1) or CSS selector' }, session: { type: 'string', description: 'Session ID' }, button: { type: 'string', enum: ['left', 'right', 'middle'], description: 'Mouse button' }, count: { type: 'number', description: 'Click count (2 for double-click)' }, }, required: ['target'], }, handler: async (input) => { const { target, session, button, count } = input; const args = ['click', target]; if (button) args.push('--button', button); if (count) args.push('--count', String(count)); return execBrowserCommand(args, session); }, }, { name: 'browser_fill', description: 'Clear and fill an input element', category: 'browser', tags: ['interaction', 'form'], inputSchema: { type: 'object', properties: { target: { type: 'string', description: 'Element ref (@e1) or CSS selector' }, value: { type: 'string', description: 'Value to fill' }, session: { type: 'string', description: 'Session ID' }, }, required: ['target', 'value'], }, handler: async (input) => { const { target, value, session } = input; return execBrowserCommand(['fill', target, value], session); }, }, { name: 'browser_type', description: 'Type text with key events (for autocomplete, etc.)', category: 'browser', tags: ['interaction', 'form'], inputSchema: { type: 'object', properties: { target: { type: 'string', description: 'Element ref or CSS selector' }, text: { type: 'string', description: 'Text to type' }, session: { type: 'string', description: 'Session ID' }, delay: { type: 'number', description: 'Delay between keystrokes (ms)' }, }, required: ['target', 'text'], }, handler: async (input) => { const { target, text, session, delay } = input; const args = ['type', target, text]; if (delay) args.push('--delay', String(delay)); return execBrowserCommand(args, session); }, }, { name: 'browser_press', description: 'Press a keyboard key', category: 'browser', tags: ['interaction'], inputSchema: { type: 'object', properties: { key: { type: 'string', description: 'Key to press (Enter, Tab, Escape, etc.)' }, session: { type: 'string', description: 'Session ID' }, }, required: ['key'], }, handler: async (input) => { const { key, session } = input; return execBrowserCommand(['press', key], session); }, }, { name: 'browser_hover', description: 'Hover over an element', category: 'browser', tags: ['interaction'], inputSchema: { type: 'object', properties: { target: { type: 'string', description: 'Element ref or CSS selector' }, session: { type: 'string', description: 'Session ID' }, }, required: ['target'], }, handler: async (input) => { const { target, session } = input; return execBrowserCommand(['hover', target], session); }, }, { name: 'browser_select', description: 'Select an option from a dropdown', category: 'browser', tags: ['interaction', 'form'], inputSchema: { type: 'object', properties: { target: { type: 'string', description: 'Select element ref or CSS selector' }, value: { type: 'string', description: 'Option value to select' }, session: { type: 'string', description: 'Session ID' }, }, required: ['target', 'value'], }, handler: async (input) => { const { target, value, session } = input; return execBrowserCommand(['select', target, value], session); }, }, { name: 'browser_check', description: 'Check a checkbox', category: 'browser', tags: ['interaction', 'form'], inputSchema: { type: 'object', properties: { target: { type: 'string', description: 'Checkbox ref or CSS selector' }, session: { type: 'string', description: 'Session ID' }, }, required: ['target'], }, handler: async (input) => { const { target, session } = input; return execBrowserCommand(['check', target], session); }, }, { name: 'browser_uncheck', description: 'Uncheck a checkbox', category: 'browser', tags: ['interaction', 'form'], inputSchema: { type: 'object', properties: { target: { type: 'string', description: 'Checkbox ref or CSS selector' }, session: { type: 'string', description: 'Session ID' }, }, required: ['target'], }, handler: async (input) => { const { target, session } = input; return execBrowserCommand(['uncheck', target], session); }, }, { name: 'browser_scroll', description: 'Scroll the page', category: 'browser', tags: ['interaction'], inputSchema: { type: 'object', properties: { direction: { type: 'string', enum: ['up', 'down', 'left', 'right'], description: 'Scroll direction' }, amount: { type: 'number', description: 'Scroll amount in pixels' }, session: { type: 'string', description: 'Session ID' }, }, required: ['direction'], }, handler: async (input) => { const { direction, amount, session } = input; const args = ['scroll', direction]; if (amount) args.push(String(amount)); return execBrowserCommand(args, session); }, }, // ========================================================================== // Information Retrieval Tools // ========================================================================== { name: 'browser_get-text', description: 'Get text content of an element', category: 'browser', tags: ['info'], inputSchema: { type: 'object', properties: { target: { type: 'string', description: 'Element ref or CSS selector' }, session: { type: 'string', description: 'Session ID' }, }, required: ['target'], }, handler: async (input) => { const { target, session } = input; return execBrowserCommand(['get', 'text', target], session); }, }, { name: 'browser_get-value', description: 'Get value of an input element', category: 'browser', tags: ['info', 'form'], inputSchema: { type: 'object', properties: { target: { type: 'string', description: 'Input element ref or CSS selector' }, session: { type: 'string', description: 'Session ID' }, }, required: ['target'], }, handler: async (input) => { const { target, session } = input; return execBrowserCommand(['get', 'value', target], session); }, }, { name: 'browser_get-title', description: 'Get the page title', category: 'browser', tags: ['info'], inputSchema: { type: 'object', properties: { session: { type: 'string', description: 'Session ID' }, }, }, handler: async (input) => { const { session } = input; return execBrowserCommand(['get', 'title'], session); }, }, { name: 'browser_get-url', description: 'Get the current URL', category: 'browser', tags: ['info'], inputSchema: { type: 'object', properties: { session: { type: 'string', description: 'Session ID' }, }, }, handler: async (input) => { const { session } = input; return execBrowserCommand(['get', 'url'], session); }, }, // ========================================================================== // Wait Tools // ========================================================================== { name: 'browser_wait', description: 'Wait for a condition', category: 'browser', tags: ['wait'], inputSchema: { type: 'object', properties: { selector: { type: 'string', description: 'CSS selector to wait for' }, text: { type: 'string', description: 'Text to wait for' }, url: { type: 'string', description: 'URL pattern to wait for' }, timeout: { type: 'number', description: 'Wait timeout in ms' }, session: { type: 'string', description: 'Session ID' }, }, }, handler: async (input) => { const { selector, text, url, timeout, session } = input; const args = ['wait']; if (selector) args.push(selector); if (text) args.push('--text', text); if (url) args.push('--url', url); if (timeout) args.push(String(timeout)); return execBrowserCommand(args, session); }, }, // ========================================================================== // JavaScript Execution // ========================================================================== { name: 'browser_eval', description: 'Execute JavaScript in page context', category: 'browser', tags: ['eval', 'js'], inputSchema: { type: 'object', properties: { script: { type: 'string', description: 'JavaScript code to execute' }, session: { type: 'string', description: 'Session ID' }, }, required: ['script'], }, handler: async (input) => { const { script, session } = input; return execBrowserCommand(['eval', script], session); }, }, // ========================================================================== // Session Management // ========================================================================== { name: 'browser_session-list', description: 'List active browser sessions', category: 'browser', tags: ['session'], inputSchema: { type: 'object', properties: {}, }, handler: async () => { const sessions = Array.from(browserSessions.values()); return { content: [{ type: 'text', text: JSON.stringify({ success: true, sessions, count: sessions.length, }, null, 2), }], }; }, }, ]; export default browserTools; //# sourceMappingURL=browser-tools.js.map