UNPKG

@origindot./zigzag

Version:

Comprehensive MCP server providing AI agents with visual, development, and design validation tools

235 lines 10 kB
import { exec } from 'child_process'; import { promisify } from 'util'; import { readFile, unlink } from 'fs/promises'; import * as os from 'os'; import * as path from 'path'; const execAsync = promisify(exec); export class ScreenshotTool { definition = { name: 'screenshot', description: 'Capture screenshots using system commands (cross-platform)', inputSchema: { type: 'object', properties: { target: { type: 'string', enum: ['screen', 'window', 'region'], description: 'What to capture' }, window_title: { type: 'string', description: 'Title of specific window to capture (for target="window")' }, region: { type: 'object', properties: { x: { type: 'number' }, y: { type: 'number' }, width: { type: 'number' }, height: { type: 'number' } }, description: 'Specific region coordinates (for target="region")' }, output_path: { type: 'string', description: 'Optional output file path (defaults to temp file)' }, format: { type: 'string', enum: ['png', 'jpg', 'bmp'], default: 'png' } }, required: ['target'] } }; async execute(args) { try { const platform = os.platform(); const tempDir = os.tmpdir(); const timestamp = Date.now(); const format = args.format || 'png'; const outputPath = args.output_path || path.join(tempDir, `screenshot-${timestamp}.${format}`); let success = false; switch (args.target) { case 'screen': success = await this.captureScreen(outputPath, platform); break; case 'window': if (!args.window_title) { throw new Error('window_title is required for window capture'); } success = await this.captureWindow(outputPath, args.window_title, platform); break; case 'region': if (!args.region) { throw new Error('region is required for region capture'); } success = await this.captureRegion(outputPath, args.region, platform); break; default: throw new Error('Invalid target type'); } if (!success) { throw new Error('Screenshot capture failed'); } // Read the image file and convert to base64 const imageBuffer = await readFile(outputPath); const base64Image = imageBuffer.toString('base64'); // Clean up temp file if we created it if (!args.output_path) { await unlink(outputPath).catch(() => { }); // Ignore cleanup errors } return { content: [{ type: 'image', data: base64Image, mimeType: `image/${format}` }, { type: 'text', text: `Screenshot captured successfully (${imageBuffer.length} bytes)` }], isError: false }; } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error'; return { content: [{ type: 'text', text: `Screenshot failed: ${errorMessage}` }], isError: true }; } } async captureScreen(outputPath, platform) { try { switch (platform) { case 'linux': // Try multiple methods for Linux const linuxCommands = [ `import -window root "${outputPath}"`, // ImageMagick `gnome-screenshot -f "${outputPath}"`, // GNOME `scrot "${outputPath}"`, // Scrot `spectacle -b -o "${outputPath}"`, // KDE Spectacle `maim "${outputPath}"` // Maim ]; for (const cmd of linuxCommands) { try { await execAsync(cmd); return true; } catch (e) { continue; // Try next command } } return false; case 'darwin': // macOS await execAsync(`screencapture "${outputPath}"`); return true; case 'win32': // Windows using PowerShell const psScript = ` Add-Type -AssemblyName System.Windows.Forms; $screen = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds; $bitmap = New-Object System.Drawing.Bitmap $screen.Width, $screen.Height; $graphics = [System.Drawing.Graphics]::FromImage($bitmap); $graphics.CopyFromScreen(0, 0, 0, 0, $bitmap.Size); $bitmap.Save("${outputPath}", [System.Drawing.Imaging.ImageFormat]::Png); $graphics.Dispose(); $bitmap.Dispose(); `; await execAsync(`powershell -Command "${psScript}"`); return true; default: throw new Error(`Unsupported platform: ${platform}`); } } catch (error) { console.error('Screen capture error:', error); return false; } } async captureWindow(outputPath, windowTitle, platform) { try { switch (platform) { case 'linux': // Get window ID by title and capture it const { stdout } = await execAsync(`xwininfo -name "${windowTitle}" | grep "Window id" | awk '{print $4}'`); const windowId = stdout.trim(); if (windowId) { await execAsync(`import -window ${windowId} "${outputPath}"`); return true; } return false; case 'darwin': // macOS - capture specific window await execAsync(`screencapture -l$(osascript -e 'tell app "${windowTitle}" to id of window 1') "${outputPath}"`); return true; case 'win32': // Windows - find and capture window const psWindowScript = ` Add-Type -AssemblyName System.Windows.Forms; $processes = Get-Process | Where-Object {$_.MainWindowTitle -like "*${windowTitle}*"}; if ($processes) { $hwnd = $processes[0].MainWindowHandle; # Window capture logic would go here # For now, fall back to full screen $screen = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds; $bitmap = New-Object System.Drawing.Bitmap $screen.Width, $screen.Height; $graphics = [System.Drawing.Graphics]::FromImage($bitmap); $graphics.CopyFromScreen(0, 0, 0, 0, $bitmap.Size); $bitmap.Save("${outputPath}", [System.Drawing.Imaging.ImageFormat]::Png); $graphics.Dispose(); $bitmap.Dispose(); } `; await execAsync(`powershell -Command "${psWindowScript}"`); return true; default: throw new Error(`Window capture not supported on platform: ${platform}`); } } catch (error) { console.error('Window capture error:', error); return false; } } async captureRegion(outputPath, region, platform) { try { const { x, y, width, height } = region; switch (platform) { case 'linux': // ImageMagick import with geometry await execAsync(`import -window root -crop ${width}x${height}+${x}+${y} "${outputPath}"`); return true; case 'darwin': // macOS screencapture with region await execAsync(`screencapture -R ${x},${y},${width},${height} "${outputPath}"`); return true; case 'win32': // Windows PowerShell with region const psRegionScript = ` Add-Type -AssemblyName System.Windows.Forms; $bitmap = New-Object System.Drawing.Bitmap ${width}, ${height}; $graphics = [System.Drawing.Graphics]::FromImage($bitmap); $graphics.CopyFromScreen(${x}, ${y}, 0, 0, $bitmap.Size); $bitmap.Save("${outputPath}", [System.Drawing.Imaging.ImageFormat]::Png); $graphics.Dispose(); $bitmap.Dispose(); `; await execAsync(`powershell -Command "${psRegionScript}"`); return true; default: throw new Error(`Region capture not supported on platform: ${platform}`); } } catch (error) { console.error('Region capture error:', error); return false; } } } //# sourceMappingURL=screenshot-system.js.map