@perplexity-ai/mcp-server 0.6.2 → 0.7.0
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/dist/server.js +88 -26
- 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.
|
|
9
|
+
"version": "0.7.0"
|
|
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.
|
|
16
|
+
"version": "0.7.0",
|
|
17
17
|
"author": {
|
|
18
18
|
"name": "Perplexity AI",
|
|
19
19
|
"email": "api@perplexity.ai"
|
package/dist/server.js
CHANGED
|
@@ -43,7 +43,7 @@ export function validateMessages(messages, toolName) {
|
|
|
43
43
|
export function stripThinkingTokens(content) {
|
|
44
44
|
return content.replace(/<think>[\s\S]*?<\/think>/g, '').trim();
|
|
45
45
|
}
|
|
46
|
-
export async function performChatCompletion(messages, model = "sonar-pro", stripThinking = false, serviceOrigin) {
|
|
46
|
+
export async function performChatCompletion(messages, model = "sonar-pro", stripThinking = false, serviceOrigin, options) {
|
|
47
47
|
if (!PERPLEXITY_API_KEY) {
|
|
48
48
|
throw new Error("PERPLEXITY_API_KEY environment variable is required");
|
|
49
49
|
}
|
|
@@ -53,6 +53,10 @@ export async function performChatCompletion(messages, model = "sonar-pro", strip
|
|
|
53
53
|
const body = {
|
|
54
54
|
model: model,
|
|
55
55
|
messages: messages,
|
|
56
|
+
...(options?.search_recency_filter && { search_recency_filter: options.search_recency_filter }),
|
|
57
|
+
...(options?.search_domain_filter && { search_domain_filter: options.search_domain_filter }),
|
|
58
|
+
...(options?.search_context_size && { web_search_options: { search_context_size: options.search_context_size } }),
|
|
59
|
+
...(options?.reasoning_effort && { reasoning_effort: options.reasoning_effort }),
|
|
56
60
|
};
|
|
57
61
|
const controller = new AbortController();
|
|
58
62
|
const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS);
|
|
@@ -200,36 +204,76 @@ export async function performSearch(query, maxResults = 10, maxTokensPerPage = 1
|
|
|
200
204
|
export function createPerplexityServer(serviceOrigin) {
|
|
201
205
|
const server = new McpServer({
|
|
202
206
|
name: "io.github.perplexityai/mcp-server",
|
|
203
|
-
version: "0.
|
|
207
|
+
version: "0.7.0",
|
|
208
|
+
}, {
|
|
209
|
+
instructions: "Perplexity AI server for web-grounded search, research, and reasoning. " +
|
|
210
|
+
"Use perplexity_search for finding URLs, facts, and recent news. " +
|
|
211
|
+
"Use perplexity_ask for quick AI-answered questions with citations. Supports recency filters, domain restrictions, and search context size control. " +
|
|
212
|
+
"Use perplexity_research for in-depth multi-source investigation (slow, 30s+). Supports reasoning_effort parameter to control depth. " +
|
|
213
|
+
"Use perplexity_reason for complex analysis requiring step-by-step logic. Supports recency filters, domain restrictions, and search context size control. " +
|
|
214
|
+
"All tools are read-only and access live web data.",
|
|
204
215
|
});
|
|
205
216
|
const messageSchema = z.object({
|
|
206
|
-
role: z.
|
|
217
|
+
role: z.enum(["system", "user", "assistant"]).describe("Role of the message sender"),
|
|
207
218
|
content: z.string().describe("The content of the message"),
|
|
208
219
|
});
|
|
209
220
|
const messagesField = z.array(messageSchema).describe("Array of conversation messages");
|
|
210
221
|
const stripThinkingField = z.boolean().optional()
|
|
211
222
|
.describe("If true, removes <think>...</think> tags and their content from the response to save context tokens. Default is false.");
|
|
223
|
+
const searchRecencyFilterField = z.enum(["hour", "day", "week", "month", "year"]).optional()
|
|
224
|
+
.describe("Filter search results by recency. Use 'hour' for very recent news, 'day' for today's updates, 'week' for this week, etc.");
|
|
225
|
+
const searchDomainFilterField = z.array(z.string()).optional()
|
|
226
|
+
.describe("Restrict search results to specific domains (e.g., ['wikipedia.org', 'arxiv.org']). Use '-' prefix for exclusion (e.g., ['-reddit.com']).");
|
|
227
|
+
const searchContextSizeField = z.enum(["low", "medium", "high"]).optional()
|
|
228
|
+
.describe("Controls how much web context is retrieved. 'low' (default) is fastest, 'high' provides more comprehensive results.");
|
|
229
|
+
const reasoningEffortField = z.enum(["minimal", "low", "medium", "high"]).optional()
|
|
230
|
+
.describe("Controls depth of deep research reasoning. Higher values produce more thorough analysis.");
|
|
212
231
|
const responseOutputSchema = {
|
|
213
|
-
response: z.string().describe("
|
|
232
|
+
response: z.string().describe("AI-generated text response with numbered citation references"),
|
|
214
233
|
};
|
|
215
234
|
// Input schemas
|
|
216
|
-
const messagesOnlyInputSchema = {
|
|
217
|
-
|
|
235
|
+
const messagesOnlyInputSchema = {
|
|
236
|
+
messages: messagesField,
|
|
237
|
+
search_recency_filter: searchRecencyFilterField,
|
|
238
|
+
search_domain_filter: searchDomainFilterField,
|
|
239
|
+
search_context_size: searchContextSizeField,
|
|
240
|
+
};
|
|
241
|
+
const messagesWithStripThinkingInputSchema = {
|
|
242
|
+
messages: messagesField,
|
|
243
|
+
strip_thinking: stripThinkingField,
|
|
244
|
+
search_recency_filter: searchRecencyFilterField,
|
|
245
|
+
search_domain_filter: searchDomainFilterField,
|
|
246
|
+
search_context_size: searchContextSizeField,
|
|
247
|
+
};
|
|
248
|
+
const researchInputSchema = {
|
|
249
|
+
messages: messagesField,
|
|
250
|
+
strip_thinking: stripThinkingField,
|
|
251
|
+
reasoning_effort: reasoningEffortField,
|
|
252
|
+
};
|
|
218
253
|
server.registerTool("perplexity_ask", {
|
|
219
254
|
title: "Ask Perplexity",
|
|
220
|
-
description: "
|
|
221
|
-
"
|
|
222
|
-
"
|
|
255
|
+
description: "Answer a question using web-grounded AI (Sonar Pro model). " +
|
|
256
|
+
"Best for: quick factual questions, summaries, explanations, and general Q&A. " +
|
|
257
|
+
"Returns a text response with numbered citations. Fastest and cheapest option. " +
|
|
258
|
+
"Supports filtering by recency (hour/day/week/month/year), domain restrictions, and search context size. " +
|
|
259
|
+
"For in-depth multi-source research, use perplexity_research instead. " +
|
|
260
|
+
"For step-by-step reasoning and analysis, use perplexity_reason instead.",
|
|
223
261
|
inputSchema: messagesOnlyInputSchema,
|
|
224
262
|
outputSchema: responseOutputSchema,
|
|
225
263
|
annotations: {
|
|
226
264
|
readOnlyHint: true,
|
|
227
265
|
openWorldHint: true,
|
|
266
|
+
idempotentHint: true,
|
|
228
267
|
},
|
|
229
268
|
}, async (args) => {
|
|
230
|
-
const { messages } = args;
|
|
269
|
+
const { messages, search_recency_filter, search_domain_filter, search_context_size } = args;
|
|
231
270
|
validateMessages(messages, "perplexity_ask");
|
|
232
|
-
const
|
|
271
|
+
const options = {
|
|
272
|
+
...(search_recency_filter && { search_recency_filter }),
|
|
273
|
+
...(search_domain_filter && { search_domain_filter }),
|
|
274
|
+
...(search_context_size && { search_context_size }),
|
|
275
|
+
};
|
|
276
|
+
const result = await performChatCompletion(messages, "sonar-pro", false, serviceOrigin, Object.keys(options).length > 0 ? options : undefined);
|
|
233
277
|
return {
|
|
234
278
|
content: [{ type: "text", text: result }],
|
|
235
279
|
structuredContent: { response: result },
|
|
@@ -237,20 +281,27 @@ export function createPerplexityServer(serviceOrigin) {
|
|
|
237
281
|
});
|
|
238
282
|
server.registerTool("perplexity_research", {
|
|
239
283
|
title: "Deep Research",
|
|
240
|
-
description: "
|
|
241
|
-
"
|
|
242
|
-
"
|
|
243
|
-
|
|
284
|
+
description: "Conduct deep, multi-source research on a topic (Sonar Deep Research model). " +
|
|
285
|
+
"Best for: literature reviews, comprehensive overviews, investigative queries needing " +
|
|
286
|
+
"many sources. Returns a detailed response with numbered citations. " +
|
|
287
|
+
"Significantly slower than other tools (30+ seconds). " +
|
|
288
|
+
"For quick factual questions, use perplexity_ask instead. " +
|
|
289
|
+
"For logical analysis and reasoning, use perplexity_reason instead.",
|
|
290
|
+
inputSchema: researchInputSchema,
|
|
244
291
|
outputSchema: responseOutputSchema,
|
|
245
292
|
annotations: {
|
|
246
293
|
readOnlyHint: true,
|
|
247
294
|
openWorldHint: true,
|
|
295
|
+
idempotentHint: true,
|
|
248
296
|
},
|
|
249
297
|
}, async (args) => {
|
|
250
|
-
const { messages, strip_thinking } = args;
|
|
298
|
+
const { messages, strip_thinking, reasoning_effort } = args;
|
|
251
299
|
validateMessages(messages, "perplexity_research");
|
|
252
300
|
const stripThinking = typeof strip_thinking === "boolean" ? strip_thinking : false;
|
|
253
|
-
const
|
|
301
|
+
const options = {
|
|
302
|
+
...(reasoning_effort && { reasoning_effort }),
|
|
303
|
+
};
|
|
304
|
+
const result = await performChatCompletion(messages, "sonar-deep-research", stripThinking, serviceOrigin, Object.keys(options).length > 0 ? options : undefined);
|
|
254
305
|
return {
|
|
255
306
|
content: [{ type: "text", text: result }],
|
|
256
307
|
structuredContent: { response: result },
|
|
@@ -258,20 +309,29 @@ export function createPerplexityServer(serviceOrigin) {
|
|
|
258
309
|
});
|
|
259
310
|
server.registerTool("perplexity_reason", {
|
|
260
311
|
title: "Advanced Reasoning",
|
|
261
|
-
description: "
|
|
262
|
-
"
|
|
263
|
-
"
|
|
312
|
+
description: "Analyze a question using step-by-step reasoning with web grounding (Sonar Reasoning Pro model). " +
|
|
313
|
+
"Best for: math, logic, comparisons, complex arguments, and tasks requiring chain-of-thought. " +
|
|
314
|
+
"Returns a reasoned response with numbered citations. " +
|
|
315
|
+
"Supports filtering by recency (hour/day/week/month/year), domain restrictions, and search context size. " +
|
|
316
|
+
"For quick factual questions, use perplexity_ask instead. " +
|
|
317
|
+
"For comprehensive multi-source research, use perplexity_research instead.",
|
|
264
318
|
inputSchema: messagesWithStripThinkingInputSchema,
|
|
265
319
|
outputSchema: responseOutputSchema,
|
|
266
320
|
annotations: {
|
|
267
321
|
readOnlyHint: true,
|
|
268
322
|
openWorldHint: true,
|
|
323
|
+
idempotentHint: true,
|
|
269
324
|
},
|
|
270
325
|
}, async (args) => {
|
|
271
|
-
const { messages, strip_thinking } = args;
|
|
326
|
+
const { messages, strip_thinking, search_recency_filter, search_domain_filter, search_context_size } = args;
|
|
272
327
|
validateMessages(messages, "perplexity_reason");
|
|
273
328
|
const stripThinking = typeof strip_thinking === "boolean" ? strip_thinking : false;
|
|
274
|
-
const
|
|
329
|
+
const options = {
|
|
330
|
+
...(search_recency_filter && { search_recency_filter }),
|
|
331
|
+
...(search_domain_filter && { search_domain_filter }),
|
|
332
|
+
...(search_context_size && { search_context_size }),
|
|
333
|
+
};
|
|
334
|
+
const result = await performChatCompletion(messages, "sonar-reasoning-pro", stripThinking, serviceOrigin, Object.keys(options).length > 0 ? options : undefined);
|
|
275
335
|
return {
|
|
276
336
|
content: [{ type: "text", text: result }],
|
|
277
337
|
structuredContent: { response: result },
|
|
@@ -287,18 +347,20 @@ export function createPerplexityServer(serviceOrigin) {
|
|
|
287
347
|
.describe("ISO 3166-1 alpha-2 country code for regional results (e.g., 'US', 'GB')"),
|
|
288
348
|
};
|
|
289
349
|
const searchOutputSchema = {
|
|
290
|
-
results: z.string().describe("Formatted search results"),
|
|
350
|
+
results: z.string().describe("Formatted search results, each with title, URL, snippet, and date"),
|
|
291
351
|
};
|
|
292
352
|
server.registerTool("perplexity_search", {
|
|
293
353
|
title: "Search the Web",
|
|
294
|
-
description: "
|
|
295
|
-
"
|
|
296
|
-
"
|
|
354
|
+
description: "Search the web and return a ranked list of results with titles, URLs, snippets, and dates. " +
|
|
355
|
+
"Best for: finding specific URLs, checking recent news, verifying facts, discovering sources. " +
|
|
356
|
+
"Returns formatted results (title, URL, snippet, date) — no AI synthesis. " +
|
|
357
|
+
"For AI-generated answers with citations, use perplexity_ask instead.",
|
|
297
358
|
inputSchema: searchInputSchema,
|
|
298
359
|
outputSchema: searchOutputSchema,
|
|
299
360
|
annotations: {
|
|
300
361
|
readOnlyHint: true,
|
|
301
362
|
openWorldHint: true,
|
|
363
|
+
idempotentHint: true,
|
|
302
364
|
},
|
|
303
365
|
}, async (args) => {
|
|
304
366
|
const { query, max_results, max_tokens_per_page, country } = args;
|
package/package.json
CHANGED