Skip to main content
Glama

mcp-server-browserbase

Official
by browserbase
Apache 2.0
2,054
2,714
index.ts6.78 kB
import * as dotenv from "dotenv"; dotenv.config(); import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { z } from "zod"; import type { MCPToolsArray } from "./types/types.js"; import { Context } from "./context.js"; import type { Config } from "../config.d.ts"; import { TOOLS } from "./tools/index.js"; import { AvailableModelSchema } from "./types/models.js"; import { PROMPTS, getPrompt } from "./mcp/prompts.js"; import { RESOURCE_TEMPLATES } from "./mcp/resources.js"; import { ListResourcesRequestSchema, ReadResourceRequestSchema, ListResourceTemplatesRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, } from "@modelcontextprotocol/sdk/types.js"; const cookieSchema = z.object({ name: z.string(), value: z.string(), domain: z.string(), path: z.string().optional(), expires: z.number().optional(), httpOnly: z.boolean().optional(), secure: z.boolean().optional(), sameSite: z.enum(["Strict", "Lax", "None"]).optional(), }); // Configuration schema for Smithery - matches existing Config interface export const configSchema = z .object({ browserbaseApiKey: z.string().describe("The Browserbase API Key to use"), browserbaseProjectId: z .string() .describe("The Browserbase Project ID to use"), proxies: z .boolean() .optional() .describe("Whether or not to use Browserbase proxies"), advancedStealth: z .boolean() .optional() .describe( "Use advanced stealth mode. Only available to Browserbase Scale Plan users", ), keepAlive: z .boolean() .optional() .describe("Whether or not to keep the Browserbase session alive"), context: z .object({ contextId: z .string() .optional() .describe("The ID of the context to use"), persist: z .boolean() .optional() .describe("Whether or not to persist the context"), }) .optional(), viewPort: z .object({ browserWidth: z .number() .optional() .describe("The width of the browser"), browserHeight: z .number() .optional() .describe("The height of the browser"), }) .optional(), cookies: z .array(cookieSchema) .optional() .describe("Cookies to inject into the Browserbase context"), server: z .object({ port: z .number() .optional() .describe("The port to listen on for SHTTP or MCP transport"), host: z .string() .optional() .describe( "The host to bind the server to. Default is localhost. Use 0.0.0.0 to bind to all interfaces", ), }) .optional(), modelName: AvailableModelSchema.optional().describe( "The model to use for Stagehand (default: google/gemini-2.0-flash)", ), // Already an existing Zod Enum modelApiKey: z .string() .optional() .describe( "API key for the custom model provider. Required when using a model other than the default google/gemini-2.0-flash", ), experimental: z .boolean() .optional() .describe("Enable experimental Stagehand features"), }) .refine( (data) => { // If a non-default model is explicitly specified, API key is required if (data.modelName && data.modelName !== "google/gemini-2.0-flash") { return data.modelApiKey !== undefined && data.modelApiKey.length > 0; } return true; }, { message: "modelApiKey is required when specifying a custom model", path: ["modelApiKey"], }, ); // Default function for Smithery export default function ({ config }: { config: z.infer<typeof configSchema> }) { if (!config.browserbaseApiKey) { throw new Error("browserbaseApiKey is required"); } if (!config.browserbaseProjectId) { throw new Error("browserbaseProjectId is required"); } const server = new McpServer({ name: "Browserbase MCP Server", version: "2.0.0", description: "Cloud browser automation server powered by Browserbase and Stagehand. Enables LLMs to navigate websites, interact with elements, extract data, and capture screenshots using natural language commands.", capabilities: { resources: { subscribe: true, listChanged: true, }, prompts: { listChanged: true, }, sampling: {}, }, }); const internalConfig: Config = config as Config; // Create the context, passing server instance and config const context = new Context(server.server, internalConfig); server.server.registerCapabilities({ resources: { subscribe: true, listChanged: true, }, prompts: { listChanged: true, }, sampling: {}, }); // Add resource handlers server.server.setRequestHandler(ListResourcesRequestSchema, async () => { return context.listResources(); }); server.server.setRequestHandler( ReadResourceRequestSchema, async (request) => { return context.readResource(request.params.uri); }, ); server.server.setRequestHandler( ListResourceTemplatesRequestSchema, async () => { return { resourceTemplates: RESOURCE_TEMPLATES }; }, ); // Add prompt handlers server.server.setRequestHandler(ListPromptsRequestSchema, async () => { return { prompts: PROMPTS }; }); server.server.setRequestHandler(GetPromptRequestSchema, async (request) => { const prompt = getPrompt(request.params.name); return prompt; }); 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}`, ); } }); return server.server; }

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/browserbase/mcp-server-browserbase'

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