@perplexity-ai/mcp-server 0.6.0 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +2 -2
- package/README.md +3 -1
- package/dist/server.js +45 -50
- package/package.json +1 -1
|
@@ -6,14 +6,14 @@
|
|
|
6
6
|
},
|
|
7
7
|
"metadata": {
|
|
8
8
|
"description": "Official Perplexity AI plugin providing real-time web search, reasoning, and research capabilities",
|
|
9
|
-
"version": "0.6.
|
|
9
|
+
"version": "0.6.2"
|
|
10
10
|
},
|
|
11
11
|
"plugins": [
|
|
12
12
|
{
|
|
13
13
|
"name": "perplexity",
|
|
14
14
|
"source": "./",
|
|
15
15
|
"description": "Real-time web search, reasoning, and research through Perplexity's API",
|
|
16
|
-
"version": "0.6.
|
|
16
|
+
"version": "0.6.2",
|
|
17
17
|
"author": {
|
|
18
18
|
"name": "Perplexity AI",
|
|
19
19
|
"email": "api@perplexity.ai"
|
package/README.md
CHANGED
|
@@ -34,7 +34,8 @@ Advanced reasoning and problem-solving using the `sonar-reasoning-pro` model. Pe
|
|
|
34
34
|
1. Get your Perplexity API Key from the [API Portal](https://www.perplexity.ai/account/api/group)
|
|
35
35
|
2. Replace `your_key_here` in the configurations below with your API key
|
|
36
36
|
3. (Optional) Set timeout: `PERPLEXITY_TIMEOUT_MS=600000` (default: 5 minutes)
|
|
37
|
-
4. (Optional) Set
|
|
37
|
+
4. (Optional) Set custom base URL: `PERPLEXITY_BASE_URL=https://your-custom-url.com` (default: https://api.perplexity.ai)
|
|
38
|
+
5. (Optional) Set log level: `PERPLEXITY_LOG_LEVEL=DEBUG|INFO|WARN|ERROR` (default: ERROR)
|
|
38
39
|
|
|
39
40
|
### Claude Code
|
|
40
41
|
|
|
@@ -145,6 +146,7 @@ For cloud or shared deployments, run the server in HTTP mode.
|
|
|
145
146
|
| Variable | Description | Default |
|
|
146
147
|
|----------|-------------|---------|
|
|
147
148
|
| `PERPLEXITY_API_KEY` | Your Perplexity API key | *Required* |
|
|
149
|
+
| `PERPLEXITY_BASE_URL` | Custom base URL for API requests | `https://api.perplexity.ai` |
|
|
148
150
|
| `PORT` | HTTP server port | `8080` |
|
|
149
151
|
| `BIND_ADDRESS` | Network interface to bind to | `0.0.0.0` |
|
|
150
152
|
| `ALLOWED_ORIGINS` | CORS origins (comma-separated) | `*` |
|
package/dist/server.js
CHANGED
|
@@ -3,6 +3,7 @@ import { z } from "zod";
|
|
|
3
3
|
import { fetch as undiciFetch, ProxyAgent } from "undici";
|
|
4
4
|
import { ChatCompletionResponseSchema, SearchResponseSchema } from "./validation.js";
|
|
5
5
|
const PERPLEXITY_API_KEY = process.env.PERPLEXITY_API_KEY;
|
|
6
|
+
const PERPLEXITY_BASE_URL = process.env.PERPLEXITY_BASE_URL || "https://api.perplexity.ai";
|
|
6
7
|
export function getProxyUrl() {
|
|
7
8
|
return process.env.PERPLEXITY_PROXY ||
|
|
8
9
|
process.env.HTTPS_PROXY ||
|
|
@@ -48,7 +49,7 @@ export async function performChatCompletion(messages, model = "sonar-pro", strip
|
|
|
48
49
|
}
|
|
49
50
|
// Read timeout fresh each time to respect env var changes
|
|
50
51
|
const TIMEOUT_MS = parseInt(process.env.PERPLEXITY_TIMEOUT_MS || "300000", 10);
|
|
51
|
-
const url = new URL(
|
|
52
|
+
const url = new URL(`${PERPLEXITY_BASE_URL}/chat/completions`);
|
|
52
53
|
const body = {
|
|
53
54
|
model: model,
|
|
54
55
|
messages: messages,
|
|
@@ -143,7 +144,7 @@ export async function performSearch(query, maxResults = 10, maxTokensPerPage = 1
|
|
|
143
144
|
}
|
|
144
145
|
// Read timeout fresh each time to respect env var changes
|
|
145
146
|
const TIMEOUT_MS = parseInt(process.env.PERPLEXITY_TIMEOUT_MS || "300000", 10);
|
|
146
|
-
const url = new URL(
|
|
147
|
+
const url = new URL(`${PERPLEXITY_BASE_URL}/search`);
|
|
147
148
|
const body = {
|
|
148
149
|
query: query,
|
|
149
150
|
max_results: maxResults,
|
|
@@ -199,27 +200,34 @@ export async function performSearch(query, maxResults = 10, maxTokensPerPage = 1
|
|
|
199
200
|
export function createPerplexityServer(serviceOrigin) {
|
|
200
201
|
const server = new McpServer({
|
|
201
202
|
name: "io.github.perplexityai/mcp-server",
|
|
202
|
-
version: "0.6.
|
|
203
|
+
version: "0.6.2",
|
|
203
204
|
});
|
|
205
|
+
const messageSchema = z.object({
|
|
206
|
+
role: z.string().describe("Role of the message (e.g., system, user, assistant)"),
|
|
207
|
+
content: z.string().describe("The content of the message"),
|
|
208
|
+
});
|
|
209
|
+
const messagesField = z.array(messageSchema).describe("Array of conversation messages");
|
|
210
|
+
const stripThinkingField = z.boolean().optional()
|
|
211
|
+
.describe("If true, removes <think>...</think> tags and their content from the response to save context tokens. Default is false.");
|
|
212
|
+
const responseOutputSchema = {
|
|
213
|
+
response: z.string().describe("The response from Perplexity"),
|
|
214
|
+
};
|
|
215
|
+
// Input schemas
|
|
216
|
+
const messagesOnlyInputSchema = { messages: messagesField };
|
|
217
|
+
const messagesWithStripThinkingInputSchema = { messages: messagesField, strip_thinking: stripThinkingField };
|
|
204
218
|
server.registerTool("perplexity_ask", {
|
|
205
219
|
title: "Ask Perplexity",
|
|
206
220
|
description: "Engages in a conversation using the Sonar API. " +
|
|
207
221
|
"Accepts an array of messages (each with a role and content) " +
|
|
208
222
|
"and returns a chat completion response from the Perplexity model.",
|
|
209
|
-
inputSchema:
|
|
210
|
-
|
|
211
|
-
role: z.string().describe("Role of the message (e.g., system, user, assistant)"),
|
|
212
|
-
content: z.string().describe("The content of the message"),
|
|
213
|
-
})).describe("Array of conversation messages"),
|
|
214
|
-
},
|
|
215
|
-
outputSchema: {
|
|
216
|
-
response: z.string().describe("The chat completion response"),
|
|
217
|
-
},
|
|
223
|
+
inputSchema: messagesOnlyInputSchema,
|
|
224
|
+
outputSchema: responseOutputSchema,
|
|
218
225
|
annotations: {
|
|
219
226
|
readOnlyHint: true,
|
|
220
227
|
openWorldHint: true,
|
|
221
228
|
},
|
|
222
|
-
}, async (
|
|
229
|
+
}, async (args) => {
|
|
230
|
+
const { messages } = args;
|
|
223
231
|
validateMessages(messages, "perplexity_ask");
|
|
224
232
|
const result = await performChatCompletion(messages, "sonar-pro", false, serviceOrigin);
|
|
225
233
|
return {
|
|
@@ -232,22 +240,14 @@ export function createPerplexityServer(serviceOrigin) {
|
|
|
232
240
|
description: "Performs deep research using the Perplexity API. " +
|
|
233
241
|
"Accepts an array of messages (each with a role and content) " +
|
|
234
242
|
"and returns a comprehensive research response with citations.",
|
|
235
|
-
inputSchema:
|
|
236
|
-
|
|
237
|
-
role: z.string().describe("Role of the message (e.g., system, user, assistant)"),
|
|
238
|
-
content: z.string().describe("The content of the message"),
|
|
239
|
-
})).describe("Array of conversation messages"),
|
|
240
|
-
strip_thinking: z.boolean().optional()
|
|
241
|
-
.describe("If true, removes <think>...</think> tags and their content from the response to save context tokens. Default is false."),
|
|
242
|
-
},
|
|
243
|
-
outputSchema: {
|
|
244
|
-
response: z.string().describe("The research response"),
|
|
245
|
-
},
|
|
243
|
+
inputSchema: messagesWithStripThinkingInputSchema,
|
|
244
|
+
outputSchema: responseOutputSchema,
|
|
246
245
|
annotations: {
|
|
247
246
|
readOnlyHint: true,
|
|
248
247
|
openWorldHint: true,
|
|
249
248
|
},
|
|
250
|
-
}, async (
|
|
249
|
+
}, async (args) => {
|
|
250
|
+
const { messages, strip_thinking } = args;
|
|
251
251
|
validateMessages(messages, "perplexity_research");
|
|
252
252
|
const stripThinking = typeof strip_thinking === "boolean" ? strip_thinking : false;
|
|
253
253
|
const result = await performChatCompletion(messages, "sonar-deep-research", stripThinking, serviceOrigin);
|
|
@@ -261,22 +261,14 @@ export function createPerplexityServer(serviceOrigin) {
|
|
|
261
261
|
description: "Performs reasoning tasks using the Perplexity API. " +
|
|
262
262
|
"Accepts an array of messages (each with a role and content) " +
|
|
263
263
|
"and returns a well-reasoned response using the sonar-reasoning-pro model.",
|
|
264
|
-
inputSchema:
|
|
265
|
-
|
|
266
|
-
role: z.string().describe("Role of the message (e.g., system, user, assistant)"),
|
|
267
|
-
content: z.string().describe("The content of the message"),
|
|
268
|
-
})).describe("Array of conversation messages"),
|
|
269
|
-
strip_thinking: z.boolean().optional()
|
|
270
|
-
.describe("If true, removes <think>...</think> tags and their content from the response to save context tokens. Default is false."),
|
|
271
|
-
},
|
|
272
|
-
outputSchema: {
|
|
273
|
-
response: z.string().describe("The reasoning response"),
|
|
274
|
-
},
|
|
264
|
+
inputSchema: messagesWithStripThinkingInputSchema,
|
|
265
|
+
outputSchema: responseOutputSchema,
|
|
275
266
|
annotations: {
|
|
276
267
|
readOnlyHint: true,
|
|
277
268
|
openWorldHint: true,
|
|
278
269
|
},
|
|
279
|
-
}, async (
|
|
270
|
+
}, async (args) => {
|
|
271
|
+
const { messages, strip_thinking } = args;
|
|
280
272
|
validateMessages(messages, "perplexity_reason");
|
|
281
273
|
const stripThinking = typeof strip_thinking === "boolean" ? strip_thinking : false;
|
|
282
274
|
const result = await performChatCompletion(messages, "sonar-reasoning-pro", stripThinking, serviceOrigin);
|
|
@@ -285,28 +277,31 @@ export function createPerplexityServer(serviceOrigin) {
|
|
|
285
277
|
structuredContent: { response: result },
|
|
286
278
|
};
|
|
287
279
|
});
|
|
280
|
+
const searchInputSchema = {
|
|
281
|
+
query: z.string().describe("Search query string"),
|
|
282
|
+
max_results: z.number().min(1).max(20).optional()
|
|
283
|
+
.describe("Maximum number of results to return (1-20, default: 10)"),
|
|
284
|
+
max_tokens_per_page: z.number().min(256).max(2048).optional()
|
|
285
|
+
.describe("Maximum tokens to extract per webpage (default: 1024)"),
|
|
286
|
+
country: z.string().optional()
|
|
287
|
+
.describe("ISO 3166-1 alpha-2 country code for regional results (e.g., 'US', 'GB')"),
|
|
288
|
+
};
|
|
289
|
+
const searchOutputSchema = {
|
|
290
|
+
results: z.string().describe("Formatted search results"),
|
|
291
|
+
};
|
|
288
292
|
server.registerTool("perplexity_search", {
|
|
289
293
|
title: "Search the Web",
|
|
290
294
|
description: "Performs web search using the Perplexity Search API. " +
|
|
291
295
|
"Returns ranked search results with titles, URLs, snippets, and metadata. " +
|
|
292
296
|
"Perfect for finding up-to-date facts, news, or specific information.",
|
|
293
|
-
inputSchema:
|
|
294
|
-
|
|
295
|
-
max_results: z.number().min(1).max(20).optional()
|
|
296
|
-
.describe("Maximum number of results to return (1-20, default: 10)"),
|
|
297
|
-
max_tokens_per_page: z.number().min(256).max(2048).optional()
|
|
298
|
-
.describe("Maximum tokens to extract per webpage (default: 1024)"),
|
|
299
|
-
country: z.string().optional()
|
|
300
|
-
.describe("ISO 3166-1 alpha-2 country code for regional results (e.g., 'US', 'GB')"),
|
|
301
|
-
},
|
|
302
|
-
outputSchema: {
|
|
303
|
-
results: z.string().describe("Formatted search results"),
|
|
304
|
-
},
|
|
297
|
+
inputSchema: searchInputSchema,
|
|
298
|
+
outputSchema: searchOutputSchema,
|
|
305
299
|
annotations: {
|
|
306
300
|
readOnlyHint: true,
|
|
307
301
|
openWorldHint: true,
|
|
308
302
|
},
|
|
309
|
-
}, async (
|
|
303
|
+
}, async (args) => {
|
|
304
|
+
const { query, max_results, max_tokens_per_page, country } = args;
|
|
310
305
|
const maxResults = typeof max_results === "number" ? max_results : 10;
|
|
311
306
|
const maxTokensPerPage = typeof max_tokens_per_page === "number" ? max_tokens_per_page : 1024;
|
|
312
307
|
const countryCode = typeof country === "string" ? country : undefined;
|
package/package.json
CHANGED