UNPKG

@brave/brave-search-mcp-server

Version:

Brave Search MCP Server: web results, images, videos, rich results, AI summaries, and more.

97 lines (96 loc) 4.35 kB
import { LoggingLevelSchema } from '@modelcontextprotocol/sdk/types.js'; import { Command } from 'commander'; import dotenv from 'dotenv'; import tools from './tools/index.js'; dotenv.config({ debug: false, quiet: true }); function parseToolNameList(value) { if (value == null) return []; if (Array.isArray(value)) return value.map((t) => t.trim()).filter((t) => t.length > 0); return value .trim() .split(/\s+/) .filter((t) => t.length > 0); } const state = { transport: 'stdio', port: 8080, host: '0.0.0.0', braveApiKey: process.env.BRAVE_API_KEY ?? '', loggingLevel: 'info', ready: false, enabledTools: [], disabledTools: [], stateless: false, }; export function isToolPermittedByUser(toolName) { return state.enabledTools.length > 0 ? state.enabledTools.includes(toolName) : state.disabledTools.includes(toolName) === false; } export function getOptions() { const program = new Command() .option('--brave-api-key <string>', 'Brave API key', process.env.BRAVE_API_KEY ?? '') .option('--logging-level <string>', 'Logging level', process.env.BRAVE_MCP_LOG_LEVEL ?? 'info') .option('--transport <stdio|http>', 'transport type', process.env.BRAVE_MCP_TRANSPORT ?? 'stdio') .option('--enabled-tools <names...>', 'tools to enable', process.env.BRAVE_MCP_ENABLED_TOOLS?.trim().split(' ') ?? []) .option('--disabled-tools <names...>', 'tools to disable', process.env.BRAVE_MCP_DISABLED_TOOLS?.trim().split(' ') ?? []) .option('--port <number>', 'desired port for HTTP transport', process.env.BRAVE_MCP_PORT ?? '8080') .option('--host <string>', 'desired host for HTTP transport', process.env.BRAVE_MCP_HOST ?? '0.0.0.0') .option('--stateless <boolean>', 'whether the server should be stateless', process.env.BRAVE_MCP_STATELESS === 'true' ? true : false) .allowUnknownOption() .parse(process.argv); const options = program.opts(); const toolNames = Object.values(tools).map((tool) => tool.name); // Validate tool inclusion configuration const enabledTools = parseToolNameList(options.enabledTools); const disabledTools = parseToolNameList(options.disabledTools); if (enabledTools.length > 0 && disabledTools.length > 0) { console.error('Error: --enabled-tools and --disabled-tools cannot be used together'); return false; } const invalidToolNames = [...enabledTools, ...disabledTools].filter((t) => !toolNames.includes(t)); if (invalidToolNames.length > 0) { console.error(`Invalid tool name(s) used: ${invalidToolNames.join(', ')}`); console.error(`Valid tool names are: ${toolNames.join(', ')}`); return false; } // Validate all other options if (!['stdio', 'http'].includes(options.transport)) { console.error(`Invalid --transport value: '${options.transport}'. Must be one of: stdio, http.`); return false; } if (!LoggingLevelSchema.options.includes(options.loggingLevel)) { console.error(`Invalid --logging-level value: '${options.loggingLevel}'. Must be one of: ${LoggingLevelSchema.options.join(', ')}`); return false; } if (!options.braveApiKey) { console.error('Error: --brave-api-key is required. You can get one at https://brave.com/search/api/.'); return false; } if (options.transport === 'http') { if (options.port < 1 || options.port > 65535) { console.error(`Invalid --port value: '${options.port}'. Must be a valid port number between 1 and 65535.`); return false; } if (!options.host) { console.error('Error: --host is required'); return false; } } // Normalize stateless to boolean (CLI passes it as string) options.stateless = options.stateless === true || options.stateless === 'true'; // Update state state.braveApiKey = options.braveApiKey; state.transport = options.transport; state.port = options.port; state.host = options.host; state.loggingLevel = options.loggingLevel; state.enabledTools = enabledTools; state.disabledTools = disabledTools; state.stateless = options.stateless; state.ready = true; return options; } export default state;