feat: MCP Browser - servidor MCP para automação de navegador com Playwright
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
const { Server } = require('@modelcontextprotocol/sdk/server/index.js');
|
||||
const { StdioServerTransport } = require('@modelcontextprotocol/sdk/server/stdio.js');
|
||||
|
||||
const {
|
||||
ListToolsRequestSchema,
|
||||
CallToolRequestSchema
|
||||
} = require('@modelcontextprotocol/sdk/types.js');
|
||||
|
||||
// TOOLS
|
||||
const openUrl = require('./tools/openUrl');
|
||||
const click = require('./tools/click');
|
||||
const type = require('./tools/type');
|
||||
const screenshot = require('./tools/screenshot');
|
||||
const getText = require('./tools/getText');
|
||||
const getLinks = require('./tools/getLinks');
|
||||
const waitForSelector = require('./tools/waitForSelector');
|
||||
const extractElements = require('./tools/extractElements');
|
||||
const smartClick = require('./tools/smartClick');
|
||||
const smartType = require('./tools/smartType');
|
||||
const getButtons = require('./tools/getButtons');
|
||||
const smartWaitNavigation = require('./tools/smartWaitNavigation');
|
||||
const getForms = require('./tools/getForms');
|
||||
const fillFormAuto = require('./tools/fillFormAuto');
|
||||
const agentFlow = require('./tools/agentFlow');
|
||||
const agentFlowV2 = require('./tools/agentFlowV2');
|
||||
const closeBrowser = require('./tools/closeBrowser');
|
||||
|
||||
// SERVER MCP
|
||||
const server = new Server(
|
||||
{
|
||||
name: "browser",
|
||||
version: "2.0.0"
|
||||
},
|
||||
{
|
||||
capabilities: {
|
||||
tools: {}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// LISTAR TOOLS
|
||||
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
||||
return {
|
||||
tools: [
|
||||
{ name: "open_url", description: "Abre uma URL", inputSchema: { type: "object", properties: { url: { type: "string" } }, required: ["url"] } },
|
||||
{ name: "click", description: "Clica por seletor", inputSchema: { type: "object", properties: { selector: { type: "string" } }, required: ["selector"] } },
|
||||
{ name: "type", description: "Digita texto", inputSchema: { type: "object", properties: { selector: { type: "string" }, text: { type: "string" } }, required: ["selector", "text"] } },
|
||||
{ name: "screenshot", description: "Screenshot", inputSchema: { type: "object", properties: { fullPage: { type: "boolean" } } } },
|
||||
{ name: "get_text", description: "Extrai texto", inputSchema: { type: "object", properties: { selector: { type: "string" } } } },
|
||||
{ name: "get_links", description: "Lista links", inputSchema: { type: "object", properties: { selector: { type: "string" } } } },
|
||||
{ name: "wait_for_selector", description: "Espera elemento", inputSchema: { type: "object", properties: { selector: { type: "string" }, timeout: { type: "number" } }, required: ["selector"] } },
|
||||
{ name: "extract_elements", description: "Extrai elementos", inputSchema: { type: "object", properties: { selector: { type: "string" }, attributes: { type: "array", items: { type: "string" } } }, required: ["selector"] } },
|
||||
{ name: "smart_click", description: "Clica por texto visível", inputSchema: { type: "object", properties: { text: { type: "string" } }, required: ["text"] } },
|
||||
{ name: "smart_type", description: "Digita por label/placeholder", inputSchema: { type: "object", properties: { label: { type: "string" }, text: { type: "string" } }, required: ["label", "text"] } },
|
||||
{ name: "get_buttons", description: "Lista botões disponíveis", inputSchema: { type: "object", properties: {} } },
|
||||
{ name: "smart_wait_navigation", description: "Espera mudança de página", inputSchema: { type: "object", properties: { timeout: { type: "number" } } } },
|
||||
{ name: "get_forms", description: "Lista formulários da página", inputSchema: { type: "object", properties: {} } },
|
||||
{ name: "fill_form_auto", description: "Preenche formulário automaticamente", inputSchema: { type: "object", properties: { data: { type: "object" } }, required: ["data"] } },
|
||||
{ name: "agent_flow", description: "Fluxo automático simples", inputSchema: { type: "object", properties: { goal: { type: "string" }, data: { type: "object" } }, required: ["goal"] } },
|
||||
{ name: "agent_flow_v2", description: "Fluxo automático avançado com retry e fallback", inputSchema: { type: "object", properties: { goal: { type: "string" }, data: { type: "object" }, retries: { type: "number" } }, required: ["goal"] } },
|
||||
{ name: "close_browser", description: "Fecha o navegador", inputSchema: { type: "object", properties: {} } }
|
||||
]
|
||||
};
|
||||
});
|
||||
|
||||
// EXECUTAR TOOL
|
||||
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
||||
const { name, arguments: args } = request.params;
|
||||
|
||||
const tools = {
|
||||
open_url: openUrl,
|
||||
click,
|
||||
type,
|
||||
screenshot,
|
||||
get_text: getText,
|
||||
get_links: getLinks,
|
||||
wait_for_selector: waitForSelector,
|
||||
extract_elements: extractElements,
|
||||
smart_click: smartClick,
|
||||
smart_type: smartType,
|
||||
get_buttons: getButtons,
|
||||
smart_wait_navigation: smartWaitNavigation,
|
||||
get_forms: getForms,
|
||||
fill_form_auto: fillFormAuto,
|
||||
agent_flow: agentFlow,
|
||||
agent_flow_v2: agentFlowV2,
|
||||
close_browser: closeBrowser
|
||||
};
|
||||
|
||||
if (!tools[name]) {
|
||||
throw new Error("Tool não encontrada");
|
||||
}
|
||||
|
||||
const result = await tools[name](args || {});
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: JSON.stringify(result)
|
||||
}
|
||||
]
|
||||
};
|
||||
});
|
||||
|
||||
// START SERVER
|
||||
const transport = new StdioServerTransport();
|
||||
server.connect(transport);
|
||||
Reference in New Issue
Block a user