Skip to main content
Glama

start-browser

Launch a browser instance with customizable settings for testing or development workflows, including viewport configuration and URL navigation.

Instructions

Creates a new browser context with an auto-generated unique ID

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
typeNoBrowser type (default: chromium)
displayNameNoHuman-readable name for the browser
targetUrlNoURL to navigate to after starting
headlessNoRun browser in headless mode (default: false)
viewportNoBrowser viewport size (default: 1280x800)
tagsNoTags for organizing browsers
purposeNoDescription of what this browser is for

Implementation Reference

  • The MCP tool handler for 'start-browser'. Generates unique context ID, invokes ContextManager.createContext, formats response with browser details.
    async ({ type, displayName, targetUrl, headless, viewport, tags, purpose }) => { // Generate cryptographically secure unique browser ID const contextId = `context-${randomUUID()}`; try { const result = await contextManager.createContext({ id: contextId, type: type as BrowserType | undefined, displayName, targetUrl, headless, viewport, tags, purpose }); if (result.success) { return { content: [ { type: 'text', text: `Browser created successfully!\nBrowser ID: ${contextId}\nType: ${result.data?.type || type || 'chromium'}\nURL: ${targetUrl || 'about:blank'}` } ], // Include the generated ID in the response for easy access contextId: contextId, browserInfo: { id: contextId, type: result.data?.type || type || 'chromium', displayName: displayName, targetUrl: targetUrl || 'about:blank' } }; } else { return { content: [ { type: 'text', text: `Failed to create browser: ${result.error}` } ], isError: true }; } } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); Logger.error(`Failed to create browser ${contextId}:`, error); return { content: [ { type: 'text', text: `Failed to create browser: ${errorMessage}` } ], isError: true }; } }
  • Input validation schema (Zod) for the 'start-browser' tool parameters.
    { type: z.enum(['chromium', 'firefox', 'webkit']).optional().describe('Browser type (default: chromium)'), displayName: z.string().optional().describe('Human-readable name for the browser'), targetUrl: z.string().optional().describe('URL to navigate to after starting'), headless: z.boolean().optional().describe('Run browser in headless mode (default: false)'), viewport: z.object({ width: z.number(), height: z.number() }).optional().describe('Browser viewport size (default: 1280x800)'), tags: z.array(z.string()).optional().describe('Tags for organizing browsers'), purpose: z.string().optional().describe('Description of what this browser is for') },
  • Direct registration of the 'start-browser' tool via server.tool() call, including name, description, schema, and handler.
    server.tool( 'start-browser', 'Creates a new browser context with an auto-generated unique ID', { type: z.enum(['chromium', 'firefox', 'webkit']).optional().describe('Browser type (default: chromium)'), displayName: z.string().optional().describe('Human-readable name for the browser'), targetUrl: z.string().optional().describe('URL to navigate to after starting'), headless: z.boolean().optional().describe('Run browser in headless mode (default: false)'), viewport: z.object({ width: z.number(), height: z.number() }).optional().describe('Browser viewport size (default: 1280x800)'), tags: z.array(z.string()).optional().describe('Tags for organizing browsers'), purpose: z.string().optional().describe('Description of what this browser is for') }, async ({ type, displayName, targetUrl, headless, viewport, tags, purpose }) => { // Generate cryptographically secure unique browser ID const contextId = `context-${randomUUID()}`; try { const result = await contextManager.createContext({ id: contextId, type: type as BrowserType | undefined, displayName, targetUrl, headless, viewport, tags, purpose }); if (result.success) { return { content: [ { type: 'text', text: `Browser created successfully!\nBrowser ID: ${contextId}\nType: ${result.data?.type || type || 'chromium'}\nURL: ${targetUrl || 'about:blank'}` } ], // Include the generated ID in the response for easy access contextId: contextId, browserInfo: { id: contextId, type: result.data?.type || type || 'chromium', displayName: displayName, targetUrl: targetUrl || 'about:blank' } }; } else { return { content: [ { type: 'text', text: `Failed to create browser: ${result.error}` } ], isError: true }; } } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); Logger.error(`Failed to create browser ${contextId}:`, error); return { content: [ { type: 'text', text: `Failed to create browser: ${errorMessage}` } ], isError: true }; } } );
  • src/index.ts:82-82 (registration)
    Top-level call to registerBrowserManagerTools(server), which registers all browser manager tools including 'start-browser'.
    const contextManager = registerBrowserManagerTools(server);
  • Core helper method implementing browser context creation: launches shared Playwright browser if needed, creates isolated context and page, handles navigation and persistence.
    async createContext(options: ContextCreateOptions): Promise<ContextOperationResult> { try { // Check context limit if (this.contexts.size >= this.MAX_CONTEXTS) { return { success: false, error: `Maximum number of contexts (${this.MAX_CONTEXTS}) reached` }; } // Check if context ID already exists if (this.contexts.has(options.id)) { return { success: false, error: `Context with ID '${options.id}' already exists` }; } const browserType = options.type || BrowserType.CHROMIUM; const headless = options.headless ?? false; const viewport = options.viewport || { width: 1280, height: 800 }; Logger.info(`Creating context: ${options.id} (${browserType})`); // Get or create shared browser instance const browser = await this.ensureSharedBrowser(browserType, headless); // Create isolated context const context = await browser.newContext({ viewport }); // Always create a page (following Playwright standard pattern) const page = await context.newPage(); // Navigate to targetUrl if provided, otherwise stays at default "about:blank" if (options.targetUrl) { await page.goto(options.targetUrl, { waitUntil: 'networkidle' }); } const metadata: ContextMetadata = { tags: options.tags || [], purpose: options.purpose, targetUrl: options.targetUrl, viewport, headless }; const contextInstance: ContextInstance = { id: options.id, type: browserType, displayName: options.displayName, context, page, metadata, createdAt: new Date(), lastUsedAt: new Date() }; this.contexts.set(options.id, contextInstance); if (this.sharedBrowser) { this.sharedBrowser.contextCount++; } // Persist to database const db = getScreenshotDB(); db.saveBrowserInstance( // TODO: rename to saveContextInstance options.id, browserType, options.displayName, metadata ); Logger.info(`Context created successfully: ${options.id}`); return { success: true, contextId: options.id, data: { id: options.id, type: browserType, displayName: options.displayName, targetUrl: options.targetUrl } }; } catch (error) { Logger.error(`Failed to create context ${options.id}:`, error); return { success: false, error: error instanceof Error ? error.message : String(error) }; } }

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/ESnark/blowback'

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