search
Perform web searches with cited sources and summaries for current events, factual research, technical documentation, and comparative analysis using Perplexity AI.
Instructions
Web search via Perplexity AI with automatic model selection. Returns cited sources with summaries. The search uses only the query text (not conversation history). Best for: current events, factual research, technical documentation, comparative analysis.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Direct search query. Be specific with 2-3 context words, use expert terminology. Good: 'Compare 2025 React vs Vue performance for enterprise apps'. Bad: 'tell me about frameworks'. Tips: Use 'site:domain.com' for specific sites, include years for recent info, add 'analyze/compare/explain' for reasoning tasks. | |
| stream | No | Enable streaming responses (default: false) |
Implementation Reference
- src/handlers/SearchHandler.ts:22-133 (handler)The handle method implements the 'search' tool execution: validates input, selects appropriate Perplexity model based on query intent, applies domain/recency filters, performs API search (streaming or standard), and returns formatted response with model info and cited sources.async handle(request: McpRequest) { if (!isValidSearchArgs(request.params.arguments)) { throw ErrorHandler.createMcpError( ErrorCode.InvalidParams, "Invalid search arguments. Query must be a non-empty string." ); } const { query, stream = false } = request.params.arguments as SearchArgs; try { // Get model selection based on intent const selection = this.modelSelectionService.selectModelBasedOnIntent(query); let description: string; let selectedModel: string; // Determine which model to use if (this.useAutoSelection) { // Auto-select model based on intent selectedModel = selection.model; description = selection.description; } else { // We're using a manually set model // But check if we have a strong match that should override if (selection.score >= 2 && selection.model !== this.currentModel) { // Strong intent match - override manual selection selectedModel = selection.model; description = `${selection.description} (auto-selected based on query intent)`; } else { // Stick with manually selected model selectedModel = this.currentModel; description = this.modelSelectionService.getModelDescription(this.currentModel); } } // Get domain filters and recency filter const domainFilterArray = this.filterState.getDomainFilterArray(); const recencyFilter = this.filterState.getRecencyFilter(); // Create API parameters const apiParams = this.apiService.createApiParams( selectedModel, query, domainFilterArray.length > 0 ? domainFilterArray : undefined, recencyFilter || undefined, stream ); // Include model information at the start of responses const modelInfo = `[Using model: ${selectedModel} - ${description}]\n\n`; if (stream) { // Handle streaming response const streamResult = await this.apiService.searchStream(apiParams); let responseText = modelInfo + streamResult.content; // Add citations if available if (streamResult.search_results && streamResult.search_results.length > 0) { responseText += '\n\n## Sources\n'; streamResult.search_results.forEach((result, index) => { const dateInfo = result.date ? ` (${result.date})` : ''; responseText += `[${index + 1}] ${result.title}${dateInfo}\n${result.url}\n\n`; }); } return { content: [ { type: "text", text: responseText, }, ], }; } else { // Handle regular response const response = await this.apiService.search(apiParams); if (response.choices && response.choices.length > 0) { let responseText = modelInfo + response.choices[0].message.content; // Add citations if available if (response.search_results && response.search_results.length > 0) { responseText += '\n\n## Sources\n'; response.search_results.forEach((result, index) => { const dateInfo = result.date ? ` (${result.date})` : ''; responseText += `[${index + 1}] ${result.title}${dateInfo}\n${result.url}\n\n`; }); } return { content: [ { type: "text", text: responseText, }, ], }; } throw new Error("No response content received"); } } catch (error) { if (error instanceof Error && error.message === "No response content received") { throw error; } // Handle API errors return stream ? ErrorHandler.handleStreamingApiError(error) : ErrorHandler.handleApiError(error); } }
- src/schemas/toolSchemas.ts:8-25 (schema)Input schema definition for the 'search' tool, specifying query as required string and optional stream boolean.{ name: "search", description: "Web search via Perplexity AI with automatic model selection. Returns cited sources with summaries. The search uses only the query text (not conversation history). Best for: current events, factual research, technical documentation, comparative analysis.", inputSchema: { type: "object", properties: { query: { type: "string", description: "Direct search query. Be specific with 2-3 context words, use expert terminology. Good: 'Compare 2025 React vs Vue performance for enterprise apps'. Bad: 'tell me about frameworks'. Tips: Use 'site:domain.com' for specific sites, include years for recent info, add 'analyze/compare/explain' for reasoning tasks.", }, stream: { type: "boolean", description: "Enable streaming responses (default: false)", }, }, required: ["query"], }, },
- src/server/PerplexityMcpServer.ts:106-136 (registration)Registration of tool handlers in the MCP server's call tool request handler. The 'search' tool is dispatched to SearchHandler.handle() based on request.params.name.this.server.setRequestHandler(CallToolRequestSchema, async (request) => { // Update search handler with current model state this.searchHandler = new SearchHandler( this.apiService, this.modelSelectionService, this.filterState, this.currentModel, this.useAutoSelection ); switch (request.params.name) { case "search": return this.searchHandler.handle(request); case "domain_filter": return this.domainFilterHandler.handle(request); case "recency_filter": return this.recencyFilterHandler.handle(request); case "clear_filters": return this.filterManagementHandler.handleClearFilters(); case "list_filters": return this.filterManagementHandler.handleListFilters(); case "model_info": return this.modelInfoHandler.handle(request); default: throw new McpError( ErrorCode.MethodNotFound, `Unknown tool: ${request.params.name}` ); } }); }
- src/server/PerplexityMcpServer.ts:101-103 (registration)Registration of tool schemas via ListToolsRequestSchema handler, returning TOOL_SCHEMAS array which includes the 'search' tool schema.this.server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOL_SCHEMAS, }));