ai_search
Search with AI reasoning across multiple providers to find answers, analyze information, and process content through a unified interface.
Instructions
AI-powered search with reasoning. Supports perplexity (real-time + reasoning), kagi_fastgpt (quick answers), exa_answer (semantic AI).
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Query | |
| provider | Yes | AI provider | |
| limit | No | Result limit |
Implementation Reference
- src/server/tools.ts:228-283 (registration)Registration of the MCP 'ai_search' tool, including schema (query, provider: perplexity/kagi_fastgpt/exa_answer, limit) and handler that calls ai_search_provider.search() and returns JSON results or error.if (this.ai_search_provider) { server.tool( { name: 'ai_search', description: this.ai_search_provider.description, schema: v.object({ query: v.pipe(v.string(), v.description('Query')), provider: v.pipe( v.union([ v.literal('perplexity'), v.literal('kagi_fastgpt'), v.literal('exa_answer'), ]), v.description('AI provider'), ), limit: v.optional( v.pipe(v.number(), v.description('Result limit')), ), }), }, async ({ query, provider, limit }) => { try { const results = await this.ai_search_provider!.search({ query, provider, limit, } as any); const safe_results = handle_large_result( results, 'ai_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:248-281 (handler)Handler function for the 'ai_search' MCP tool. Delegates to ai_search_provider.search(), stringifies results as JSON, handles large results and errors.async ({ query, provider, limit }) => { try { const results = await this.ai_search_provider!.search({ query, provider, limit, } as any); const safe_results = handle_large_result( results, 'ai_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:233-246 (schema)Valibot input schema for 'ai_search' tool defining parameters: query (string), provider (union of 'perplexity', 'kagi_fastgpt', 'exa_answer'), optional limit (number).schema: v.object({ query: v.pipe(v.string(), v.description('Query')), provider: v.pipe( v.union([ v.literal('perplexity'), v.literal('kagi_fastgpt'), v.literal('exa_answer'), ]), v.description('AI provider'), ), limit: v.optional( v.pipe(v.number(), v.description('Result limit')), ), }),
- src/providers/index.ts:59-60 (registration)Conditional registration of UnifiedAISearchProvider as the ai_search_provider during provider initialization if relevant API keys are present.register_ai_search_provider(new UnifiedAISearchProvider()); }
- UnifiedAISearchProvider class that implements the SearchProvider interface for 'ai_search'. Instantiates and routes to sub-providers (PerplexityProvider, KagiFastGPTProvider, ExaAnswerProvider) based on the provider parameter.export class UnifiedAISearchProvider implements SearchProvider { name = 'ai_search'; description = 'AI-powered search with reasoning. Supports perplexity (real-time + reasoning), kagi_fastgpt (quick answers), exa_answer (semantic AI).'; private providers: Map<AISearchProvider, SearchProvider> = new Map(); constructor() { this.providers.set('perplexity', new PerplexityProvider()); this.providers.set('kagi_fastgpt', new KagiFastGPTProvider()); this.providers.set('exa_answer', new ExaAnswerProvider()); } async search( params: UnifiedAISearchParams, ): 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); } }