@just-every/mcp-screenshot-website-fast
Version:
Fast screenshot capture tool for web pages - optimized for Claude Vision API
86 lines (85 loc) • 3.74 kB
JavaScript
import { Command } from 'commander';
import { captureScreenshot, closeBrowser, } from './internal/screenshotCapture.js';
import { readFileSync, writeFileSync } from 'fs';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const packageJson = JSON.parse(readFileSync(join(__dirname, '../package.json'), 'utf-8'));
const program = new Command();
program
.name('mcp-screenshot')
.description('Fast screenshot capture tool for web pages - optimized for Claude Vision API')
.version(packageJson.version);
program
.command('capture <url>')
.description('Capture a screenshot of a URL')
.option('-w, --width <pixels>', 'Viewport width (max 1072)', '1072')
.option('-h, --height <pixels>', 'Viewport height (max 1072)', '1072')
.option('--no-full-page', 'Disable full page capture and tiling')
.option('--wait-until <event>', 'Wait until event: load, domcontentloaded, networkidle0, networkidle2', 'domcontentloaded')
.option('--wait-for <ms>', 'Additional wait time in milliseconds')
.option('-o, --output <path>', 'Output file path (required for tiled output)')
.action(async (url, options) => {
try {
const screenshotOptions = {
url,
viewport: {
width: Math.min(parseInt(options.width, 10), 1072),
height: Math.min(parseInt(options.height, 10), 1072),
},
fullPage: options.fullPage !== false,
waitUntil: options.waitUntil,
waitFor: options.waitFor
? parseInt(options.waitFor, 10)
: undefined,
};
console.error(`Capturing screenshot of ${url}...`);
const result = await captureScreenshot(screenshotOptions);
if ('tiles' in result) {
const tiledResult = result;
console.error(`✅ Screenshot captured successfully!`);
console.error(`📐 Full page dimensions: ${tiledResult.fullWidth}x${tiledResult.fullHeight}`);
console.error(`🔲 Created ${tiledResult.tiles.length} tiles of ${tiledResult.tileSize}x${tiledResult.tileSize} each`);
if (options.output) {
const ext = '.png';
const base = options.output.endsWith(ext)
? options.output.slice(0, -ext.length)
: options.output;
for (const tile of tiledResult.tiles) {
const filename = `${base}-tile-${tile.row}-${tile.col}${ext}`;
writeFileSync(filename, tile.screenshot);
console.error(`Saved tile ${tile.row},${tile.col} to: ${filename} (${tile.width}x${tile.height})`);
}
}
else {
console.error('Error: Full page tiled output requires -o/--output flag');
process.exit(1);
}
}
else {
if (options.output) {
writeFileSync(options.output, result.screenshot);
console.error(`✅ Screenshot saved to: ${options.output}`);
console.error(`📐 Dimensions: ${result.viewport.width}x${result.viewport.height}`);
}
else {
process.stdout.write(result.screenshot);
}
}
await closeBrowser();
}
catch (error) {
console.error('Error:', error instanceof Error ? error.message : error);
await closeBrowser();
process.exit(1);
}
});
program
.command('serve')
.description('Run as an MCP server')
.action(async () => {
await import('./serve.js');
});
program.parse();