# Directory Structure ``` ├── .github │ └── workflows │ └── node.js.yml ├── .gitignore ├── Dockerfile ├── examples │ └── deep-research.md ├── LICENSE ├── memory-bank │ ├── activeContext.md │ ├── productContext.md │ ├── progress.md │ ├── systemPatterns.md │ └── techContext.md ├── package-lock.json ├── package.json ├── README.md ├── smithery.yaml ├── src │ └── index.ts └── tsconfig.json ``` # Files -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- ``` 1 | node_modules/ 2 | build/ 3 | *.log 4 | .env* ``` -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- ```markdown 1 | # Perplexity MCP Server 2 | 3 | An intelligent research assistant powered by Perplexity's specialized AI models. Features automatic query complexity detection to route requests to the most appropriate model for optimal results. Unlike the Official server, it has search capabilities FOR EVERY TASK, essentially 4 | 5 | ## Tools 6 | 7 | **Quick Note: The Deep Research tool is going to timeout with some tools like cline, but not with others like cursor due to implementation differences, but the reason tool makes up for it.** 8 | 9 | ### 1. Search (Sonar Pro) 10 | Quick search for simple queries and basic information lookup. Best for straightforward questions that need concise, direct answers. 11 | 12 | ```javascript 13 | const result = await use_mcp_tool({ 14 | server_name: "perplexity", 15 | tool_name: "search", 16 | arguments: { 17 | query: "What is the capital of France?", 18 | force_model: false // Optional: force using this model even if query seems complex 19 | } 20 | }); 21 | ``` 22 | 23 | ### 2. Reason (Sonar Reasoning Pro) 24 | Handles complex, multi-step tasks requiring detailed analysis. Perfect for explanations, comparisons, and problem-solving. 25 | 26 | ```javascript 27 | const result = await use_mcp_tool({ 28 | server_name: "perplexity", 29 | tool_name: "reason", 30 | arguments: { 31 | query: "Compare and contrast REST and GraphQL APIs, explaining their pros and cons", 32 | force_model: false // Optional: force using this model even if query seems simple 33 | } 34 | }); 35 | ``` 36 | 37 | ### 3. Deep Research (Sonar Deep Research) 38 | Conducts comprehensive research and generates detailed reports. Ideal for in-depth analysis of complex topics. 39 | 40 | ```javascript 41 | const result = await use_mcp_tool({ 42 | server_name: "perplexity", 43 | tool_name: "deep_research", 44 | arguments: { 45 | query: "The impact of quantum computing on cryptography", 46 | focus_areas: [ 47 | "Post-quantum cryptographic algorithms", 48 | "Timeline for quantum threats", 49 | "Practical mitigation strategies" 50 | ], 51 | force_model: false // Optional: force using this model even if query seems simple 52 | } 53 | }); 54 | ``` 55 | 56 | ## Intelligent Model Selection 57 | 58 | The server automatically analyzes query complexity to route requests to the most appropriate model: 59 | 60 | 1. **Simple Queries** → Sonar Pro 61 | - Basic information lookup 62 | - Straightforward questions 63 | - Quick facts 64 | 65 | 2. **Complex Queries** → Sonar Reasoning Pro 66 | - How/why questions 67 | - Comparisons 68 | - Step-by-step explanations 69 | - Problem-solving tasks 70 | 71 | 3. **Research Queries** → Sonar Deep Research 72 | - In-depth analysis 73 | - Comprehensive research 74 | - Detailed investigations 75 | - Multi-faceted topics 76 | 77 | You can override the automatic selection using `force_model: true` in any tool's arguments. 78 | 79 | ## Setup 80 | 81 | 1. **Prerequisites** 82 | - Node.js (from [nodejs.org](https://nodejs.org)) 83 | - Perplexity API key (from [perplexity.ai/settings/api](https://www.perplexity.ai/settings/api)) 84 | - clone the repo somewhere 85 | 86 | 2. **Configure MCP Settings** 87 | 88 | Add to your MCP settings file (location varies by platform): 89 | 90 | ```json 91 | { 92 | "mcpServers": { 93 | "perplexity": { 94 | "command": "node", 95 | "args": ["/path/to/perplexity-server/build/index.js"], 96 | "env": { 97 | "PERPLEXITY_API_KEY": "YOUR_API_KEY_HERE" 98 | }, 99 | "disabled": false, 100 | "autoApprove": [] 101 | } 102 | } 103 | } 104 | ``` 105 | 106 | 107 | Or use NPX to not have to install it locally (recommended for macos): 108 | 109 | ```json 110 | { 111 | "mcpServers": { 112 | "perplexity": { 113 | "command": "npx", 114 | "args": [ 115 | "-y", 116 | "perplexity-mcp" 117 | ], 118 | "env": { 119 | "PERPLEXITY_API_KEY": "your_api_key" 120 | } 121 | } 122 | } 123 | } 124 | ``` 125 | ## Star History 126 | 127 | [](https://www.star-history.com/#DaInfernalCoder/perplexity-mcp&Timeline) 128 | ``` -------------------------------------------------------------------------------- /memory-bank/activeContext.md: -------------------------------------------------------------------------------- ```markdown 1 | # Recent Changes 2 | - Removed unused better-sqlite3 import from src/index.ts that was causing build errors 3 | - Successfully built the project after removing the dependency 4 | 5 | # Current Status 6 | - Build is now working correctly 7 | - Project is ready for further development 8 | ``` -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "compilerOptions": { 3 | "target": "ES2022", 4 | "module": "Node16", 5 | "moduleResolution": "Node16", 6 | "outDir": "./build", 7 | "rootDir": "./src", 8 | "strict": true, 9 | "esModuleInterop": true, 10 | "skipLibCheck": true, 11 | "forceConsistentCasingInFileNames": true 12 | }, 13 | "include": ["src/**/*"], 14 | "exclude": ["node_modules"] 15 | } 16 | ``` -------------------------------------------------------------------------------- /smithery.yaml: -------------------------------------------------------------------------------- ```yaml 1 | # Smithery configuration file: https://smithery.ai/docs/config#smitheryyaml 2 | 3 | startCommand: 4 | type: stdio 5 | configSchema: 6 | # JSON Schema defining the configuration options for the MCP. 7 | type: object 8 | required: 9 | - perplexityApiKey 10 | properties: 11 | perplexityApiKey: 12 | type: string 13 | description: The API key for the Perplexity API. 14 | commandFunction: 15 | # A function that produces the CLI command to start the MCP on stdio. 16 | |- 17 | (config) => ({ command: 'node', args: ['build/index.js'], env: { PERPLEXITY_API_KEY: config.perplexityApiKey } }) 18 | ``` -------------------------------------------------------------------------------- /.github/workflows/node.js.yml: -------------------------------------------------------------------------------- ```yaml 1 | # This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs 3 | 4 | name: Node.js CI 5 | 6 | on: 7 | push: 8 | branches: [ "main" ] 9 | pull_request: 10 | branches: [ "main" ] 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | strategy: 18 | matrix: 19 | node-version: [18.x, 20.x, 22.x] 20 | # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ 21 | 22 | steps: 23 | - uses: actions/checkout@v4 24 | - name: Use Node.js ${{ matrix.node-version }} 25 | uses: actions/setup-node@v4 26 | with: 27 | node-version: ${{ matrix.node-version }} 28 | cache: 'npm' 29 | - run: npm ci 30 | - run: npm run build --if-present 31 | - run: npm test 32 | ``` -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- ```dockerfile 1 | # Generated by https://smithery.ai. See: https://smithery.ai/docs/config#dockerfile 2 | # Use Node.js LTS version as the base image 3 | FROM node:18-alpine AS builder 4 | 5 | # Set the working directory 6 | WORKDIR /app 7 | 8 | # Copy package.json and package-lock.json to the working directory 9 | COPY package.json package-lock.json ./ 10 | 11 | # Install dependencies 12 | RUN npm install --ignore-scripts 13 | 14 | # Copy the rest of the application code to the working directory 15 | COPY . . 16 | 17 | # Build the TypeScript files 18 | RUN npm run build 19 | 20 | # Use a clean Node.js image for the production environment 21 | FROM node:18-alpine AS release 22 | 23 | # Set the working directory 24 | WORKDIR /app 25 | 26 | # Copy built files and node_modules from the builder stage 27 | COPY --from=builder /app/build ./build 28 | COPY --from=builder /app/node_modules ./node_modules 29 | COPY --from=builder /app/package.json ./ 30 | 31 | # Set environment variables (replace YOUR_API_KEY_HERE with the actual key) 32 | ENV PERPLEXITY_API_KEY=YOUR_API_KEY_HERE 33 | 34 | # Expose the port the app runs on 35 | EXPOSE 3000 36 | 37 | # Command to run the application 38 | ENTRYPOINT ["node", "build/index.js"] 39 | ``` -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "name": "perplexity-mcp", 3 | "version": "0.2.0", 4 | "description": "MCP server providing intelligent search, reasoning, and research capabilities powered by Perplexity's specialized AI models", 5 | "type": "module", 6 | "bin": "./build/index.js", 7 | "files": [ 8 | "build", 9 | "README.md", 10 | "LICENSE" 11 | ], 12 | "scripts": { 13 | "build": "tsc && chmod +x build/index.js", 14 | "watch": "tsc --watch", 15 | "start": "node build/index.js", 16 | "inspector": "npx @modelcontextprotocol/inspector build/index.js", 17 | "test": "tsc --noEmit", 18 | "prepublishOnly": "npm run build" 19 | }, 20 | "dependencies": { 21 | "@modelcontextprotocol/sdk": "0.6.0", 22 | "axios": "^1.7.9" 23 | }, 24 | "devDependencies": { 25 | "@types/node": "^20.11.24", 26 | "typescript": "^5.3.3" 27 | }, 28 | "keywords": [ 29 | "mcp", 30 | "perplexity", 31 | "ai", 32 | "search", 33 | "reasoning", 34 | "research", 35 | "sonar-pro", 36 | "sonar-reasoning-pro", 37 | "sonar-deep-research", 38 | "model-context-protocol" 39 | ], 40 | "author": "MCP Contributors", 41 | "license": "MIT", 42 | "repository": { 43 | "type": "git", 44 | "url": "https://github.com/DaInfernalCoder/researcher-mcp" 45 | }, 46 | "engines": { 47 | "node": ">=18.0.0" 48 | } 49 | } 50 | ``` -------------------------------------------------------------------------------- /memory-bank/progress.md: -------------------------------------------------------------------------------- ```markdown 1 | # Progress 2 | 3 | ## What Works 4 | - Server initialization and configuration 5 | - MCP protocol implementation 6 | - Intelligent query routing system 7 | - Three specialized tools implemented: 8 | - search (Sonar Pro) 9 | - reason (Sonar Reasoning Pro) 10 | - deep_research (Sonar Deep Research) 11 | - Automatic model selection based on query complexity 12 | - Manual model override with force_model flag 13 | - Build process with TypeScript 14 | - Direct Node.js execution 15 | 16 | ## Recent Updates 17 | 1. **Core Implementation** 18 | - [x] Removed chat history and SQLite 19 | - [x] Implemented query complexity detection 20 | - [x] Added specialized tool handlers 21 | - [x] Updated server version to 0.2.0 22 | 23 | 2. **Documentation** 24 | - [x] Updated README with new tools 25 | - [x] Added model selection documentation 26 | - [x] Updated setup instructions 27 | - [x] Added usage examples 28 | 29 | 3. **Memory Bank** 30 | - [x] Updated productContext.md 31 | - [x] Updated systemPatterns.md 32 | - [x] Updated techContext.md 33 | - [x] Updated activeContext.md 34 | - [x] Updated progress.md 35 | 36 | ## What's Next 37 | 1. **Testing** 38 | - [ ] Test query complexity detection 39 | - [ ] Verify model selection logic 40 | - [ ] Test each specialized tool 41 | - [ ] Validate force_model override 42 | 43 | 2. **Potential Improvements** 44 | - [ ] Expand complexity detection patterns 45 | - [ ] Add more specialized prompts per model 46 | - [ ] Enhance error messages 47 | - [ ] Add query preprocessing 48 | 49 | ## Current Status 50 | - Streamlined architecture with three specialized tools 51 | - Intelligent query routing system implemented 52 | - All documentation updated 53 | - Ready for testing and validation 54 | ``` -------------------------------------------------------------------------------- /memory-bank/techContext.md: -------------------------------------------------------------------------------- ```markdown 1 | # Technical Context 2 | 3 | ## Technologies Used 4 | 5 | ### Core Technologies 6 | - **Node.js**: Runtime environment 7 | - **TypeScript**: Type-safe development 8 | - **MCP SDK**: Server implementation 9 | - **Perplexity API**: AI model integration 10 | 11 | ### Dependencies 12 | - **@modelcontextprotocol/sdk (0.6.0)**: MCP protocol implementation 13 | - **axios (^1.7.9)**: API communication 14 | 15 | ### Development Dependencies 16 | - **@types/node (^20.11.24)**: Node.js type definitions 17 | - **typescript (^5.3.3)**: TypeScript compiler 18 | 19 | ## AI Models 20 | 1. **Sonar Pro** 21 | - Quick information retrieval 22 | - Simple query processing 23 | - Direct answers 24 | 25 | 2. **Sonar Reasoning Pro** 26 | - Complex analysis 27 | - Multi-step reasoning 28 | - Detailed explanations 29 | 30 | 3. **Sonar Deep Research** 31 | - Comprehensive research 32 | - In-depth analysis 33 | - Structured reports 34 | 35 | ## Development Setup 36 | 1. **Build Process** 37 | - TypeScript compilation 38 | - Watch mode for development 39 | - Direct Node.js execution 40 | 41 | 2. **Testing** 42 | - Type checking 43 | - MCP Inspector integration 44 | - Manual tool testing 45 | 46 | 3. **Environment Variables** 47 | - PERPLEXITY_API_KEY (required) 48 | 49 | ## Technical Constraints 50 | 1. **API Requirements** 51 | - Valid Perplexity API key 52 | - Rate limits and quotas 53 | - API availability 54 | 55 | 2. **Runtime Requirements** 56 | - Node.js environment 57 | - Local dependencies 58 | - MCP protocol support 59 | 60 | 3. **Query Processing** 61 | - Pattern-based analysis 62 | - Model selection logic 63 | - Response formatting 64 | 65 | ## Local Setup 66 | 1. **Installation** 67 | - Clone repository 68 | - Install dependencies 69 | - Build TypeScript 70 | - Configure API key 71 | 72 | 2. **Configuration** 73 | - Environment setup 74 | - MCP settings 75 | - Model selection rules 76 | 77 | 3. **Usage** 78 | - Direct Node.js execution 79 | - Tool selection 80 | - Query complexity handling 81 | ``` -------------------------------------------------------------------------------- /memory-bank/systemPatterns.md: -------------------------------------------------------------------------------- ```markdown 1 | # System Patterns 2 | 3 | ## Architecture 4 | The Perplexity Server implements a streamlined MCP architecture focused on intelligent query routing: 5 | 6 | 1. **Server Initialization** 7 | - Creates MCP server instance 8 | - Sets up API client with authentication 9 | - Registers specialized tool handlers 10 | 11 | 2. **Query Analysis System** 12 | - Pattern-based complexity detection 13 | - Intelligent model selection 14 | - Override capabilities via force_model flag 15 | 16 | 3. **Tool Specialization** 17 | - search: Quick lookups (Sonar Pro) 18 | - reason: Complex analysis (Sonar Reasoning Pro) 19 | - deep_research: Comprehensive research (Sonar Deep Research) 20 | 21 | 4. **API Integration** 22 | - Communicates with Perplexity API 23 | - Model-specific request handling 24 | - Structured response formatting 25 | 26 | ## Key Technical Decisions 27 | 28 | 1. **Intelligent Routing** 29 | - Pattern-based query analysis 30 | - Automatic model selection 31 | - Manual override capability 32 | - Optimized response quality 33 | 34 | 2. **Model Specialization** 35 | - Sonar Pro: Simple queries 36 | - Sonar Reasoning Pro: Complex analysis 37 | - Sonar Deep Research: In-depth research 38 | 39 | 3. **TypeScript Implementation** 40 | - Strong typing for tool schemas 41 | - Enhanced code reliability 42 | - Better developer experience 43 | 44 | 4. **Direct Execution** 45 | - Node.js runtime 46 | - Local dependency management 47 | - Simple configuration 48 | 49 | 5. **Error Handling** 50 | - Detailed error messages 51 | - API error conversion 52 | - Graceful shutdown 53 | - Query validation 54 | 55 | ## Communication Patterns 56 | 57 | 1. **MCP Protocol** 58 | - Stdio transport 59 | - Structured request/response 60 | - Tool schema definitions 61 | - Input validation 62 | 63 | 2. **API Communication** 64 | - RESTful endpoints 65 | - Model-specific formatting 66 | - Bearer authentication 67 | - Error handling 68 | 69 | 3. **Query Processing** 70 | - Complexity analysis 71 | - Model selection 72 | - Response formatting 73 | - Context management 74 | ``` -------------------------------------------------------------------------------- /memory-bank/productContext.md: -------------------------------------------------------------------------------- ```markdown 1 | # Product Context 2 | 3 | ## Purpose 4 | The Perplexity Server is an MCP (Model Context Protocol) server that provides intelligent research and information retrieval through specialized AI models. It automatically analyzes query complexity to route requests to the most appropriate Perplexity AI model, ensuring optimal responses for different types of queries. 5 | 6 | ## Problems Solved 7 | 1. **Query Optimization**: Automatically selects the best AI model based on query complexity 8 | 2. **Information Access**: Provides quick answers to simple questions using Sonar Pro 9 | 3. **Complex Analysis**: Handles multi-step reasoning and detailed explanations with Sonar Reasoning Pro 10 | 4. **Deep Research**: Conducts comprehensive research and analysis using Sonar Deep Research 11 | 5. **Efficiency**: Streamlines information retrieval by matching query complexity to model capabilities 12 | 13 | ## How It Works 14 | The server analyzes queries and routes them to three specialized tools: 15 | 16 | 1. **search (Sonar Pro)** 17 | - Quick information lookup 18 | - Simple factual queries 19 | - Direct, concise answers 20 | - Best for straightforward questions 21 | 22 | 2. **reason (Sonar Reasoning Pro)** 23 | - Complex problem-solving 24 | - Multi-step analysis 25 | - Comparisons and trade-offs 26 | - Detailed explanations 27 | - Best for how/why questions 28 | 29 | 3. **deep_research (Sonar Deep Research)** 30 | - Comprehensive research 31 | - In-depth analysis 32 | - Multiple perspectives 33 | - Source references 34 | - Best for complex topics 35 | 36 | The server features intelligent query analysis that automatically routes requests to the appropriate model based on complexity patterns, with manual override available through the force_model flag. 37 | 38 | ## Key Features 39 | 1. **Automatic Model Selection** 40 | - Pattern-based complexity detection 41 | - Intelligent routing to appropriate model 42 | - Override capability for manual control 43 | 44 | 2. **Specialized Response Formats** 45 | - Concise answers for simple queries 46 | - Structured analysis for complex questions 47 | - Comprehensive reports for research topics 48 | 49 | 3. **Query Analysis** 50 | - Keyword and pattern detection 51 | - Complexity assessment 52 | - Context consideration 53 | - Model-specific formatting 54 | ``` -------------------------------------------------------------------------------- /examples/deep-research.md: -------------------------------------------------------------------------------- ```markdown 1 | # Deep Research Tool 2 | 3 | The `deep_research` tool allows you to conduct comprehensive, in-depth research on complex topics using Perplexity's sonar-deep-research model. This tool is designed for situations where you need thorough analysis and detailed information beyond what a standard search can provide. 4 | 5 | ## Example Usage 6 | 7 | ```javascript 8 | const result = await use_mcp_tool({ 9 | server_name: "perplexity-ask", 10 | tool_name: "deep_research", 11 | arguments: { 12 | query: "The impact of quantum computing on cryptography", 13 | focus_areas: [ 14 | "Post-quantum cryptographic algorithms", 15 | "Timeline for quantum threats to current encryption", 16 | "Practical mitigation strategies for organizations" 17 | ] 18 | } 19 | }); 20 | 21 | console.log(result); 22 | ``` 23 | 24 | ## Parameters 25 | 26 | - `query` (required): The research query or topic to investigate in depth 27 | - `focus_areas` (optional): An array of specific aspects or areas to focus on during research 28 | - `output_format` (optional): Format of the response (text or dropdown), defaults to "text" 29 | 30 | ## Example Response 31 | 32 | The response will include a comprehensive analysis with: 33 | 34 | 1. Background and context 35 | 2. Key concepts and definitions 36 | 3. Current state of knowledge 37 | 4. Different perspectives and approaches 38 | 5. Recent developments and breakthroughs 39 | 6. Practical applications or implications 40 | 7. Challenges and limitations 41 | 8. Future directions 42 | 9. Expert opinions and consensus views 43 | 10. References to authoritative sources 44 | 45 | ## When to Use 46 | 47 | Use the `deep_research` tool when: 48 | 49 | - You need comprehensive information on complex topics 50 | - Standard search results aren't providing enough depth 51 | - You want analysis that considers multiple perspectives 52 | - You need information on cutting-edge or rapidly evolving fields 53 | - You're looking for expert consensus and authoritative sources 54 | 55 | ## Comparison with Search Tool 56 | 57 | While the `search` tool is great for quick answers and general information, the `deep_research` tool provides: 58 | 59 | - Greater depth and breadth of analysis 60 | - More comprehensive coverage of different perspectives 61 | - Better handling of complex, nuanced topics 62 | - More thorough citation of sources and expert opinions 63 | - Ability to focus on specific aspects of a broader topic 64 | ``` -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- ```typescript 1 | #!/usr/bin/env node 2 | 3 | import { Server } from "@modelcontextprotocol/sdk/server/index.js"; 4 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; 5 | import { 6 | CallToolRequestSchema, 7 | ListToolsRequestSchema, 8 | McpError, 9 | ErrorCode, 10 | } from "@modelcontextprotocol/sdk/types.js"; 11 | import axios from "axios"; 12 | import { existsSync, mkdirSync } from "fs"; 13 | import { dirname, join } from "path"; 14 | import { homedir } from "os"; 15 | 16 | const PERPLEXITY_API_KEY = process.env.PERPLEXITY_API_KEY; 17 | if (!PERPLEXITY_API_KEY) { 18 | throw new Error("PERPLEXITY_API_KEY environment variable is required"); 19 | } 20 | 21 | class PerplexityServer { 22 | private server: Server; 23 | private axiosInstance; 24 | 25 | constructor() { 26 | this.server = new Server( 27 | { 28 | name: "perplexity-server", 29 | version: "0.2.0", 30 | }, 31 | { 32 | capabilities: { 33 | tools: {}, 34 | }, 35 | } 36 | ); 37 | 38 | this.axiosInstance = axios.create({ 39 | baseURL: "https://api.perplexity.ai", 40 | headers: { 41 | "Authorization": `Bearer ${PERPLEXITY_API_KEY}`, 42 | "Content-Type": "application/json", 43 | }, 44 | }); 45 | 46 | this.setupToolHandlers(); 47 | 48 | // Error handling 49 | this.server.onerror = (error) => console.error("[MCP Error]", error); 50 | process.on("SIGINT", async () => { 51 | await this.server.close(); 52 | process.exit(0); 53 | }); 54 | } 55 | 56 | /** 57 | * Determines the complexity of a query to choose the appropriate model 58 | */ 59 | private determineQueryComplexity(query: string): "simple" | "complex" | "research" { 60 | // Check for research indicators 61 | const researchIndicators = [ 62 | "analyze", "research", "investigate", "study", "examine", "explore", 63 | "comprehensive", "detailed", "in-depth", "thorough", 64 | "compare and contrast", "evaluate", "assess" 65 | ]; 66 | 67 | // Check for complex reasoning indicators 68 | const complexIndicators = [ 69 | "how", "why", "what if", "explain", "solve", "steps to", 70 | "difference between", "compare", "which is better", 71 | "pros and cons", "advantages", "disadvantages" 72 | ]; 73 | 74 | const query_lower = query.toLowerCase(); 75 | 76 | // Check for research patterns 77 | if (researchIndicators.some(indicator => query_lower.includes(indicator))) { 78 | return "research"; 79 | } 80 | 81 | // Check for complex patterns 82 | if (complexIndicators.some(indicator => query_lower.includes(indicator))) { 83 | return "complex"; 84 | } 85 | 86 | // Default to simple if no complex/research patterns found 87 | return "simple"; 88 | } 89 | 90 | private setupToolHandlers() { 91 | this.server.setRequestHandler(ListToolsRequestSchema, async () => ({ 92 | tools: [ 93 | { 94 | name: "search", 95 | description: "Quick search for simple queries using Perplexity's Sonar Pro model. Best for straightforward questions and basic information lookup.", 96 | inputSchema: { 97 | type: "object", 98 | properties: { 99 | query: { 100 | type: "string", 101 | description: "The search query or question" 102 | }, 103 | force_model: { 104 | type: "boolean", 105 | description: "Optional: Force using this model even if query seems complex", 106 | default: false 107 | } 108 | }, 109 | required: ["query"] 110 | } 111 | }, 112 | { 113 | name: "reason", 114 | description: "Handles complex, multi-step tasks using Perplexity's Sonar Reasoning Pro model. Best for explanations, comparisons, and problem-solving.", 115 | inputSchema: { 116 | type: "object", 117 | properties: { 118 | query: { 119 | type: "string", 120 | description: "The complex query or task to reason about" 121 | }, 122 | force_model: { 123 | type: "boolean", 124 | description: "Optional: Force using this model even if query seems simple/research-oriented", 125 | default: false 126 | } 127 | }, 128 | required: ["query"] 129 | } 130 | }, 131 | { 132 | name: "deep_research", 133 | description: "Conducts in-depth analysis and generates detailed reports using Perplexity's Sonar Deep Research model. Best for comprehensive research topics.", 134 | inputSchema: { 135 | type: "object", 136 | properties: { 137 | query: { 138 | type: "string", 139 | description: "The research topic or question to investigate in depth" 140 | }, 141 | focus_areas: { 142 | type: "array", 143 | items: { 144 | type: "string" 145 | }, 146 | description: "Optional: Specific aspects or areas to focus on" 147 | }, 148 | force_model: { 149 | type: "boolean", 150 | description: "Optional: Force using this model even if query seems simple", 151 | default: false 152 | } 153 | }, 154 | required: ["query"] 155 | } 156 | } 157 | ] 158 | })); 159 | 160 | this.server.setRequestHandler(CallToolRequestSchema, async (request) => { 161 | try { 162 | const { query, force_model = false } = request.params.arguments as { 163 | query: string; 164 | force_model?: boolean; 165 | }; 166 | 167 | // Determine which model to use based on query complexity 168 | let selectedTool = request.params.name; 169 | if (!force_model && selectedTool === "search") { 170 | const complexity = this.determineQueryComplexity(query); 171 | if (complexity === "complex") { 172 | selectedTool = "reason"; 173 | } else if (complexity === "research") { 174 | selectedTool = "deep_research"; 175 | } 176 | } 177 | 178 | let model: string; 179 | let prompt: string; 180 | 181 | switch (selectedTool) { 182 | case "search": { 183 | model = "sonar-pro"; 184 | prompt = `Provide a clear, concise answer to: ${query}`; 185 | break; 186 | } 187 | 188 | case "reason": { 189 | model = "sonar-reasoning-pro"; 190 | prompt = `Provide a detailed explanation and analysis for: ${query}. Include: 191 | 1. Step-by-step reasoning 192 | 2. Key considerations 193 | 3. Relevant examples 194 | 4. Practical implications 195 | 5. Potential alternatives`; 196 | break; 197 | } 198 | 199 | case "deep_research": { 200 | model = "sonar-deep-research"; 201 | const { focus_areas = [] } = request.params.arguments as { focus_areas?: string[] }; 202 | 203 | prompt = `Conduct comprehensive research on: ${query}`; 204 | 205 | if (focus_areas.length > 0) { 206 | prompt += `\n\nFocus areas:\n${focus_areas.map((area, i) => `${i + 1}. ${area}`).join('\n')}`; 207 | } 208 | 209 | prompt += `\n\nProvide a detailed analysis including: 210 | 1. Background and context 211 | 2. Key concepts and definitions 212 | 3. Current state of knowledge 213 | 4. Different perspectives 214 | 5. Recent developments 215 | 6. Practical applications 216 | 7. Challenges and limitations 217 | 8. Future directions 218 | 9. Expert opinions 219 | 10. References to sources`; 220 | break; 221 | } 222 | 223 | default: 224 | throw new McpError( 225 | ErrorCode.MethodNotFound, 226 | `Unknown tool: ${request.params.name}` 227 | ); 228 | } 229 | 230 | const response = await this.axiosInstance.post("/chat/completions", { 231 | model, 232 | messages: [{ role: "user", content: prompt }], 233 | }); 234 | 235 | // response.data can have a string[] .citations 236 | // these are referred to in the return text as numbered citations e.g. [1] 237 | const sourcesText = response.data.citations 238 | ? `\n\n## Sources\nPlease keep the numbered citations inline.\n${response.data.citations 239 | .map((c: string, i: number) => `${i + 1}: ${c}`) 240 | .join("\n")}` 241 | : ""; 242 | 243 | return { 244 | content: [{ 245 | type: "text", 246 | text: response.data.choices[0].message.content + sourcesText, 247 | }] 248 | }; 249 | } catch (error) { 250 | if (axios.isAxiosError(error)) { 251 | throw new McpError( 252 | ErrorCode.InternalError, 253 | `Perplexity API error: ${error.response?.data?.error?.message || error.message}` 254 | ); 255 | } 256 | throw error; 257 | } 258 | }); 259 | } 260 | 261 | async run() { 262 | const transport = new StdioServerTransport(); 263 | await this.server.connect(transport); 264 | console.error("Perplexity MCP server running on stdio"); 265 | } 266 | } 267 | 268 | const server = new PerplexityServer(); 269 | server.run().catch(console.error); 270 | ```