UNPKG

levisnkyyy-browser-use-mcp

Version:

MCP server for Browser-Use API

279 lines (257 loc) 8.29 kB
#!/usr/bin/env node import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequestSchema, ListToolsRequestSchema, Tool, } from '@modelcontextprotocol/sdk/types.js'; import { BrowserUseClient, TaskRequest, ScanRequest, ScreenshotRequest } from './client.js'; import { tools } from './tools.js'; const API_URL = process.env.BROWSER_USE_API_URL || 'http://localhost:8000'; const API_KEY = process.env.BROWSER_USE_API_KEY; async function main() { const client = new BrowserUseClient(API_URL, API_KEY); const server = new Server( { name: 'browser-use-mcp', version: '0.1.0', }, { capabilities: { tools: {}, }, } ); // List available tools server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: tools as Tool[], }; }); // Handle tool calls server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; try { switch (name) { case 'browser_use_create_task': { if (!args || typeof args !== 'object' || !('task' in args) || !('project_folder' in args)) { throw new Error('task and project_folder parameters are required'); } const result = await client.createTask(args as unknown as TaskRequest); return { content: [ { type: 'text', text: JSON.stringify(result, null, 2), }, ], }; } case 'browser_use_create_task_sync': { if (!args || typeof args !== 'object' || !('task' in args) || !('project_folder' in args)) { throw new Error('task and project_folder parameters are required'); } const result = await client.createTaskSync(args as unknown as TaskRequest); return { content: [ { type: 'text', text: JSON.stringify(result, null, 2), }, ], }; } case 'browser_use_get_task': { if (!args || typeof args !== 'object' || !('task_id' in args)) { throw new Error('task_id is required'); } const result = await client.getTask(args.task_id as string); return { content: [ { type: 'text', text: JSON.stringify(result, null, 2), }, ], }; } case 'browser_use_list_tasks': { const result = await client.listTasks(); return { content: [ { type: 'text', text: JSON.stringify(result, null, 2), }, ], }; } case 'browser_use_cancel_task': { if (!args || typeof args !== 'object' || !('task_id' in args)) { throw new Error('task_id is required'); } const taskId = args.task_id as string; await client.cancelTask(taskId); return { content: [ { type: 'text', text: `Task ${taskId} cancelled successfully`, }, ], }; } case 'browser_use_pause_task': { if (!args || typeof args !== 'object' || !('task_id' in args)) { throw new Error('task_id is required'); } const taskId = args.task_id as string; await client.pauseTask(taskId); return { content: [ { type: 'text', text: `Task ${taskId} paused successfully`, }, ], }; } case 'browser_use_get_task_history': { if (!args || typeof args !== 'object' || !('task_id' in args)) { throw new Error('task_id is required'); } const result = await client.getTaskHistory(args.task_id as string); return { content: [ { type: 'text', text: JSON.stringify(result, null, 2), }, ], }; } case 'browser_use_get_screenshot': { if (!args || typeof args !== 'object' || !('task_id' in args) || !('project_folder' in args)) { throw new Error('task_id and project_folder are required'); } const screenshotParams: ScreenshotRequest = { project_folder: args.project_folder as string, filename: args.filename as string | undefined, }; const result = await client.getScreenshot(args.task_id as string, screenshotParams); return { content: [ { type: 'text', text: JSON.stringify(result, null, 2), }, ], }; } case 'browser_use_create_session': { const result = await client.createBrowserSession(args || {}); return { content: [ { type: 'text', text: JSON.stringify(result, null, 2), }, ], }; } case 'browser_use_close_session': { if (!args || typeof args !== 'object' || !('session_id' in args)) { throw new Error('session_id is required'); } const sessionId = args.session_id as string; await client.closeBrowserSession(sessionId); return { content: [ { type: 'text', text: `Browser session ${sessionId} closed successfully`, }, ], }; } case 'browser_use_stream_task': { if (!args || typeof args !== 'object' || !('task_id' in args)) { throw new Error('task_id is required'); } const messages: string[] = []; await client.streamTask(args.task_id as string, (message) => { messages.push(JSON.stringify(message)); }); return { content: [ { type: 'text', text: messages.join('\n'), }, ], }; } case 'browser_use_health': { const result = await client.checkHealth(); return { content: [ { type: 'text', text: JSON.stringify(result, null, 2), }, ], }; } case 'browser_use_scan': { if (!args || typeof args !== 'object' || !('url' in args) || !('filename' in args) || !('project_folder' in args)) { throw new Error('url, filename, and project_folder parameters are required'); } const result = await client.scanUrl(args as unknown as ScanRequest); return { content: [ { type: 'text', text: JSON.stringify(result, null, 2), }, ], }; } case 'browser_use_get_snapshot': { if (!args || typeof args !== 'object' || !('task_id' in args)) { throw new Error('task_id is required'); } const result = await client.getSnapshot(args.task_id as string); return { content: [ { type: 'image', mimeType: 'image/png', data: result, }, ], }; } default: throw new Error(`Unknown tool: ${name}`); } } catch (error) { return { content: [ { type: 'text', text: `Error: ${error instanceof Error ? error.message : String(error)}`, }, ], isError: true, }; } }); const transport = new StdioServerTransport(); await server.connect(transport); console.error(`Browser-Use MCP Server running (API: ${API_URL})`); } main().catch((error) => { console.error('Fatal error:', error); process.exit(1); });