Perplexity Deep Research MCP

#!/usr/bin/env node import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { CallToolRequestSchema, ListToolsRequestSchema, ErrorCode, McpError } from "@modelcontextprotocol/sdk/types.js"; import axios, { AxiosError } from "axios"; import dotenv from "dotenv"; // Load environment variables dotenv.config(); // Define interface for error response interface PerplexityErrorResponse { error?: string; message?: string; } export class PerplexityServer { private server: Server; private maxTokens: number = 8192; private temperature: number = 0.2; constructor() { this.server = new Server({ name: "perplexity-deep-research-server", version: "0.1.0" }, { capabilities: { tools: {} } }); this.setupHandlers(); this.setupErrorHandling(); } private setupErrorHandling(): void { this.server.onerror = (error) => { console.error("[MCP Error]", error); }; process.on('SIGINT', async () => { await this.server.close(); process.exit(0); }); } private setupHandlers(): void { // List available tools this.server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [{ name: "deep_research", description: "Perform a comprehensive web search using Perplexity's Deep Research API, which provides detailed and contextually relevant results with citations.", inputSchema: { type: "object", properties: { query: { type: "string", description: "The search query to perform" }, search_recency_filter: { type: "string", description: "Filter search results by recency (options: month, week, day, hour)", enum: ["month", "week", "day", "hour"] } }, required: ["query"] } }] }; }); // Handle tool execution this.server.setRequestHandler(CallToolRequestSchema, async (request) => { switch (request.params.name) { case "deep_research": { const { query, search_recency_filter } = request.params.arguments as { query: string; search_recency_filter?: string; }; try { const payload: any = { model: "sonar-deep-research", messages: [ { role: "user", content: query } ], max_tokens: this.maxTokens, temperature: this.temperature }; // Add optional parameters if provided if (search_recency_filter) { payload.search_recency_filter = search_recency_filter; } console.error(`Using model: sonar-deep-research, max_tokens: ${this.maxTokens}, temperature: ${this.temperature}`); const response = await axios.post('https://api.perplexity.ai/chat/completions', payload, { headers: { 'Authorization': `Bearer ${process.env.PERPLEXITY_API_KEY!}`, 'Content-Type': 'application/json' } }); // Format the response to only include content and citations const formattedResponse = { content: response.data.choices[0].message.content, citations: response.data.citations || [] }; return { content: [{ type: "text", text: JSON.stringify(formattedResponse, null, 2) }] }; } catch (error: unknown) { if (axios.isAxiosError(error)) { const axiosError = error as AxiosError<PerplexityErrorResponse>; const errorData = axiosError.response?.data; const errorMessage = errorData?.error || errorData?.message || axiosError.message; return { content: [{ type: "text", text: `Perplexity API error: ${errorMessage}` }], isError: true }; } throw error; } } default: throw new McpError( ErrorCode.MethodNotFound, `Unknown tool: ${request.params.name}` ); } }); } async run(): Promise<void> { const transport = new StdioServerTransport(); await this.server.connect(transport); console.error(`Perplexity Deep Research MCP server running on stdio`); } } // Start the server const server = new PerplexityServer(); server.run().catch(console.error);
ID: z2ghbeb8h7