Skip to main content
Glama

Firefox MCP Server

by JediLuke
index.js14.8 kB
// #!/usr/bin/env node // import { Server } from '@modelcontextprotocol/sdk/server/index.js'; // import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; // import { // CallToolRequestSchema, // ErrorCode, // ListToolsRequestSchema, // McpError, // } from '@modelcontextprotocol/sdk/types.js'; // import { chromium, firefox } from 'playwright'; // class FirefoxMCPServer { // constructor() { // this.server = new Server( // { // name: 'firefox-mcp-server', // version: '1.0.0', // }, // { // capabilities: { // tools: {}, // }, // } // ); // this.browser = null; // this.page = null; // this.setupToolHandlers(); // } // setupToolHandlers() { // this.server.setRequestHandler(ListToolsRequestSchema, async () => { // return { // tools: [ // { // name: 'launch_firefox', // description: 'Launch Firefox browser', // inputSchema: { // type: 'object', // properties: { // headless: { // type: 'boolean', // description: 'Run browser in headless mode', // default: false // }, // url: { // type: 'string', // description: 'Initial URL to navigate to', // default: 'about:blank' // } // } // } // }, // { // name: 'navigate', // description: 'Navigate to a URL', // inputSchema: { // type: 'object', // properties: { // url: { // type: 'string', // description: 'URL to navigate to' // } // }, // required: ['url'] // } // }, // { // name: 'click', // description: 'Click on an element', // inputSchema: { // type: 'object', // properties: { // selector: { // type: 'string', // description: 'CSS selector or text content to click' // }, // coordinates: { // type: 'object', // properties: { // x: { type: 'number' }, // y: { type: 'number' } // }, // description: 'Click at specific coordinates (alternative to selector)' // } // } // } // }, // { // name: 'type_text', // description: 'Type text into an input field', // inputSchema: { // type: 'object', // properties: { // selector: { // type: 'string', // description: 'CSS selector of the input field' // }, // text: { // type: 'string', // description: 'Text to type' // } // }, // required: ['selector', 'text'] // } // }, // { // name: 'get_page_content', // description: 'Get the HTML content of the current page', // inputSchema: { // type: 'object', // properties: { // selector: { // type: 'string', // description: 'CSS selector to get specific element content (optional)' // } // } // } // }, // { // name: 'get_page_text', // description: 'Get the visible text content of the current page', // inputSchema: { // type: 'object', // properties: { // selector: { // type: 'string', // description: 'CSS selector to get specific element text (optional)' // } // } // } // }, // { // name: 'screenshot', // description: 'Take a screenshot of the current page', // inputSchema: { // type: 'object', // properties: { // path: { // type: 'string', // description: 'File path to save screenshot', // default: 'screenshot.png' // }, // fullPage: { // type: 'boolean', // description: 'Capture full page', // default: false // } // } // } // }, // { // name: 'wait_for_element', // description: 'Wait for an element to appear on the page', // inputSchema: { // type: 'object', // properties: { // selector: { // type: 'string', // description: 'CSS selector to wait for' // }, // timeout: { // type: 'number', // description: 'Timeout in milliseconds', // default: 30000 // } // }, // required: ['selector'] // } // }, // { // name: 'execute_script', // description: 'Execute JavaScript in the browser', // inputSchema: { // type: 'object', // properties: { // script: { // type: 'string', // description: 'JavaScript code to execute' // } // }, // required: ['script'] // } // }, // { // name: 'close_browser', // description: 'Close the Firefox browser', // inputSchema: { // type: 'object', // properties: {} // } // }, // { // name: 'get_current_url', // description: 'Get the current page URL', // inputSchema: { // type: 'object', // properties: {} // } // }, // { // name: 'back', // description: 'Navigate back in browser history', // inputSchema: { // type: 'object', // properties: {} // } // }, // { // name: 'forward', // description: 'Navigate forward in browser history', // inputSchema: { // type: 'object', // properties: {} // } // }, // { // name: 'reload', // description: 'Reload the current page', // inputSchema: { // type: 'object', // properties: {} // } // } // ], // }; // }); // this.server.setRequestHandler(CallToolRequestSchema, async (request) => { // const { name, arguments: args } = request.params; // try { // switch (name) { // case 'launch_firefox': // return await this.launchFirefox(args); // case 'navigate': // return await this.navigate(args); // case 'click': // return await this.click(args); // case 'type_text': // return await this.typeText(args); // case 'get_page_content': // return await this.getPageContent(args); // case 'get_page_text': // return await this.getPageText(args); // case 'screenshot': // return await this.screenshot(args); // case 'wait_for_element': // return await this.waitForElement(args); // case 'execute_script': // return await this.executeScript(args); // case 'close_browser': // return await this.closeBrowser(); // case 'get_current_url': // return await this.getCurrentUrl(); // case 'back': // return await this.back(); // case 'forward': // return await this.forward(); // case 'reload': // return await this.reload(); // default: // throw new McpError( // ErrorCode.MethodNotFound, // `Unknown tool: ${name}` // ); // } // } catch (error) { // throw new McpError( // ErrorCode.InternalError, // `Error executing ${name}: ${error.message}` // ); // } // }); // } // async launchFirefox(args = {}) { // const { headless = false, url = 'about:blank' } = args; // try { // this.browser = await firefox.launch({ // headless, // firefoxUserPrefs: { // 'dom.webnotifications.enabled': false, // 'media.navigator.permission.disabled': true // } // }); // this.page = await this.browser.newPage(); // await this.page.goto(url); // return { // content: [ // { // type: 'text', // text: `Firefox launched successfully. Navigated to: ${url}` // } // ] // }; // } catch (error) { // throw new Error(`Failed to launch Firefox: ${error.message}`); // } // } // async navigate(args) { // this.ensureBrowserRunning(); // const { url } = args; // await this.page.goto(url); // return { // content: [ // { // type: 'text', // text: `Navigated to: ${url}` // } // ] // }; // } // async click(args) { // this.ensureBrowserRunning(); // const { selector, coordinates } = args; // if (coordinates) { // await this.page.click(`body`, { position: coordinates }); // return { // content: [ // { // type: 'text', // text: `Clicked at coordinates (${coordinates.x}, ${coordinates.y})` // } // ] // }; // } else if (selector) { // await this.page.click(selector); // return { // content: [ // { // type: 'text', // text: `Clicked element: ${selector}` // } // ] // }; // } else { // throw new Error('Either selector or coordinates must be provided'); // } // } // async typeText(args) { // this.ensureBrowserRunning(); // const { selector, text } = args; // await this.page.fill(selector, text); // return { // content: [ // { // type: 'text', // text: `Typed "${text}" into ${selector}` // } // ] // }; // } // async getPageContent(args = {}) { // this.ensureBrowserRunning(); // const { selector } = args; // let content; // if (selector) { // content = await this.page.innerHTML(selector); // } else { // content = await this.page.content(); // } // return { // content: [ // { // type: 'text', // text: content // } // ] // }; // } // async getPageText(args = {}) { // this.ensureBrowserRunning(); // const { selector } = args; // let text; // if (selector) { // text = await this.page.textContent(selector); // } else { // text = await this.page.textContent('body'); // } // return { // content: [ // { // type: 'text', // text: text || '' // } // ] // }; // } // async screenshot(args = {}) { // this.ensureBrowserRunning(); // const { path = 'screenshot.png', fullPage = false } = args; // await this.page.screenshot({ // path, // fullPage // }); // return { // content: [ // { // type: 'text', // text: `Screenshot saved to: ${path}` // } // ] // }; // } // async waitForElement(args) { // this.ensureBrowserRunning(); // const { selector, timeout = 30000 } = args; // await this.page.waitForSelector(selector, { timeout }); // return { // content: [ // { // type: 'text', // text: `Element found: ${selector}` // } // ] // }; // } // async executeScript(args) { // this.ensureBrowserRunning(); // const { script } = args; // const result = await this.page.evaluate(script); // return { // content: [ // { // type: 'text', // text: `Script executed. Result: ${JSON.stringify(result)}` // } // ] // }; // } // async closeBrowser() { // if (this.browser) { // await this.browser.close(); // this.browser = null; // this.page = null; // } // return { // content: [ // { // type: 'text', // text: 'Firefox browser closed' // } // ] // }; // } // async getCurrentUrl() { // this.ensureBrowserRunning(); // const url = this.page.url(); // return { // content: [ // { // type: 'text', // text: `Current URL: ${url}` // } // ] // }; // } // async back() { // this.ensureBrowserRunning(); // await this.page.goBack(); // return { // content: [ // { // type: 'text', // text: 'Navigated back' // } // ] // }; // } // async forward() { // this.ensureBrowserRunning(); // await this.page.goForward(); // return { // content: [ // { // type: 'text', // text: 'Navigated forward' // } // ] // }; // } // async reload() { // this.ensureBrowserRunning(); // await this.page.reload(); // return { // content: [ // { // type: 'text', // text: 'Page reloaded' // } // ] // }; // } // ensureBrowserRunning() { // if (!this.browser || !this.page) { // throw new Error('Firefox browser is not running. Please launch it first using the launch_firefox tool.'); // } // } // async run() { // const transport = new StdioServerTransport(); // await this.server.connect(transport); // console.error('Firefox MCP server running on stdio'); // } // } // const server = new FirefoxMCPServer(); // server.run().catch(console.error);

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

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