├── .gitignore ├── LICENSE ├── README.md └── perplexity-ask ├── Dockerfile ├── assets ├── available_tools.png ├── cursor-mcp-directory.png ├── cursor-settings.png ├── demo_screenshot.png ├── perplexity-ask-mcp-cursor.png ├── system_architecture.png └── visual-indicator-mcp-tools.png ├── index.ts ├── package-lock.json ├── package.json └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore macOS system files 2 | .DS_Store 3 | 4 | # Ignore Python compiled files 5 | __pycache__/ 6 | *.py[cod] 7 | *$py.class 8 | 9 | # Ignore Jupyter Notebook checkpoints 10 | .ipynb_checkpoints/ 11 | 12 | # Ignore virtual environments 13 | venv/ 14 | .env/ 15 | *.env 16 | 17 | # Ignore log files 18 | *.log 19 | *.out 20 | *.err 21 | 22 | # Ignore database and cache files 23 | *.sqlite3 24 | *.db 25 | *.cache 26 | 27 | # Ignore IDE specific files 28 | .idea/ 29 | .vscode/ 30 | *.swp 31 | *.swo 32 | 33 | # Ignore dependency and build artifacts 34 | node_modules/ 35 | npm-debug.log 36 | yarn-error.log 37 | 38 | # Ignore coverage and test reports 39 | .coverage 40 | coverage.xml 41 | *.cover 42 | *.pyc 43 | 44 | # Ignore system-specific files 45 | Thumbs.db 46 | Desktop.ini 47 | 48 | # Ignore CSV and large data files 49 | *.csv 50 | *.tsv 51 | *.jsonl 52 | : 53 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 perplexity 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Perplexity Ask MCP Server 2 | 3 | An MCP server implementation that integrates the Sonar API to provide Claude with unparalleled real-time, web-wide research. 4 | 5 | Please refer to the official [DeepWiki page](https://deepwiki.com/ppl-ai/modelcontextprotocol) for assistance with implementation. 6 | 7 | # High-level System Architecture 8 | 9 | *Credits: DeepWiki powered by Devin* 10 | 11 | ![System Architecture](perplexity-ask/assets/system_architecture.png) 12 | 13 | 14 | 15 | 16 | 17 | ![Demo](perplexity-ask/assets/demo_screenshot.png) 18 | 19 | 20 | ## Tools 21 | 22 | - **perplexity_ask** 23 | - Engage in a conversation with the Sonar API for live web searches. 24 | - **Inputs:** 25 | - `messages` (array): An array of conversation messages. 26 | - Each message must include: 27 | - `role` (string): The role of the message (e.g., `system`, `user`, `assistant`). 28 | - `content` (string): The content of the message. 29 | 30 | ## Configuration 31 | 32 | ### Step 1: 33 | 34 | Clone this repository: 35 | 36 | ```bash 37 | git clone git@github.com:ppl-ai/modelcontextprotocol.git 38 | ``` 39 | 40 | Navigate to the `perplexity-ask` directory and install the necessary dependencies: 41 | 42 | ```bash 43 | cd modelcontextprotocol/perplexity-ask && npm install 44 | ``` 45 | 46 | ### Step 2: Get a Sonar API Key 47 | 48 | 1. Sign up for a [Sonar API account](https://docs.perplexity.ai/guides/getting-started). 49 | 2. Follow the account setup instructions and generate your API key from the developer dashboard. 50 | 3. Set the API key in your environment as `PERPLEXITY_API_KEY`. 51 | 52 | ### Step 3: Configure Claude Desktop 53 | 54 | 1. Download Claude desktop [here](https://claude.ai/download). 55 | 56 | 2. Add this to your `claude_desktop_config.json`: 57 | 58 | ```json 59 | { 60 | "mcpServers": { 61 | "perplexity-ask": { 62 | "command": "docker", 63 | "args": [ 64 | "run", 65 | "-i", 66 | "--rm", 67 | "-e", 68 | "PERPLEXITY_API_KEY", 69 | "mcp/perplexity-ask" 70 | ], 71 | "env": { 72 | "PERPLEXITY_API_KEY": "YOUR_API_KEY_HERE" 73 | } 74 | } 75 | } 76 | } 77 | ``` 78 | 79 | ### NPX 80 | 81 | ```json 82 | { 83 | "mcpServers": { 84 | "perplexity-ask": { 85 | "command": "npx", 86 | "args": [ 87 | "-y", 88 | "server-perplexity-ask" 89 | ], 90 | "env": { 91 | "PERPLEXITY_API_KEY": "YOUR_API_KEY_HERE" 92 | } 93 | } 94 | } 95 | } 96 | ``` 97 | 98 | You can access the file using: 99 | 100 | ```bash 101 | vim ~/Library/Application\ Support/Claude/claude_desktop_config.json 102 | ``` 103 | 104 | ### Step 4: Build the Docker Image 105 | 106 | Docker build: 107 | 108 | ```bash 109 | docker build -t mcp/perplexity-ask:latest -f Dockerfile . 110 | ``` 111 | 112 | ### Step 5: Testing 113 | 114 | Let's make sure Claude for Desktop is picking up the two tools we've exposed in our `perplexity-ask` server. You can do this by looking for the hammer icon: 115 | 116 | ![Claude Visual Tools](perplexity-ask/assets/visual-indicator-mcp-tools.png) 117 | 118 | After clicking on the hammer icon, you should see the tools that come with the Filesystem MCP Server: 119 | 120 | ![Available Integration](perplexity-ask/assets/available_tools.png) 121 | 122 | If you see both of these this means that the integration is active. Congratulations! This means Claude can now ask Perplexity. You can then simply use it as you would use the Perplexity web app. 123 | 124 | ### Step 6: Advanced parameters 125 | 126 | Currently, the search parameters used are the default ones. You can modify any search parameter in the API call directly in the `index.ts` script. For this, please refer to the official [API documentation](https://docs.perplexity.ai/api-reference/chat-completions). 127 | 128 | ### Troubleshooting 129 | 130 | The Claude documentation provides an excellent [troubleshooting guide](https://modelcontextprotocol.io/docs/tools/debugging) you can refer to. However, you can still reach out to us at api@perplexity.ai for any additional support or [file a bug](https://github.com/ppl-ai/api-discussion/issues). 131 | 132 | 133 | # Cursor integration 134 | 135 | You can also use our MCP with Cursor (or any other app that supports this). To use Sonar with Cursor, you can follow the following steps. 136 | 137 | ### Step 1: Navigate to your Cursor settings: 138 | 139 | ![Cursor Settings](perplexity-ask/assets/cursor-settings.png) 140 | 141 | ### Step 2: Navigate to the MCP directory 142 | 143 | And click on `Add new global MCP server` 144 | 145 | ![Add Server](perplexity-ask/assets/cursor-mcp-directory.png) 146 | 147 | 148 | ### Step 3: Insert the MCP Server Configuration from above 149 | 150 | This is the same configuration you would use for any other application that supports MCP. 151 | 152 | You should then see the application being part of your available tools like this: 153 | 154 | ![Cursor MCP](perplexity-ask/assets/perplexity-ask-mcp-cursor.png) 155 | 156 | 157 | ## License 158 | 159 | This MCP server is licensed under the MIT License. This means you are free to use, modify, and distribute the software, subject to the terms and conditions of the MIT License. For more details, please see the LICENSE file in the project repository. 160 | 161 | -------------------------------------------------------------------------------- /perplexity-ask/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:22.12-alpine AS builder 2 | 3 | COPY . /app 4 | 5 | WORKDIR /app 6 | 7 | RUN --mount=type=cache,target=/root/.npm npm install 8 | 9 | FROM node:22-alpine AS release 10 | 11 | WORKDIR /app 12 | 13 | COPY --from=builder /app/dist /app/dist 14 | COPY --from=builder /app/package.json /app/package.json 15 | COPY --from=builder /app/package-lock.json /app/package-lock.json 16 | 17 | ENV NODE_ENV=production 18 | 19 | RUN npm ci --ignore-scripts --omit-dev 20 | 21 | ENTRYPOINT ["node", "dist/index.js"] 22 | -------------------------------------------------------------------------------- /perplexity-ask/assets/available_tools.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ppl-ai/modelcontextprotocol/332deaf8e6f51fdcfefe0a35b6fa3b777e246038/perplexity-ask/assets/available_tools.png -------------------------------------------------------------------------------- /perplexity-ask/assets/cursor-mcp-directory.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ppl-ai/modelcontextprotocol/332deaf8e6f51fdcfefe0a35b6fa3b777e246038/perplexity-ask/assets/cursor-mcp-directory.png -------------------------------------------------------------------------------- /perplexity-ask/assets/cursor-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ppl-ai/modelcontextprotocol/332deaf8e6f51fdcfefe0a35b6fa3b777e246038/perplexity-ask/assets/cursor-settings.png -------------------------------------------------------------------------------- /perplexity-ask/assets/demo_screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ppl-ai/modelcontextprotocol/332deaf8e6f51fdcfefe0a35b6fa3b777e246038/perplexity-ask/assets/demo_screenshot.png -------------------------------------------------------------------------------- /perplexity-ask/assets/perplexity-ask-mcp-cursor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ppl-ai/modelcontextprotocol/332deaf8e6f51fdcfefe0a35b6fa3b777e246038/perplexity-ask/assets/perplexity-ask-mcp-cursor.png -------------------------------------------------------------------------------- /perplexity-ask/assets/system_architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ppl-ai/modelcontextprotocol/332deaf8e6f51fdcfefe0a35b6fa3b777e246038/perplexity-ask/assets/system_architecture.png -------------------------------------------------------------------------------- /perplexity-ask/assets/visual-indicator-mcp-tools.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ppl-ai/modelcontextprotocol/332deaf8e6f51fdcfefe0a35b6fa3b777e246038/perplexity-ask/assets/visual-indicator-mcp-tools.png -------------------------------------------------------------------------------- /perplexity-ask/index.ts: -------------------------------------------------------------------------------- 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 | Tool, 9 | } from "@modelcontextprotocol/sdk/types.js"; 10 | 11 | /** 12 | * Definition of the Perplexity Ask Tool. 13 | * This tool accepts an array of messages and returns a chat completion response 14 | * from the Perplexity API, with citations appended to the message if provided. 15 | */ 16 | const PERPLEXITY_ASK_TOOL: Tool = { 17 | name: "perplexity_ask", 18 | description: 19 | "Engages in a conversation using the Sonar API. " + 20 | "Accepts an array of messages (each with a role and content) " + 21 | "and returns a ask completion response from the Perplexity model.", 22 | inputSchema: { 23 | type: "object", 24 | properties: { 25 | messages: { 26 | type: "array", 27 | items: { 28 | type: "object", 29 | properties: { 30 | role: { 31 | type: "string", 32 | description: "Role of the message (e.g., system, user, assistant)", 33 | }, 34 | content: { 35 | type: "string", 36 | description: "The content of the message", 37 | }, 38 | }, 39 | required: ["role", "content"], 40 | }, 41 | description: "Array of conversation messages", 42 | }, 43 | }, 44 | required: ["messages"], 45 | }, 46 | }; 47 | 48 | /** 49 | * Definition of the Perplexity Research Tool. 50 | * This tool performs deep research queries using the Perplexity API. 51 | */ 52 | const PERPLEXITY_RESEARCH_TOOL: Tool = { 53 | name: "perplexity_research", 54 | description: 55 | "Performs deep research using the Perplexity API. " + 56 | "Accepts an array of messages (each with a role and content) " + 57 | "and returns a comprehensive research response with citations.", 58 | inputSchema: { 59 | type: "object", 60 | properties: { 61 | messages: { 62 | type: "array", 63 | items: { 64 | type: "object", 65 | properties: { 66 | role: { 67 | type: "string", 68 | description: "Role of the message (e.g., system, user, assistant)", 69 | }, 70 | content: { 71 | type: "string", 72 | description: "The content of the message", 73 | }, 74 | }, 75 | required: ["role", "content"], 76 | }, 77 | description: "Array of conversation messages", 78 | }, 79 | }, 80 | required: ["messages"], 81 | }, 82 | }; 83 | 84 | /** 85 | * Definition of the Perplexity Reason Tool. 86 | * This tool performs reasoning queries using the Perplexity API. 87 | */ 88 | const PERPLEXITY_REASON_TOOL: Tool = { 89 | name: "perplexity_reason", 90 | description: 91 | "Performs reasoning tasks using the Perplexity API. " + 92 | "Accepts an array of messages (each with a role and content) " + 93 | "and returns a well-reasoned response using the sonar-reasoning-pro model.", 94 | inputSchema: { 95 | type: "object", 96 | properties: { 97 | messages: { 98 | type: "array", 99 | items: { 100 | type: "object", 101 | properties: { 102 | role: { 103 | type: "string", 104 | description: "Role of the message (e.g., system, user, assistant)", 105 | }, 106 | content: { 107 | type: "string", 108 | description: "The content of the message", 109 | }, 110 | }, 111 | required: ["role", "content"], 112 | }, 113 | description: "Array of conversation messages", 114 | }, 115 | }, 116 | required: ["messages"], 117 | }, 118 | }; 119 | 120 | // Retrieve the Perplexity API key from environment variables 121 | const PERPLEXITY_API_KEY = process.env.PERPLEXITY_API_KEY; 122 | if (!PERPLEXITY_API_KEY) { 123 | console.error("Error: PERPLEXITY_API_KEY environment variable is required"); 124 | process.exit(1); 125 | } 126 | 127 | /** 128 | * Performs a chat completion by sending a request to the Perplexity API. 129 | * Appends citations to the returned message content if they exist. 130 | * 131 | * @param {Array<{ role: string; content: string }>} messages - An array of message objects. 132 | * @param {string} model - The model to use for the completion. 133 | * @returns {Promise} The chat completion result with appended citations. 134 | * @throws Will throw an error if the API request fails. 135 | */ 136 | async function performChatCompletion( 137 | messages: Array<{ role: string; content: string }>, 138 | model: string = "sonar-pro" 139 | ): Promise { 140 | // Construct the API endpoint URL and request body 141 | const url = new URL("https://api.perplexity.ai/chat/completions"); 142 | const body = { 143 | model: model, // Model identifier passed as parameter 144 | messages: messages, 145 | // Additional parameters can be added here if required (e.g., max_tokens, temperature, etc.) 146 | // See the Sonar API documentation for more details: 147 | // https://docs.perplexity.ai/api-reference/chat-completions 148 | }; 149 | 150 | let response; 151 | try { 152 | response = await fetch(url.toString(), { 153 | method: "POST", 154 | headers: { 155 | "Content-Type": "application/json", 156 | "Authorization": `Bearer ${PERPLEXITY_API_KEY}`, 157 | }, 158 | body: JSON.stringify(body), 159 | }); 160 | } catch (error) { 161 | throw new Error(`Network error while calling Perplexity API: ${error}`); 162 | } 163 | 164 | // Check for non-successful HTTP status 165 | if (!response.ok) { 166 | let errorText; 167 | try { 168 | errorText = await response.text(); 169 | } catch (parseError) { 170 | errorText = "Unable to parse error response"; 171 | } 172 | throw new Error( 173 | `Perplexity API error: ${response.status} ${response.statusText}\n${errorText}` 174 | ); 175 | } 176 | 177 | // Attempt to parse the JSON response from the API 178 | let data; 179 | try { 180 | data = await response.json(); 181 | } catch (jsonError) { 182 | throw new Error(`Failed to parse JSON response from Perplexity API: ${jsonError}`); 183 | } 184 | 185 | // Directly retrieve the main message content from the response 186 | let messageContent = data.choices[0].message.content; 187 | 188 | // If citations are provided, append them to the message content 189 | if (data.citations && Array.isArray(data.citations) && data.citations.length > 0) { 190 | messageContent += "\n\nCitations:\n"; 191 | data.citations.forEach((citation: string, index: number) => { 192 | messageContent += `[${index + 1}] ${citation}\n`; 193 | }); 194 | } 195 | 196 | return messageContent; 197 | } 198 | 199 | // Initialize the server with tool metadata and capabilities 200 | const server = new Server( 201 | { 202 | name: "example-servers/perplexity-ask", 203 | version: "0.1.0", 204 | }, 205 | { 206 | capabilities: { 207 | tools: {}, 208 | }, 209 | } 210 | ); 211 | 212 | /** 213 | * Registers a handler for listing available tools. 214 | * When the client requests a list of tools, this handler returns all available Perplexity tools. 215 | */ 216 | server.setRequestHandler(ListToolsRequestSchema, async () => ({ 217 | tools: [PERPLEXITY_ASK_TOOL, PERPLEXITY_RESEARCH_TOOL, PERPLEXITY_REASON_TOOL], 218 | })); 219 | 220 | /** 221 | * Registers a handler for calling a specific tool. 222 | * Processes requests by validating input and invoking the appropriate tool. 223 | * 224 | * @param {object} request - The incoming tool call request. 225 | * @returns {Promise} The response containing the tool's result or an error. 226 | */ 227 | server.setRequestHandler(CallToolRequestSchema, async (request) => { 228 | try { 229 | const { name, arguments: args } = request.params; 230 | if (!args) { 231 | throw new Error("No arguments provided"); 232 | } 233 | switch (name) { 234 | case "perplexity_ask": { 235 | if (!Array.isArray(args.messages)) { 236 | throw new Error("Invalid arguments for perplexity_ask: 'messages' must be an array"); 237 | } 238 | // Invoke the chat completion function with the provided messages 239 | const messages = args.messages; 240 | const result = await performChatCompletion(messages, "sonar-pro"); 241 | return { 242 | content: [{ type: "text", text: result }], 243 | isError: false, 244 | }; 245 | } 246 | case "perplexity_research": { 247 | if (!Array.isArray(args.messages)) { 248 | throw new Error("Invalid arguments for perplexity_research: 'messages' must be an array"); 249 | } 250 | // Invoke the chat completion function with the provided messages using the deep research model 251 | const messages = args.messages; 252 | const result = await performChatCompletion(messages, "sonar-deep-research"); 253 | return { 254 | content: [{ type: "text", text: result }], 255 | isError: false, 256 | }; 257 | } 258 | case "perplexity_reason": { 259 | if (!Array.isArray(args.messages)) { 260 | throw new Error("Invalid arguments for perplexity_reason: 'messages' must be an array"); 261 | } 262 | // Invoke the chat completion function with the provided messages using the reasoning model 263 | const messages = args.messages; 264 | const result = await performChatCompletion(messages, "sonar-reasoning-pro"); 265 | return { 266 | content: [{ type: "text", text: result }], 267 | isError: false, 268 | }; 269 | } 270 | default: 271 | // Respond with an error if an unknown tool is requested 272 | return { 273 | content: [{ type: "text", text: `Unknown tool: ${name}` }], 274 | isError: true, 275 | }; 276 | } 277 | } catch (error) { 278 | // Return error details in the response 279 | return { 280 | content: [ 281 | { 282 | type: "text", 283 | text: `Error: ${error instanceof Error ? error.message : String(error)}`, 284 | }, 285 | ], 286 | isError: true, 287 | }; 288 | } 289 | }); 290 | 291 | /** 292 | * Initializes and runs the server using standard I/O for communication. 293 | * Logs an error and exits if the server fails to start. 294 | */ 295 | async function runServer() { 296 | try { 297 | const transport = new StdioServerTransport(); 298 | await server.connect(transport); 299 | console.error("Perplexity MCP Server running on stdio with Ask, Research, and Reason tools"); 300 | } catch (error) { 301 | console.error("Fatal error running server:", error); 302 | process.exit(1); 303 | } 304 | } 305 | 306 | // Start the server and catch any startup errors 307 | runServer().catch((error) => { 308 | console.error("Fatal error running server:", error); 309 | process.exit(1); 310 | }); 311 | -------------------------------------------------------------------------------- /perplexity-ask/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@modelcontextprotocol/server-perplexity-ask", 3 | "version": "0.1.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "@modelcontextprotocol/server-perplexity-ask", 9 | "version": "0.1.0", 10 | "license": "MIT", 11 | "dependencies": { 12 | "@modelcontextprotocol/sdk": "^1.0.1" 13 | }, 14 | "bin": { 15 | "mcp-server-perplexity-ask": "dist/index.js" 16 | }, 17 | "devDependencies": { 18 | "@types/node": "^22", 19 | "shx": "^0.3.4", 20 | "typescript": "^5.6.2" 21 | } 22 | }, 23 | "node_modules/@modelcontextprotocol/sdk": { 24 | "version": "1.0.1", 25 | "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.0.1.tgz", 26 | "integrity": "sha512-slLdFaxQJ9AlRg+hw28iiTtGvShAOgOKXcD0F91nUcRYiOMuS9ZBYjcdNZRXW9G5JQ511GRTdUy1zQVZDpJ+4w==", 27 | "license": "MIT", 28 | "dependencies": { 29 | "content-type": "^1.0.5", 30 | "raw-body": "^3.0.0", 31 | "zod": "^3.23.8" 32 | } 33 | }, 34 | "node_modules/@types/node": { 35 | "version": "22.13.9", 36 | "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.9.tgz", 37 | "integrity": "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw==", 38 | "dev": true, 39 | "license": "MIT", 40 | "dependencies": { 41 | "undici-types": "~6.20.0" 42 | } 43 | }, 44 | "node_modules/balanced-match": { 45 | "version": "1.0.2", 46 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 47 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 48 | "dev": true, 49 | "license": "MIT" 50 | }, 51 | "node_modules/brace-expansion": { 52 | "version": "1.1.11", 53 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 54 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 55 | "dev": true, 56 | "license": "MIT", 57 | "dependencies": { 58 | "balanced-match": "^1.0.0", 59 | "concat-map": "0.0.1" 60 | } 61 | }, 62 | "node_modules/bytes": { 63 | "version": "3.1.2", 64 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 65 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", 66 | "license": "MIT", 67 | "engines": { 68 | "node": ">= 0.8" 69 | } 70 | }, 71 | "node_modules/concat-map": { 72 | "version": "0.0.1", 73 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 74 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", 75 | "dev": true, 76 | "license": "MIT" 77 | }, 78 | "node_modules/content-type": { 79 | "version": "1.0.5", 80 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", 81 | "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", 82 | "license": "MIT", 83 | "engines": { 84 | "node": ">= 0.6" 85 | } 86 | }, 87 | "node_modules/depd": { 88 | "version": "2.0.0", 89 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 90 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", 91 | "license": "MIT", 92 | "engines": { 93 | "node": ">= 0.8" 94 | } 95 | }, 96 | "node_modules/fs.realpath": { 97 | "version": "1.0.0", 98 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 99 | "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", 100 | "dev": true, 101 | "license": "ISC" 102 | }, 103 | "node_modules/function-bind": { 104 | "version": "1.1.2", 105 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", 106 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", 107 | "dev": true, 108 | "license": "MIT", 109 | "funding": { 110 | "url": "https://github.com/sponsors/ljharb" 111 | } 112 | }, 113 | "node_modules/glob": { 114 | "version": "7.2.3", 115 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", 116 | "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", 117 | "deprecated": "Glob versions prior to v9 are no longer supported", 118 | "dev": true, 119 | "license": "ISC", 120 | "dependencies": { 121 | "fs.realpath": "^1.0.0", 122 | "inflight": "^1.0.4", 123 | "inherits": "2", 124 | "minimatch": "^3.1.1", 125 | "once": "^1.3.0", 126 | "path-is-absolute": "^1.0.0" 127 | }, 128 | "engines": { 129 | "node": "*" 130 | }, 131 | "funding": { 132 | "url": "https://github.com/sponsors/isaacs" 133 | } 134 | }, 135 | "node_modules/hasown": { 136 | "version": "2.0.2", 137 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", 138 | "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", 139 | "dev": true, 140 | "license": "MIT", 141 | "dependencies": { 142 | "function-bind": "^1.1.2" 143 | }, 144 | "engines": { 145 | "node": ">= 0.4" 146 | } 147 | }, 148 | "node_modules/http-errors": { 149 | "version": "2.0.0", 150 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 151 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 152 | "license": "MIT", 153 | "dependencies": { 154 | "depd": "2.0.0", 155 | "inherits": "2.0.4", 156 | "setprototypeof": "1.2.0", 157 | "statuses": "2.0.1", 158 | "toidentifier": "1.0.1" 159 | }, 160 | "engines": { 161 | "node": ">= 0.8" 162 | } 163 | }, 164 | "node_modules/iconv-lite": { 165 | "version": "0.6.3", 166 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", 167 | "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", 168 | "license": "MIT", 169 | "dependencies": { 170 | "safer-buffer": ">= 2.1.2 < 3.0.0" 171 | }, 172 | "engines": { 173 | "node": ">=0.10.0" 174 | } 175 | }, 176 | "node_modules/inflight": { 177 | "version": "1.0.6", 178 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 179 | "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", 180 | "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", 181 | "dev": true, 182 | "license": "ISC", 183 | "dependencies": { 184 | "once": "^1.3.0", 185 | "wrappy": "1" 186 | } 187 | }, 188 | "node_modules/inherits": { 189 | "version": "2.0.4", 190 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 191 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 192 | "license": "ISC" 193 | }, 194 | "node_modules/interpret": { 195 | "version": "1.4.0", 196 | "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", 197 | "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", 198 | "dev": true, 199 | "license": "MIT", 200 | "engines": { 201 | "node": ">= 0.10" 202 | } 203 | }, 204 | "node_modules/is-core-module": { 205 | "version": "2.16.1", 206 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", 207 | "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", 208 | "dev": true, 209 | "license": "MIT", 210 | "dependencies": { 211 | "hasown": "^2.0.2" 212 | }, 213 | "engines": { 214 | "node": ">= 0.4" 215 | }, 216 | "funding": { 217 | "url": "https://github.com/sponsors/ljharb" 218 | } 219 | }, 220 | "node_modules/minimatch": { 221 | "version": "3.1.2", 222 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 223 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 224 | "dev": true, 225 | "license": "ISC", 226 | "dependencies": { 227 | "brace-expansion": "^1.1.7" 228 | }, 229 | "engines": { 230 | "node": "*" 231 | } 232 | }, 233 | "node_modules/minimist": { 234 | "version": "1.2.8", 235 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", 236 | "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", 237 | "dev": true, 238 | "license": "MIT", 239 | "funding": { 240 | "url": "https://github.com/sponsors/ljharb" 241 | } 242 | }, 243 | "node_modules/once": { 244 | "version": "1.4.0", 245 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 246 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", 247 | "dev": true, 248 | "license": "ISC", 249 | "dependencies": { 250 | "wrappy": "1" 251 | } 252 | }, 253 | "node_modules/path-is-absolute": { 254 | "version": "1.0.1", 255 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 256 | "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", 257 | "dev": true, 258 | "license": "MIT", 259 | "engines": { 260 | "node": ">=0.10.0" 261 | } 262 | }, 263 | "node_modules/path-parse": { 264 | "version": "1.0.7", 265 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", 266 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", 267 | "dev": true, 268 | "license": "MIT" 269 | }, 270 | "node_modules/raw-body": { 271 | "version": "3.0.0", 272 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", 273 | "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", 274 | "license": "MIT", 275 | "dependencies": { 276 | "bytes": "3.1.2", 277 | "http-errors": "2.0.0", 278 | "iconv-lite": "0.6.3", 279 | "unpipe": "1.0.0" 280 | }, 281 | "engines": { 282 | "node": ">= 0.8" 283 | } 284 | }, 285 | "node_modules/rechoir": { 286 | "version": "0.6.2", 287 | "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", 288 | "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", 289 | "dev": true, 290 | "dependencies": { 291 | "resolve": "^1.1.6" 292 | }, 293 | "engines": { 294 | "node": ">= 0.10" 295 | } 296 | }, 297 | "node_modules/resolve": { 298 | "version": "1.22.10", 299 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", 300 | "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", 301 | "dev": true, 302 | "license": "MIT", 303 | "dependencies": { 304 | "is-core-module": "^2.16.0", 305 | "path-parse": "^1.0.7", 306 | "supports-preserve-symlinks-flag": "^1.0.0" 307 | }, 308 | "bin": { 309 | "resolve": "bin/resolve" 310 | }, 311 | "engines": { 312 | "node": ">= 0.4" 313 | }, 314 | "funding": { 315 | "url": "https://github.com/sponsors/ljharb" 316 | } 317 | }, 318 | "node_modules/safer-buffer": { 319 | "version": "2.1.2", 320 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 321 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", 322 | "license": "MIT" 323 | }, 324 | "node_modules/setprototypeof": { 325 | "version": "1.2.0", 326 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 327 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", 328 | "license": "ISC" 329 | }, 330 | "node_modules/shelljs": { 331 | "version": "0.8.5", 332 | "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", 333 | "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", 334 | "dev": true, 335 | "license": "BSD-3-Clause", 336 | "dependencies": { 337 | "glob": "^7.0.0", 338 | "interpret": "^1.0.0", 339 | "rechoir": "^0.6.2" 340 | }, 341 | "bin": { 342 | "shjs": "bin/shjs" 343 | }, 344 | "engines": { 345 | "node": ">=4" 346 | } 347 | }, 348 | "node_modules/shx": { 349 | "version": "0.3.4", 350 | "resolved": "https://registry.npmjs.org/shx/-/shx-0.3.4.tgz", 351 | "integrity": "sha512-N6A9MLVqjxZYcVn8hLmtneQWIJtp8IKzMP4eMnx+nqkvXoqinUPCbUFLp2UcWTEIUONhlk0ewxr/jaVGlc+J+g==", 352 | "dev": true, 353 | "license": "MIT", 354 | "dependencies": { 355 | "minimist": "^1.2.3", 356 | "shelljs": "^0.8.5" 357 | }, 358 | "bin": { 359 | "shx": "lib/cli.js" 360 | }, 361 | "engines": { 362 | "node": ">=6" 363 | } 364 | }, 365 | "node_modules/statuses": { 366 | "version": "2.0.1", 367 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 368 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", 369 | "license": "MIT", 370 | "engines": { 371 | "node": ">= 0.8" 372 | } 373 | }, 374 | "node_modules/supports-preserve-symlinks-flag": { 375 | "version": "1.0.0", 376 | "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", 377 | "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", 378 | "dev": true, 379 | "license": "MIT", 380 | "engines": { 381 | "node": ">= 0.4" 382 | }, 383 | "funding": { 384 | "url": "https://github.com/sponsors/ljharb" 385 | } 386 | }, 387 | "node_modules/toidentifier": { 388 | "version": "1.0.1", 389 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 390 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", 391 | "license": "MIT", 392 | "engines": { 393 | "node": ">=0.6" 394 | } 395 | }, 396 | "node_modules/typescript": { 397 | "version": "5.8.2", 398 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz", 399 | "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==", 400 | "dev": true, 401 | "license": "Apache-2.0", 402 | "bin": { 403 | "tsc": "bin/tsc", 404 | "tsserver": "bin/tsserver" 405 | }, 406 | "engines": { 407 | "node": ">=14.17" 408 | } 409 | }, 410 | "node_modules/undici-types": { 411 | "version": "6.20.0", 412 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", 413 | "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", 414 | "dev": true, 415 | "license": "MIT" 416 | }, 417 | "node_modules/unpipe": { 418 | "version": "1.0.0", 419 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 420 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", 421 | "license": "MIT", 422 | "engines": { 423 | "node": ">= 0.8" 424 | } 425 | }, 426 | "node_modules/wrappy": { 427 | "version": "1.0.2", 428 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 429 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", 430 | "dev": true, 431 | "license": "ISC" 432 | }, 433 | "node_modules/zod": { 434 | "version": "3.24.2", 435 | "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.2.tgz", 436 | "integrity": "sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==", 437 | "license": "MIT", 438 | "funding": { 439 | "url": "https://github.com/sponsors/colinhacks" 440 | } 441 | } 442 | } 443 | } 444 | -------------------------------------------------------------------------------- /perplexity-ask/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "server-perplexity-ask", 3 | "version": "0.1.0", 4 | "description": "MCP server for Perplexity API integration", 5 | "keywords": [ 6 | "ai", 7 | "perplexity", 8 | "mcp", 9 | "modelcontextprotocol" 10 | ], 11 | "homepage": "https://modelcontextprotocol.io", 12 | "bugs": { 13 | "url": "https://github.com/modelcontextprotocol/servers/issues" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/modelcontextprotocol/servers.git" 18 | }, 19 | "license": "MIT", 20 | "author": "Model Context Protocol (https://modelcontextprotocol.io)", 21 | "type": "module", 22 | "main": "dist/index.js", 23 | "bin": { 24 | "mcp-server-perplexity-ask": "dist/index.js" 25 | }, 26 | "files": [ 27 | "dist" 28 | ], 29 | "scripts": { 30 | "build": "tsc && shx chmod +x dist/*.js", 31 | "prepare": "npm run build", 32 | "watch": "tsc --watch" 33 | }, 34 | "dependencies": { 35 | "@modelcontextprotocol/sdk": "^1.0.1", 36 | "axios": "^1.6.2", 37 | "dotenv": "^16.3.1" 38 | }, 39 | "devDependencies": { 40 | "@types/node": "^20", 41 | "shx": "^0.3.4", 42 | "typescript": "^5.6.2" 43 | }, 44 | "engines": { 45 | "node": ">=18" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /perplexity-ask/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2015", 4 | "module": "ESNext", 5 | "outDir": "./dist", 6 | "rootDir": ".", 7 | "strict": true, 8 | "esModuleInterop": true, 9 | "forceConsistentCasingInFileNames": true, 10 | "skipLibCheck": true, 11 | "moduleResolution": "node" 12 | }, 13 | "include": [ 14 | "./**/*.ts" 15 | ] 16 | } 17 | --------------------------------------------------------------------------------