import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { screenshotSchema, pdfSchema } from '../schemas.js';
import { getPageForOperation } from '../tabs.js';
import {
handleResult,
ok,
err,
selectorNotFound,
normalizeError,
} from '../errors.js';
import type { ScreenshotFormat, PdfFormat } from '../types.js';
/**
* Register media capture tools
*/
export function registerMediaTools(server: McpServer): void {
// Screenshot
server.tool(
'screenshot',
'Capture a screenshot of the page or a specific element',
screenshotSchema.shape,
async ({ fullPage, selector, format, quality, width, height, scale, tabId }) => {
const pageResult = await getPageForOperation(tabId);
if (!pageResult.success) {
return handleResult(pageResult);
}
const page = pageResult.data;
const imageFormat = (format ?? 'png') as ScreenshotFormat;
// Set viewport with sensible defaults for reasonable image sizes
const viewportWidth = width ?? 1024;
const viewportHeight = height ?? 768;
const deviceScaleFactor = scale ?? 1;
try {
// Set viewport before screenshot to control resolution
await page.setViewport({
width: viewportWidth,
height: viewportHeight,
deviceScaleFactor,
});
let screenshotData: Uint8Array;
if (selector) {
// Screenshot specific element
const element = await page.$(selector);
if (!element) {
return handleResult(err(selectorNotFound(selector)));
}
screenshotData = await element.screenshot({
type: imageFormat,
quality: imageFormat === 'png' ? undefined : (quality ?? 100),
});
} else {
// Screenshot page/viewport
screenshotData = await page.screenshot({
fullPage: fullPage ?? false,
type: imageFormat,
quality: imageFormat === 'png' ? undefined : (quality ?? 100),
});
}
const base64Data = Buffer.from(screenshotData).toString('base64');
const mimeType = imageFormat === 'png' ? 'image/png'
: imageFormat === 'jpeg' ? 'image/jpeg'
: 'image/webp';
// Return as image content block for efficient processing by Claude
return {
content: [
{
type: 'image' as const,
data: base64Data,
mimeType,
},
],
};
} catch (error) {
return handleResult(err(normalizeError(error)));
}
}
);
// PDF
server.tool(
'pdf',
'Generate a PDF of the current page',
pdfSchema.shape,
async ({ format, landscape, printBackground, margin, tabId }) => {
const pageResult = await getPageForOperation(tabId);
if (!pageResult.success) {
return handleResult(pageResult);
}
const page = pageResult.data;
try {
const pdfData = await page.pdf({
format: (format ?? 'A4') as PdfFormat,
landscape: landscape ?? false,
printBackground: printBackground ?? true,
margin: margin ?? undefined,
});
const base64Data = Buffer.from(pdfData).toString('base64');
return handleResult(ok({
data: base64Data,
size: pdfData.length,
}));
} catch (error) {
return handleResult(err(normalizeError(error)));
}
}
);
}