UNPKG

n8n-nodes-playwright-mcp

Version:

Complete n8n Playwright node with all Microsoft Playwright MCP tools and AI assistant support for advanced browser automation

671 lines 23.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AI_INTEGRATION = exports.MCP_CAPABILITIES = exports.MCP_TOOLS = void 0; exports.getEnabledMCPTools = getEnabledMCPTools; exports.getOperationByMCPTool = getOperationByMCPTool; exports.convertToMCPParameters = convertToMCPParameters; exports.validateMCPParameters = validateMCPParameters; exports.MCP_TOOLS = { navigate: { name: 'browser_navigate', description: 'Navigate to a URL', inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'The URL to navigate to', format: 'uri' } }, required: ['url'] } }, navigateBack: { name: 'browser_navigate_back', description: 'Go back to the previous page', inputSchema: { type: 'object', properties: {} } }, navigateForward: { name: 'browser_navigate_forward', description: 'Go forward to the next page', inputSchema: { type: 'object', properties: {} } }, snapshot: { name: 'browser_snapshot', description: 'Capture accessibility snapshot of the current page, this is better than screenshot', inputSchema: { type: 'object', properties: {} } }, click: { name: 'browser_click', description: 'Perform click on a web page', inputSchema: { type: 'object', properties: { element: { type: 'string', description: 'Human-readable element description used to obtain permission to interact with the element' }, ref: { type: 'string', description: 'Exact target element reference from the page snapshot' }, doubleClick: { type: 'boolean', description: 'Whether to perform a double click instead of a single click' }, button: { type: 'string', enum: ['left', 'right', 'middle'], description: 'Button to click, defaults to left' } }, required: ['element', 'ref'] } }, hover: { name: 'browser_hover', description: 'Hover over element on page', inputSchema: { type: 'object', properties: { element: { type: 'string', description: 'Human-readable element description used to obtain permission to interact with the element' }, ref: { type: 'string', description: 'Exact target element reference from the page snapshot' } }, required: ['element', 'ref'] } }, drag: { name: 'browser_drag', description: 'Perform drag and drop between two elements', inputSchema: { type: 'object', properties: { startElement: { type: 'string', description: 'Human-readable source element description used to obtain the permission to interact with the element' }, startRef: { type: 'string', description: 'Exact source element reference from the page snapshot' }, endElement: { type: 'string', description: 'Human-readable target element description used to obtain the permission to interact with the element' }, endRef: { type: 'string', description: 'Exact target element reference from the page snapshot' } }, required: ['startElement', 'startRef', 'endElement', 'endRef'] } }, selectOption: { name: 'browser_select_option', description: 'Select an option in a dropdown', inputSchema: { type: 'object', properties: { element: { type: 'string', description: 'Human-readable element description used to obtain permission to interact with the element' }, ref: { type: 'string', description: 'Exact target element reference from the page snapshot' }, values: { type: 'array', items: { type: 'string' }, description: 'Array of values to select in the dropdown. This can be a single value or multiple values.' } }, required: ['element', 'ref', 'values'] } }, type: { name: 'browser_type', description: 'Type text into editable element', inputSchema: { type: 'object', properties: { element: { type: 'string', description: 'Human-readable element description used to obtain permission to interact with the element' }, ref: { type: 'string', description: 'Exact target element reference from the page snapshot' }, text: { type: 'string', description: 'Text to type into the element' }, submit: { type: 'boolean', description: 'Whether to submit entered text (press Enter after)' }, slowly: { type: 'boolean', description: 'Whether to type one character at a time. Useful for triggering key handlers in the page. By default entire text is filled in at once.' } }, required: ['element', 'ref', 'text'] } }, pressKey: { name: 'browser_press_key', description: 'Press a key on the keyboard', inputSchema: { type: 'object', properties: { key: { type: 'string', description: 'Name of the key to press or a character to generate, such as `ArrowLeft` or `a`' } }, required: ['key'] } }, evaluate: { name: 'browser_evaluate', description: 'Evaluate JavaScript expression on page or element', inputSchema: { type: 'object', properties: { function: { type: 'string', description: '() => { /* code */ } or (element) => { /* code */ } when element is provided' }, element: { type: 'string', description: 'Human-readable element description used to obtain permission to interact with the element' }, ref: { type: 'string', description: 'Exact target element reference from the page snapshot' } }, required: ['function'] } }, fileUpload: { name: 'browser_file_upload', description: 'Upload one or multiple files', inputSchema: { type: 'object', properties: { paths: { type: 'array', items: { type: 'string' }, description: 'The absolute paths to the files to upload. Can be a single file or multiple files.' } }, required: ['paths'] } }, handleDialog: { name: 'browser_handle_dialog', description: 'Handle a dialog', inputSchema: { type: 'object', properties: { accept: { type: 'boolean', description: 'Whether to accept the dialog.' }, promptText: { type: 'string', description: 'The text of the prompt in case of a prompt dialog.' } }, required: ['accept'] } }, close: { name: 'browser_close', description: 'Close the page', inputSchema: { type: 'object', properties: {} } }, resize: { name: 'browser_resize', description: 'Resize the browser window', inputSchema: { type: 'object', properties: { width: { type: 'number', description: 'Width of the browser window' }, height: { type: 'number', description: 'Height of the browser window' } }, required: ['width', 'height'] } }, consoleMessages: { name: 'browser_console_messages', description: 'Returns all console messages', inputSchema: { type: 'object', properties: {} } }, networkRequests: { name: 'browser_network_requests', description: 'Returns all network requests since loading the page', inputSchema: { type: 'object', properties: {} } }, takeScreenshot: { name: 'browser_take_screenshot', description: 'Take a screenshot of the current page. You can\'t perform actions based on the screenshot, use browser_snapshot for actions.', inputSchema: { type: 'object', properties: { type: { type: 'string', enum: ['png', 'jpeg'], description: 'Image format for the screenshot. Default is png.' }, filename: { type: 'string', description: 'File name to save the screenshot to. Defaults to `page-{timestamp}.{png|jpeg}` if not specified.' }, element: { type: 'string', description: 'Human-readable element description used to obtain permission to screenshot the element. If not provided, the screenshot will be taken of viewport. If element is provided, ref must be provided too.' }, ref: { type: 'string', description: 'Exact target element reference from the page snapshot. If not provided, the screenshot will be taken of viewport. If ref is provided, element must be provided too.' }, fullPage: { type: 'boolean', description: 'When true, takes a screenshot of the full scrollable page, instead of the currently visible viewport. Cannot be used with element screenshots.' } } } }, waitFor: { name: 'browser_wait_for', description: 'Wait for text to appear or disappear or a specified time to pass', inputSchema: { type: 'object', properties: { time: { type: 'number', description: 'The time to wait in seconds' }, text: { type: 'string', description: 'The text to wait for' }, textGone: { type: 'string', description: 'The text to wait for to disappear' } } } }, tabList: { name: 'browser_tab_list', description: 'List browser tabs', inputSchema: { type: 'object', properties: {} } }, tabSelect: { name: 'browser_tab_select', description: 'Select a tab by index', inputSchema: { type: 'object', properties: { index: { type: 'number', description: 'The index of the tab to select' } }, required: ['index'] } }, tabNew: { name: 'browser_tab_new', description: 'Open a new tab', inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'The URL to navigate to in the new tab. If not provided, the new tab will be blank.' } } } }, tabClose: { name: 'browser_tab_close', description: 'Close a tab', inputSchema: { type: 'object', properties: { index: { type: 'number', description: 'The index of the tab to close. Closes current tab if not provided.' } } } }, install: { name: 'browser_install', description: 'Install the browser specified in the config. Call this if you get an error about the browser not being installed.', inputSchema: { type: 'object', properties: {} } }, mouseMoveXY: { name: 'browser_mouse_move_xy', description: 'Move mouse to a given position', inputSchema: { type: 'object', properties: { element: { type: 'string', description: 'Human-readable element description used to obtain permission to interact with the element' }, x: { type: 'number', description: 'X coordinate' }, y: { type: 'number', description: 'Y coordinate' } }, required: ['element', 'x', 'y'] } }, mouseClickXY: { name: 'browser_mouse_click_xy', description: 'Click left mouse button at a given position', inputSchema: { type: 'object', properties: { element: { type: 'string', description: 'Human-readable element description used to obtain permission to interact with the element' }, x: { type: 'number', description: 'X coordinate' }, y: { type: 'number', description: 'Y coordinate' } }, required: ['element', 'x', 'y'] } }, mouseDragXY: { name: 'browser_mouse_drag_xy', description: 'Drag left mouse button to a given position', inputSchema: { type: 'object', properties: { element: { type: 'string', description: 'Human-readable element description used to obtain permission to interact with the element' }, startX: { type: 'number', description: 'Start X coordinate' }, startY: { type: 'number', description: 'Start Y coordinate' }, endX: { type: 'number', description: 'End X coordinate' }, endY: { type: 'number', description: 'End Y coordinate' } }, required: ['element', 'startX', 'startY', 'endX', 'endY'] } }, savePDF: { name: 'browser_pdf_save', description: 'Save page as PDF', inputSchema: { type: 'object', properties: { filename: { type: 'string', description: 'File name to save the pdf to. Defaults to `page-{timestamp}.pdf` if not specified.' } } } }, getText: { name: 'browser_get_text_legacy', description: 'Get text from an element (legacy operation)', inputSchema: { type: 'object', properties: { selector: { type: 'string', description: 'CSS selector for the element' } }, required: ['selector'] } }, fillForm: { name: 'browser_fill_form_legacy', description: 'Fill a form field (legacy operation)', inputSchema: { type: 'object', properties: { selector: { type: 'string', description: 'CSS selector for the form field' }, value: { type: 'string', description: 'Value to fill in the form field' } }, required: ['selector', 'value'] } }, clickElement: { name: 'browser_click_element_legacy', description: 'Click on an element (legacy operation)', inputSchema: { type: 'object', properties: { selector: { type: 'string', description: 'CSS selector for the element' } }, required: ['selector'] } } }; exports.MCP_CAPABILITIES = { 'core': { name: 'core', description: 'Core browser automation features', tools: [ 'browser_navigate', 'browser_navigate_back', 'browser_navigate_forward', 'browser_snapshot', 'browser_click', 'browser_hover', 'browser_drag', 'browser_select_option', 'browser_type', 'browser_press_key', 'browser_evaluate', 'browser_file_upload', 'browser_handle_dialog', 'browser_close', 'browser_resize', 'browser_console_messages', 'browser_network_requests', 'browser_take_screenshot', 'browser_wait_for' ], enabled: true }, 'core-tabs': { name: 'core-tabs', description: 'Tab management functionality', tools: [ 'browser_tab_list', 'browser_tab_select', 'browser_tab_new', 'browser_tab_close' ], enabled: true }, 'core-install': { name: 'core-install', description: 'Browser installation capabilities', tools: [ 'browser_install' ], enabled: true }, 'vision': { name: 'vision', description: 'Coordinate-based interactions (requires vision capability)', tools: [ 'browser_mouse_move_xy', 'browser_mouse_click_xy', 'browser_mouse_drag_xy' ], enabled: false }, 'pdf': { name: 'pdf', description: 'PDF generation and manipulation', tools: [ 'browser_pdf_save' ], enabled: false } }; function getEnabledMCPTools(capabilities = ['core', 'core-tabs', 'core-install']) { const enabledTools = []; capabilities.forEach(cap => { var _a; if ((_a = exports.MCP_CAPABILITIES[cap]) === null || _a === void 0 ? void 0 : _a.enabled) { enabledTools.push(...exports.MCP_CAPABILITIES[cap].tools); } }); return Object.entries(exports.MCP_TOOLS) .filter(([_, tool]) => enabledTools.includes(tool.name)) .map(([_, tool]) => tool); } function getOperationByMCPTool(toolName) { var _a; return (_a = Object.entries(exports.MCP_TOOLS).find(([_, tool]) => tool.name === toolName)) === null || _a === void 0 ? void 0 : _a[0]; } function convertToMCPParameters(operation, n8nParams) { const mcpTool = exports.MCP_TOOLS[operation]; if (!mcpTool) return n8nParams; const mcpParams = {}; const schema = mcpTool.inputSchema; Object.keys(schema.properties).forEach(key => { if (n8nParams[key] !== undefined) { mcpParams[key] = n8nParams[key]; } }); return mcpParams; } function validateMCPParameters(operation, params) { const mcpTool = exports.MCP_TOOLS[operation]; if (!mcpTool) { return { valid: false, errors: [`Unknown operation: ${operation}`] }; } const errors = []; const schema = mcpTool.inputSchema; if (schema.required) { schema.required.forEach(required => { if (params[required] === undefined) { errors.push(`Missing required parameter: ${required}`); } }); } Object.entries(schema.properties).forEach(([key, propSchema]) => { if (params[key] !== undefined) { const value = params[key]; const expectedType = propSchema.type; if (expectedType === 'string' && typeof value !== 'string') { errors.push(`Parameter ${key} must be a string`); } else if (expectedType === 'number' && typeof value !== 'number') { errors.push(`Parameter ${key} must be a number`); } else if (expectedType === 'boolean' && typeof value !== 'boolean') { errors.push(`Parameter ${key} must be a boolean`); } else if (expectedType === 'array' && !Array.isArray(value)) { errors.push(`Parameter ${key} must be an array`); } } }); return { valid: errors.length === 0, errors }; } exports.AI_INTEGRATION = { getWorkflowSuggestions(intent) { const intentLower = intent.toLowerCase(); if (intentLower.includes('navigate') || intentLower.includes('go to')) { return ['navigate', 'snapshot']; } if (intentLower.includes('click') || intentLower.includes('button')) { return ['snapshot', 'click']; } if (intentLower.includes('type') || intentLower.includes('fill') || intentLower.includes('form')) { return ['snapshot', 'type']; } if (intentLower.includes('screenshot') || intentLower.includes('capture')) { return ['takeScreenshot']; } if (intentLower.includes('pdf') || intentLower.includes('save')) { return ['savePDF']; } if (intentLower.includes('tab')) { return ['tabList', 'tabNew', 'tabSelect']; } return ['navigate', 'snapshot', 'click']; }, getOperationDescription(operation) { const tool = exports.MCP_TOOLS[operation]; return tool ? tool.description : `Perform ${operation} operation`; }, getParameterHints(operation) { const tool = exports.MCP_TOOLS[operation]; if (!tool) return {}; const hints = {}; Object.entries(tool.inputSchema.properties).forEach(([key, schema]) => { hints[key] = schema.description || `${key} parameter`; }); return hints; } }; //# sourceMappingURL=mcp-config.js.map