levisnkyyy-browser-use-mcp
Version:
MCP server for Browser-Use API
279 lines (257 loc) • 8.29 kB
text/typescript
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);
});