web_search
Search the web using multiple providers for factual, privacy-focused, or AI-enhanced results with query operators and domain filtering.
Instructions
Search the web. Providers: tavily (factual/citations), brave (privacy/operators), kagi (quality/operators), exa (AI-semantic). Brave/Kagi support query operators like site:, filetype:, lang:, etc.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Query | |
| provider | Yes | Search provider | |
| limit | No | Result limit | |
| include_domains | No | Domains to include | |
| exclude_domains | No | Domains to exclude |
Implementation Reference
- src/server/tools.ts:76-152 (handler)MCP tool registration including schema, description, and handler function for 'web_search'. The handler delegates to the registered web_search_provider's search method, handles large results, and formats the response as JSON text or error.if (this.web_search_provider) { server.tool( { name: 'web_search', description: this.web_search_provider.description, schema: v.object({ query: v.pipe(v.string(), v.description('Query')), provider: v.pipe( v.union([ v.literal('tavily'), v.literal('brave'), v.literal('kagi'), v.literal('exa'), ]), v.description('Search provider'), ), limit: v.optional( v.pipe(v.number(), v.description('Result limit')), ), include_domains: v.optional( v.pipe( v.array(v.string()), v.description('Domains to include'), ), ), exclude_domains: v.optional( v.pipe( v.array(v.string()), v.description('Domains to exclude'), ), ), }), }, async ({ query, provider, limit, include_domains, exclude_domains, }) => { try { const results = await this.web_search_provider!.search({ query, provider, limit, include_domains, exclude_domains, } as any); const safe_results = handle_large_result( results, 'web_search', ); return { content: [ { type: 'text' as const, text: JSON.stringify(safe_results, null, 2), }, ], }; } catch (error) { const error_response = create_error_response( error as Error, ); return { content: [ { type: 'text' as const, text: error_response.error, }, ], isError: true, }; } }, ); }
- src/server/tools.ts:81-107 (schema)Valibot input schema for the web_search tool defining parameters: query (required), provider (tavily|brave|kagi|exa), optional limit, include_domains, exclude_domains.schema: v.object({ query: v.pipe(v.string(), v.description('Query')), provider: v.pipe( v.union([ v.literal('tavily'), v.literal('brave'), v.literal('kagi'), v.literal('exa'), ]), v.description('Search provider'), ), limit: v.optional( v.pipe(v.number(), v.description('Result limit')), ), include_domains: v.optional( v.pipe( v.array(v.string()), v.description('Domains to include'), ), ), exclude_domains: v.optional( v.pipe( v.array(v.string()), v.description('Domains to exclude'), ), ), }),
- src/providers/index.ts:32-34 (registration)Conditional registration of the UnifiedWebSearchProvider instance to the tool registry if any web search API key is valid.if (has_web_search) { register_web_search_provider(new UnifiedWebSearchProvider()); }
- UnifiedWebSearchProvider class implementing SearchProvider. Instantiates sub-providers (Tavily, Brave, Kagi, Exa) and delegates search calls to the selected provider based on input.export class UnifiedWebSearchProvider implements SearchProvider { name = 'web_search'; description = 'Search the web. Providers: tavily (factual/citations), brave (privacy/operators), kagi (quality/operators), exa (AI-semantic). Brave/Kagi support query operators like site:, filetype:, lang:, etc.'; private providers: Map<WebSearchProvider, SearchProvider> = new Map(); constructor() { this.providers.set('tavily', new TavilySearchProvider()); this.providers.set('brave', new BraveSearchProvider()); this.providers.set('kagi', new KagiSearchProvider()); this.providers.set('exa', new ExaSearchProvider()); } async search( params: UnifiedWebSearchParams, ): Promise<SearchResult[]> { const { provider, ...searchParams } = params; if (!provider) { throw new ProviderError( ErrorType.INVALID_INPUT, 'Provider parameter is required', this.name, ); } const selectedProvider = this.providers.get(provider); if (!selectedProvider) { throw new ProviderError( ErrorType.INVALID_INPUT, `Invalid provider: ${provider}. Valid options: ${Array.from(this.providers.keys()).join(', ')}`, this.name, ); } return selectedProvider.search(searchParams); } }
- src/server/tools.ts:521-525 (registration)Function to register a SearchProvider instance (e.g., UnifiedWebSearchProvider) with the ToolRegistry for use in the web_search tool.export const register_web_search_provider = ( provider: SearchProvider, ) => { registry.register_web_search_provider(provider); };