take_screenshot
Capture a screenshot of any Electron application window and return base64 image data. Optionally save the image to a specified path for further AI analysis or processing.
Instructions
Take a screenshot of any running Electron application window. Returns base64 image data for AI analysis. No files created unless outputPath is specified.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| outputPath | No | Path to save the screenshot (optional, defaults to temp directory) | |
| windowTitle | No | Specific window title to screenshot (optional) |
Implementation Reference
- src/screenshot.ts:150-274 (handler)Core handler function that connects to running Electron apps via Chrome DevTools Protocol (CDP), takes a screenshot of the target page, encrypts the image data, optionally saves to file, and returns base64-encoded image for AI analysis.export async function takeScreenshot( outputPath?: string, windowTitle?: string, ): Promise<{ filePath?: string; base64: string; data: string; error?: string; }> { // Validate output path for security if (outputPath && !validateScreenshotPath(outputPath)) { throw new Error( `Invalid output path: ${outputPath}. Path appears to target a restricted system location.`, ); } // Inform user about screenshot logger.info('📸 Taking screenshot of Electron application', { outputPath, windowTitle, timestamp: new Date().toISOString(), }); try { // Find running Electron applications const apps = await scanForElectronApps(); if (apps.length === 0) { throw new Error('No running Electron applications found with remote debugging enabled'); } // Use the first app found (or find by title if specified) let targetApp = apps[0]; if (windowTitle) { const namedApp = apps.find((app) => app.targets.some((target) => target.title?.toLowerCase().includes(windowTitle.toLowerCase()), ), ); if (namedApp) { targetApp = namedApp; } } // Connect to the Electron app's debugging port const browser = await chromium.connectOverCDP(`http://localhost:${targetApp.port}`); const contexts = browser.contexts(); if (contexts.length === 0) { throw new Error( 'No browser contexts found - make sure Electron app is running with remote debugging enabled', ); } const context = contexts[0]; const pages = context.pages(); if (pages.length === 0) { throw new Error('No pages found in the browser context'); } // Find the main application page (skip DevTools pages) let targetPage = pages[0]; for (const page of pages) { const url = page.url(); const title = await page.title().catch(() => ''); // Skip DevTools and about:blank pages if ( !url.includes('devtools://') && !url.includes('about:blank') && title && !title.includes('DevTools') ) { // If windowTitle is specified, try to match it if (windowTitle && title.toLowerCase().includes(windowTitle.toLowerCase())) { targetPage = page; break; } else if (!windowTitle) { targetPage = page; break; } } } logger.info(`Taking screenshot of page: ${targetPage.url()} (${await targetPage.title()})`); // Take screenshot as buffer (in memory) const screenshotBuffer = await targetPage.screenshot({ type: 'png', fullPage: false, }); await browser.close(); // Encrypt screenshot data for security const encryptedScreenshot = encryptScreenshotData(screenshotBuffer); // Convert buffer to base64 for transmission const base64Data = screenshotBuffer.toString('base64'); logger.info( `Screenshot captured and encrypted successfully (${screenshotBuffer.length} bytes)`, ); // If outputPath is provided, save encrypted data to file if (outputPath) { await fs.writeFile(outputPath + '.encrypted', JSON.stringify(encryptedScreenshot)); // Also save unencrypted for compatibility (in production, consider removing this) await fs.writeFile(outputPath, screenshotBuffer); return { filePath: outputPath, base64: base64Data, data: `Screenshot saved to: ${outputPath} (encrypted backup: ${outputPath}.encrypted) and returned as base64 data`, }; } else { return { base64: base64Data, data: `Screenshot captured as base64 data (${screenshotBuffer.length} bytes) - no file saved`, }; } } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); throw new Error( `Screenshot failed: ${errorMessage}. Make sure the Electron app is running with remote debugging enabled (--remote-debugging-port=9222)`, ); } }
- src/schemas.ts:41-47 (schema)Zod schema defining the input parameters for the take_screenshot tool: optional outputPath and windowTitle.export const TakeScreenshotSchema = z.object({ outputPath: z .string() .optional() .describe('Path to save the screenshot (optional, defaults to temp directory)'), windowTitle: z.string().optional().describe('Specific window title to screenshot (optional)'), });
- src/tools.ts:26-31 (registration)Tool registration in the tools array, defining name 'take_screenshot', description, and input schema.{ name: ToolName.TAKE_SCREENSHOT, description: 'Take a screenshot of any running Electron application window. Returns base64 image data for AI analysis. No files created unless outputPath is specified.', inputSchema: zodToJsonSchema(TakeScreenshotSchema) as ToolInput, },
- src/handlers.ts:62-109 (registration)Handler dispatch in handleToolCall switch statement: validates args, calls takeScreenshot, and formats MCP response with base64 image.case ToolName.TAKE_SCREENSHOT: { // Security check for screenshot operation const securityResult = await securityManager.executeSecurely({ command: 'take_screenshot', args, sourceIP, userAgent, operationType: 'screenshot', }); if (securityResult.blocked) { return { content: [ { type: 'text', text: `Screenshot blocked: ${securityResult.error}`, }, ], isError: true, }; } const { outputPath, windowTitle } = TakeScreenshotSchema.parse(args); const result = await takeScreenshot(outputPath, windowTitle); // Return the screenshot as base64 data for AI to evaluate const content: any[] = []; if (result.filePath) { content.push({ type: 'text', text: `Screenshot saved to: ${result.filePath}`, }); } else { content.push({ type: 'text', text: 'Screenshot captured in memory (no file saved)', }); } // Add the image data for AI evaluation content.push({ type: 'image', data: result.base64!, mimeType: 'image/png', }); return { content, isError: false }; }