#!/usr/bin/env node
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
import { initBrowser, closeBrowser } from './browser.js';
import { tools } from './tools.js';
import {
handleNavigate,
handleGetDom,
handleGetElement,
handleExecuteJs,
handleScreenshot,
handleGetConsoleLogs,
handleGetNetworkActivity,
handleGetPageSource,
handleQuerySelectorAll,
handleGetPageInfo,
handleClickElement,
handleTypeText,
handleGetLocalStorage,
handleGetCookies,
handleEvaluateXPath,
handleOpenBrowser,
handleLogin,
handleGetBrowserStatus,
handleCloseBrowser,
} from './browserTools.js';
// Criar servidor MCP
const server = new Server(
{
name: 'mcp-browser-debugger',
version: '1.0.0',
},
{
capabilities: {
tools: {},
},
}
);
// Listar ferramentas disponíveis
server.setRequestHandler(ListToolsRequestSchema, async () => {
return { tools };
});
// Handler de execução de ferramentas
server.setRequestHandler(CallToolRequestSchema, async (request) => {
try {
const { name, arguments: args } = request.params;
// Despachar para o handler apropriado
switch (name) {
case 'get_browser_status':
return await handleGetBrowserStatus();
case 'close_browser':
return await handleCloseBrowser();
case 'open_browser':
// open_browser gerencia seu próprio initBrowser
return await handleOpenBrowser(args);
case 'login': // login precisa de página, mas open_browser já foi chamado antes
{
const currentPage = await initBrowser();
return await handleLogin(args, currentPage);
}
case 'navigate': {
const currentPage = await initBrowser();
return await handleNavigate(args, currentPage);
}
case 'get_dom': {
const currentPage = await initBrowser();
return await handleGetDom(args, currentPage);
}
case 'get_element': {
const currentPage = await initBrowser();
return await handleGetElement(args, currentPage);
}
case 'execute_js': {
const currentPage = await initBrowser();
return await handleExecuteJs(args, currentPage);
}
case 'screenshot': {
const currentPage = await initBrowser();
return await handleScreenshot(args, currentPage);
}
case 'get_console_logs':
return await handleGetConsoleLogs(args);
case 'get_network_activity':
return await handleGetNetworkActivity(args);
case 'get_page_source': {
const currentPage = await initBrowser();
return await handleGetPageSource(args, currentPage);
}
case 'query_selector_all': {
const currentPage = await initBrowser();
return await handleQuerySelectorAll(args, currentPage);
}
case 'get_page_info': {
const currentPage = await initBrowser();
return await handleGetPageInfo(currentPage);
}
case 'click_element': {
const currentPage = await initBrowser();
return await handleClickElement(args, currentPage);
}
case 'type_text': {
const currentPage = await initBrowser();
return await handleTypeText(args, currentPage);
}
case 'get_local_storage': {
const currentPage = await initBrowser();
return await handleGetLocalStorage(currentPage);
}
case 'get_cookies': {
const currentPage = await initBrowser();
return await handleGetCookies(currentPage);
}
case 'evaluate_xpath': {
const currentPage = await initBrowser();
return await handleEvaluateXPath(args, currentPage);
}
default:
return {
content: [
{
type: 'text',
text: JSON.stringify({ error: `Ferramenta desconhecida: ${name}` }),
},
],
};
}
} catch (error) {
const err = error as Error;
return {
content: [
{
type: 'text',
text: JSON.stringify(
{
error: err.message,
stack: err.stack,
},
null,
2
),
},
],
isError: true,
};
}
});
// Iniciar servidor
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error('MCP Browser Debugger Server iniciado!');
console.error('Ferramentas disponíveis: 19');
console.error('⚠️ IMPORTANTE: Sempre use get_browser_status antes de open_browser!');
console.error('Pronto para receber requisições via stdio');
}
main().catch((error) => {
console.error('Erro fatal:', error);
process.exit(1);
});
// Cleanup ao encerrar
process.on('SIGINT', async () => {
await closeBrowser();
process.exit(0);
});