Skip to main content
Glama
MesuterPikin

Browserbase MCP Server

by MesuterPikin

browserbase_screenshot

Capture full-page screenshots of websites for documentation, testing, or analysis purposes. This tool saves screenshots as resources for later reference.

Instructions

Capture a full-page screenshot and return it (and save as a resource).

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
nameNoThe name of the screenshot

Implementation Reference

  • The core handler function `handleScreenshot` for the `browserbase_screenshot` tool. Captures a full-page screenshot of the active page using Chrome DevTools Protocol's Page.captureScreenshot, resizes the PNG image using Sharp if it exceeds Claude's vision API limits (1568px edge, 1.15MP), generates a timestamped name, registers the base64 image as an MCP resource via `registerScreenshot`, notifies the server of resource changes, and returns a ToolResult with text and image content.
    async function handleScreenshot(
      context: Context,
      params: ScreenshotInput,
    ): Promise<ToolResult> {
      const action = async (): Promise<ToolActionResult> => {
        try {
          const stagehand = await context.getStagehand();
          const page = stagehand.context.pages()[0];
    
          if (!page) {
            throw new Error("No active page available");
          }
    
          // We're taking a full page screenshot to give context of the entire page, similar to a snapshot
          // Enable Page domain if needed
          await page.sendCDP("Page.enable");
    
          // Use CDP to capture screenshot
          const { data } = await page.sendCDP<{ data: string }>(
            "Page.captureScreenshot",
            {
              format: "png",
              fromSurface: true,
            },
          );
    
          // data is already base64 string from CDP
          let screenshotBase64 = data;
    
          // Scale down image if needed for Claude's vision API
          // Claude constraints: max 1568px on any edge AND max 1.15 megapixels
          // Reference: https://docs.anthropic.com/en/docs/build-with-claude/vision#evaluate-image-size
          const imageBuffer = Buffer.from(data, "base64");
          const metadata = await sharp(imageBuffer).metadata();
    
          if (metadata.width && metadata.height) {
            const pixels = metadata.width * metadata.height;
    
            // Min of: width constraint, height constraint, and megapixel constraint
            const shrink = Math.min(
              1568 / metadata.width,
              1568 / metadata.height,
              Math.sqrt((1.15 * 1024 * 1024) / pixels),
            );
    
            // Only resize if we need to shrink (shrink < 1)
            if (shrink < 1) {
              const newWidth = Math.floor(metadata.width * shrink);
              const newHeight = Math.floor(metadata.height * shrink);
    
              process.stderr.write(
                `[Screenshot] Scaling image from ${metadata.width}x${metadata.height} (${(pixels / (1024 * 1024)).toFixed(2)}MP) to ${newWidth}x${newHeight} (${((newWidth * newHeight) / (1024 * 1024)).toFixed(2)}MP) for Claude vision API\n`,
              );
    
              const resizedBuffer = await sharp(imageBuffer)
                .resize(newWidth, newHeight, {
                  fit: "inside",
                  withoutEnlargement: true,
                })
                .png()
                .toBuffer();
    
              screenshotBase64 = resizedBuffer.toString("base64");
            }
          }
          const name = params.name
            ? `screenshot-${params.name}-${new Date()
                .toISOString()
                .replace(/:/g, "-")}`
            : `screenshot-${new Date().toISOString().replace(/:/g, "-")}` +
              context.config.browserbaseProjectId;
    
          // Associate with current mcp session id and store in memory /src/mcp/resources.ts
          const sessionId = context.currentSessionId;
          registerScreenshot(sessionId, name, screenshotBase64);
    
          // Notify the client that the resources changed
          const serverInstance = context.getServer();
    
          if (serverInstance) {
            serverInstance.notification({
              method: "notifications/resources/list_changed",
            });
          }
    
          return {
            content: [
              {
                type: "text",
                text: `Screenshot taken with name: ${name}`,
              },
              {
                type: "image",
                data: screenshotBase64,
                mimeType: "image/png",
              },
            ],
          };
        } catch (error) {
          const errorMsg = error instanceof Error ? error.message : String(error);
          throw new Error(`Failed to take screenshot: ${errorMsg}`);
        }
      };
    
      return {
        action,
        waitForNetwork: false,
      };
    }
  • Defines the input schema `ScreenshotInputSchema` (optional `name` string) using Zod and the `screenshotSchema` ToolSchema object with name `"browserbase_screenshot"`, description, and inputSchema.
    const ScreenshotInputSchema = z.object({
      name: z.string().optional().describe("The name of the screenshot"),
    });
    
    type ScreenshotInput = z.infer<typeof ScreenshotInputSchema>;
    
    const screenshotSchema: ToolSchema<typeof ScreenshotInputSchema> = {
      name: "browserbase_screenshot",
      description: `Capture a full-page screenshot and return it (and save as a resource).`,
      inputSchema: ScreenshotInputSchema,
    };
  • Creates and exports the `screenshotTool` Tool object, combining the `screenshotSchema` and `handleScreenshot` function for use in the tools index.
    const screenshotTool: Tool<typeof ScreenshotInputSchema> = {
      capability: "core",
      schema: screenshotSchema,
      handle: handleScreenshot,
    };
    
    export default screenshotTool;
  • Includes `screenshotTool` in the `TOOLS` array (imported at line 5), which is consumed by the MCP server to register all tools.
    export const TOOLS = [
      ...sessionTools,
      navigateTool,
      actTool,
      extractTool,
      observeTool,
      screenshotTool,
      getUrlTool,
      agentTool,
    ];
  • src/index.ts:168-198 (registration)
    Registers all tools from `TOOLS` (including `browserbase_screenshot`) with the MCP server using `server.tool()`, providing a wrapper handler that invokes `context.run(tool, params)`.
    const tools: MCPToolsArray = [...TOOLS];
    
    // Register each tool with the Smithery server
    tools.forEach((tool) => {
      if (tool.schema.inputSchema instanceof z.ZodObject) {
        server.tool(
          tool.schema.name,
          tool.schema.description,
          tool.schema.inputSchema.shape,
          async (params: z.infer<typeof tool.schema.inputSchema>) => {
            try {
              const result = await context.run(tool, params);
              return result;
            } catch (error) {
              const errorMessage =
                error instanceof Error ? error.message : String(error);
              process.stderr.write(
                `[Smithery Error] ${new Date().toISOString()} Error running tool ${tool.schema.name}: ${errorMessage}\n`,
              );
              throw new Error(
                `Failed to run tool '${tool.schema.name}': ${errorMessage}`,
              );
            }
          },
        );
      } else {
        console.warn(
          `Tool "${tool.schema.name}" has an input schema that is not a ZodObject. Schema type: ${tool.schema.inputSchema.constructor.name}`,
        );
      }
    });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/MesuterPikin/mcp-server-browserbase'

If you have feedback or need assistance with the MCP directory API, please join our Discord server