Skip to main content
Glama
brave

Brave Search MCP Server

Official

brave_web_search

Perform web searches using Brave Search API to find information, news, locations, videos, and discussions with comprehensive metadata and filtering options.

Instructions

Performs web searches using the Brave Search API and returns comprehensive search results with rich metadata. When to use: - General web searches for information, facts, or current topics - Location-based queries (restaurants, businesses, points of interest) - News searches for recent events or breaking stories - Finding videos, discussions, or FAQ content - Research requiring diverse result types (web pages, images, reviews, etc.) Returns a JSON list of web results with title, description, and URL. When the "results_filter" parameter is empty, JSON results may also contain FAQ, Discussions, News, and Video results.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
countNoNumber of results (1-20, default 10). Applies only to web search results (i.e., has no effect on locations, news, videos, etc.)
countryNoSearch query country, where the results come from. The country string is limited to 2 character country codes of supported countries.US
extra_snippetsNoA snippet is an excerpt from a page you get as a result of the query, and extra_snippets allow you to get up to 5 additional, alternative excerpts. Only available under Free AI, Base AI, Pro AI, Base Data, Pro Data and Custom plans.
freshnessNoFilters search results by when they were discovered. The following values are supported: 'pd' - Discovered within the last 24 hours. 'pw' - Discovered within the last 7 days. 'pm' - Discovered within the last 31 days. 'py' - Discovered within the last 365 days. 'YYYY-MM-DDtoYYYY-MM-DD' - Timeframe is also supported by specifying the date range e.g. 2022-04-01to2022-07-30.
gogglesNoGoggles act as a custom re-ranking on top of Brave's search index. The parameter supports both a url where the Goggle is hosted or the definition of the Goggle. For more details, refer to the Goggles repository (i.e., https://github.com/brave/goggles-quickstart).
offsetNoPagination offset (max 9, default 0)
queryYesSearch query (max 400 chars, 50 words)
result_filterNoResult filter (default ['web', 'query'])
safesearchNoFilters search results for adult content. The following values are supported: 'off' - No filtering. 'moderate' - Filters explicit content (e.g., images and videos), but allows adult domains in search results. 'strict' - Drops all adult content from search results. The default value is 'moderate'.moderate
search_langNoSearch language preference. The 2 or more character language code for which the search results are provided.en
spellcheckNoWhether to spellcheck the provided query.
summaryNoThis parameter enables summary key generation in web search results. This is required for summarizer to be enabled.
text_decorationsNoWhether display strings (e.g. result snippets) should include decoration markers (e.g. highlighting characters).
ui_langNoThe language of the UI. The 2 or more character language code for which the search results are provided.en-US
unitsNoThe measurement units. If not provided, units are derived from search country.

Implementation Reference

  • Main execution handler for the brave_web_search tool. Calls the Brave Search API with provided params, handles summarizer key if present, formats and stringifies web, FAQ, discussions, news, and video results into TextContent blocks, or returns error if no web results.
    export const execute = async (params: QueryParams) => { const response = { content: [] as TextContent[], isError: false }; const { web, faq, discussions, news, videos, summarizer } = await API.issueRequest<'web'>( 'web', params ); if (summarizer) { response.content.push({ type: 'text' as const, text: `Summarizer key: ${summarizer.key}`, }); } if (!web || !Array.isArray(web.results) || web.results.length < 1) { response.isError = true; response.content.push({ type: 'text' as const, text: 'No web results found', }); return response; } // TODO (Sampson): The following is unnecessarily repetitive. if (web && web.results?.length > 0) { for (const entry of formatWebResults(web)) { response.content.push({ type: 'text' as const, text: stringify(entry), }); } } if (faq && faq.results?.length > 0) { for (const entry of formatFAQResults(faq)) { response.content.push({ type: 'text' as const, text: stringify(entry), }); } } if (discussions && discussions.results?.length > 0) { for (const entry of formatDiscussionsResults(discussions)) { response.content.push({ type: 'text' as const, text: stringify(entry), }); } } if (news && news.results?.length > 0) { for (const entry of formatNewsResults(news)) { response.content.push({ type: 'text' as const, text: stringify(entry), }); } } if (videos && videos.results?.length > 0) { for (const entry of formatVideoResults(videos)) { response.content.push({ type: 'text' as const, text: stringify(entry), }); } } return response;
  • Zod input schema defining all parameters for the brave_web_search tool, including query, country, language options, count, filters, and advanced options like goggles and summary.
    export const params = z.object({ query: z .string() .max(400) .refine((str) => str.split(/\s+/).length <= 50, 'Query cannot exceed 50 words') .describe('Search query (max 400 chars, 50 words)'), country: z .enum([ 'ALL', 'AR', 'AU', 'AT', 'BE', 'BR', 'CA', 'CL', 'DK', 'FI', 'FR', 'DE', 'HK', 'IN', 'ID', 'IT', 'JP', 'KR', 'MY', 'MX', 'NL', 'NZ', 'NO', 'CN', 'PL', 'PT', 'PH', 'RU', 'SA', 'ZA', 'ES', 'SE', 'CH', 'TW', 'TR', 'GB', 'US', ]) .default('US') .describe( 'Search query country, where the results come from. The country string is limited to 2 character country codes of supported countries.' ) .optional(), search_lang: z .enum([ 'ar', 'eu', 'bn', 'bg', 'ca', 'zh-hans', 'zh-hant', 'hr', 'cs', 'da', 'nl', 'en', 'en-gb', 'et', 'fi', 'fr', 'gl', 'de', 'gu', 'he', 'hi', 'hu', 'is', 'it', 'jp', 'kn', 'ko', 'lv', 'lt', 'ms', 'ml', 'mr', 'nb', 'pl', 'pt-br', 'pt-pt', 'pa', 'ro', 'ru', 'sr', 'sk', 'sl', 'es', 'sv', 'ta', 'te', 'th', 'tr', 'uk', 'vi', ]) .default('en') .describe( 'Search language preference. The 2 or more character language code for which the search results are provided.' ) .optional(), ui_lang: z .enum([ 'es-AR', 'en-AU', 'de-AT', 'nl-BE', 'fr-BE', 'pt-BR', 'en-CA', 'fr-CA', 'es-CL', 'da-DK', 'fi-FI', 'fr-FR', 'de-DE', 'zh-HK', 'en-IN', 'en-ID', 'it-IT', 'ja-JP', 'ko-KR', 'en-MY', 'es-MX', 'nl-NL', 'en-NZ', 'no-NO', 'zh-CN', 'pl-PL', 'en-PH', 'ru-RU', 'en-ZA', 'es-ES', 'sv-SE', 'fr-CH', 'de-CH', 'zh-TW', 'tr-TR', 'en-GB', 'en-US', 'es-US', ]) .default('en-US') .describe( 'The language of the UI. The 2 or more character language code for which the search results are provided.' ) .optional(), count: z .number() .int() .min(1) .max(20) .default(10) .describe( 'Number of results (1-20, default 10). Applies only to web search results (i.e., has no effect on locations, news, videos, etc.)' ) .optional(), offset: z .number() .int() .min(0) .max(9) .default(0) .describe('Pagination offset (max 9, default 0)') .optional(), safesearch: z .enum(['off', 'moderate', 'strict']) .default('moderate') .describe( "Filters search results for adult content. The following values are supported: 'off' - No filtering. 'moderate' - Filters explicit content (e.g., images and videos), but allows adult domains in search results. 'strict' - Drops all adult content from search results. The default value is 'moderate'." ) .optional(), freshness: z .enum(['pd', 'pw', 'pm', 'py', 'YYYY-MM-DDtoYYYY-MM-DD']) .describe( "Filters search results by when they were discovered. The following values are supported: 'pd' - Discovered within the last 24 hours. 'pw' - Discovered within the last 7 days. 'pm' - Discovered within the last 31 days. 'py' - Discovered within the last 365 days. 'YYYY-MM-DDtoYYYY-MM-DD' - Timeframe is also supported by specifying the date range e.g. 2022-04-01to2022-07-30." ) .optional(), text_decorations: z .boolean() .default(true) .describe( 'Whether display strings (e.g. result snippets) should include decoration markers (e.g. highlighting characters).' ) .optional(), spellcheck: z .boolean() .default(true) .describe('Whether to spellcheck the provided query.') .optional(), result_filter: z .array( z.enum([ 'discussions', 'faq', 'infobox', 'news', 'query', 'summarizer', 'videos', 'web', 'locations', 'rich', ]) ) .default(['web', 'query']) .describe("Result filter (default ['web', 'query'])") .optional(), goggles: z .array(z.string()) .describe( "Goggles act as a custom re-ranking on top of Brave's search index. The parameter supports both a url where the Goggle is hosted or the definition of the Goggle. For more details, refer to the Goggles repository (i.e., https://github.com/brave/goggles-quickstart)." ) .optional(), units: z .union([z.literal('metric'), z.literal('imperial')]) .describe('The measurement units. If not provided, units are derived from search country.') .optional(), extra_snippets: z .boolean() .describe( 'A snippet is an excerpt from a page you get as a result of the query, and extra_snippets allow you to get up to 5 additional, alternative excerpts. Only available under Free AI, Base AI, Pro AI, Base Data, Pro Data and Custom plans.' ) .optional(), summary: z .boolean() .describe( 'This parameter enables summary key generation in web search results. This is required for summarizer to be enabled.' ) .optional(), });
  • Registration function for the brave_web_search tool, called by the server to register it with the MCP server using the tool's name, description, input schema from params, annotations, and the execute handler.
    export const register = (mcpServer: McpServer) => { mcpServer.registerTool( name, { title: name, description: description, inputSchema: params.shape, annotations: annotations, }, execute ); };
  • Helper function to format raw web search results into a standardized FormattedWebResults array used in the handler.
    export const formatWebResults = (web: Search): FormattedWebResults => { return (web.results || []).map(({ url, title, description, extra_snippets }) => ({ url, title, description, extra_snippets, })); };
  • src/server.ts:30-34 (registration)
    Top-level registration loop in the MCP server creation that calls register() on all tools, including brave_web_search via WebSearchTool.
    for (const tool of Object.values(tools)) { // The user may have enabled/disabled this tool at runtime if (!isToolPermittedByUser(tool.name)) continue; tool.register(mcpServer); }

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

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