@perplexity-ai/mcp-server 0.8.2 → 0.8.3
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 +56 -89
- 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.8.
|
|
9
|
+
"version": "0.8.3"
|
|
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.8.
|
|
16
|
+
"version": "0.8.3",
|
|
17
17
|
"author": {
|
|
18
18
|
"name": "Perplexity AI",
|
|
19
19
|
"email": "api@perplexity.ai"
|
package/dist/server.js
CHANGED
|
@@ -43,6 +43,51 @@ 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
|
+
async function makeApiRequest(endpoint, body, serviceOrigin) {
|
|
47
|
+
if (!PERPLEXITY_API_KEY) {
|
|
48
|
+
throw new Error("PERPLEXITY_API_KEY environment variable is required");
|
|
49
|
+
}
|
|
50
|
+
// Read timeout fresh each time to respect env var changes
|
|
51
|
+
const TIMEOUT_MS = parseInt(process.env.PERPLEXITY_TIMEOUT_MS || "300000", 10);
|
|
52
|
+
const url = new URL(`${PERPLEXITY_BASE_URL}/${endpoint}`);
|
|
53
|
+
const controller = new AbortController();
|
|
54
|
+
const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS);
|
|
55
|
+
let response;
|
|
56
|
+
try {
|
|
57
|
+
const headers = {
|
|
58
|
+
"Content-Type": "application/json",
|
|
59
|
+
"Authorization": `Bearer ${PERPLEXITY_API_KEY}`,
|
|
60
|
+
};
|
|
61
|
+
if (serviceOrigin) {
|
|
62
|
+
headers["X-Service"] = serviceOrigin;
|
|
63
|
+
}
|
|
64
|
+
response = await proxyAwareFetch(url.toString(), {
|
|
65
|
+
method: "POST",
|
|
66
|
+
headers,
|
|
67
|
+
body: JSON.stringify(body),
|
|
68
|
+
signal: controller.signal,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
clearTimeout(timeoutId);
|
|
73
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
74
|
+
throw new Error(`Request timeout: Perplexity API did not respond within ${TIMEOUT_MS}ms. Consider increasing PERPLEXITY_TIMEOUT_MS.`);
|
|
75
|
+
}
|
|
76
|
+
throw new Error(`Network error while calling Perplexity API: ${error}`);
|
|
77
|
+
}
|
|
78
|
+
clearTimeout(timeoutId);
|
|
79
|
+
if (!response.ok) {
|
|
80
|
+
let errorText;
|
|
81
|
+
try {
|
|
82
|
+
errorText = await response.text();
|
|
83
|
+
}
|
|
84
|
+
catch (parseError) {
|
|
85
|
+
errorText = "Unable to parse error response";
|
|
86
|
+
}
|
|
87
|
+
throw new Error(`Perplexity API error: ${response.status} ${response.statusText}\n${errorText}`);
|
|
88
|
+
}
|
|
89
|
+
return response;
|
|
90
|
+
}
|
|
46
91
|
export async function consumeSSEStream(response) {
|
|
47
92
|
const body = response.body;
|
|
48
93
|
if (!body) {
|
|
@@ -111,13 +156,7 @@ export async function consumeSSEStream(response) {
|
|
|
111
156
|
return ChatCompletionResponseSchema.parse(assembled);
|
|
112
157
|
}
|
|
113
158
|
export async function performChatCompletion(messages, model = "sonar-pro", stripThinking = false, serviceOrigin, options) {
|
|
114
|
-
if (!PERPLEXITY_API_KEY) {
|
|
115
|
-
throw new Error("PERPLEXITY_API_KEY environment variable is required");
|
|
116
|
-
}
|
|
117
|
-
// Read timeout fresh each time to respect env var changes
|
|
118
|
-
const TIMEOUT_MS = parseInt(process.env.PERPLEXITY_TIMEOUT_MS || "300000", 10);
|
|
119
159
|
const useStreaming = model === "sonar-deep-research";
|
|
120
|
-
const url = new URL(`${PERPLEXITY_BASE_URL}/chat/completions`);
|
|
121
160
|
const body = {
|
|
122
161
|
model: model,
|
|
123
162
|
messages: messages,
|
|
@@ -127,42 +166,7 @@ export async function performChatCompletion(messages, model = "sonar-pro", strip
|
|
|
127
166
|
...(options?.search_context_size && { web_search_options: { search_context_size: options.search_context_size } }),
|
|
128
167
|
...(options?.reasoning_effort && { reasoning_effort: options.reasoning_effort }),
|
|
129
168
|
};
|
|
130
|
-
const
|
|
131
|
-
const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS);
|
|
132
|
-
let response;
|
|
133
|
-
try {
|
|
134
|
-
const headers = {
|
|
135
|
-
"Content-Type": "application/json",
|
|
136
|
-
"Authorization": `Bearer ${PERPLEXITY_API_KEY}`,
|
|
137
|
-
};
|
|
138
|
-
if (serviceOrigin) {
|
|
139
|
-
headers["X-Service"] = serviceOrigin;
|
|
140
|
-
}
|
|
141
|
-
response = await proxyAwareFetch(url.toString(), {
|
|
142
|
-
method: "POST",
|
|
143
|
-
headers,
|
|
144
|
-
body: JSON.stringify(body),
|
|
145
|
-
signal: controller.signal,
|
|
146
|
-
});
|
|
147
|
-
clearTimeout(timeoutId);
|
|
148
|
-
}
|
|
149
|
-
catch (error) {
|
|
150
|
-
clearTimeout(timeoutId);
|
|
151
|
-
if (error instanceof Error && error.name === "AbortError") {
|
|
152
|
-
throw new Error(`Request timeout: Perplexity API did not respond within ${TIMEOUT_MS}ms. Consider increasing PERPLEXITY_TIMEOUT_MS.`);
|
|
153
|
-
}
|
|
154
|
-
throw new Error(`Network error while calling Perplexity API: ${error}`);
|
|
155
|
-
}
|
|
156
|
-
if (!response.ok) {
|
|
157
|
-
let errorText;
|
|
158
|
-
try {
|
|
159
|
-
errorText = await response.text();
|
|
160
|
-
}
|
|
161
|
-
catch (parseError) {
|
|
162
|
-
errorText = "Unable to parse error response";
|
|
163
|
-
}
|
|
164
|
-
throw new Error(`Perplexity API error: ${response.status} ${response.statusText}\n${errorText}`);
|
|
165
|
-
}
|
|
169
|
+
const response = await makeApiRequest("chat/completions", body, serviceOrigin);
|
|
166
170
|
let data;
|
|
167
171
|
try {
|
|
168
172
|
if (useStreaming) {
|
|
@@ -217,54 +221,13 @@ export function formatSearchResults(data) {
|
|
|
217
221
|
return formattedResults;
|
|
218
222
|
}
|
|
219
223
|
export async function performSearch(query, maxResults = 10, maxTokensPerPage = 1024, country, serviceOrigin) {
|
|
220
|
-
if (!PERPLEXITY_API_KEY) {
|
|
221
|
-
throw new Error("PERPLEXITY_API_KEY environment variable is required");
|
|
222
|
-
}
|
|
223
|
-
// Read timeout fresh each time to respect env var changes
|
|
224
|
-
const TIMEOUT_MS = parseInt(process.env.PERPLEXITY_TIMEOUT_MS || "300000", 10);
|
|
225
|
-
const url = new URL(`${PERPLEXITY_BASE_URL}/search`);
|
|
226
224
|
const body = {
|
|
227
225
|
query: query,
|
|
228
226
|
max_results: maxResults,
|
|
229
227
|
max_tokens_per_page: maxTokensPerPage,
|
|
230
228
|
...(country && { country }),
|
|
231
229
|
};
|
|
232
|
-
const
|
|
233
|
-
const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS);
|
|
234
|
-
let response;
|
|
235
|
-
try {
|
|
236
|
-
const headers = {
|
|
237
|
-
"Content-Type": "application/json",
|
|
238
|
-
"Authorization": `Bearer ${PERPLEXITY_API_KEY}`,
|
|
239
|
-
};
|
|
240
|
-
if (serviceOrigin) {
|
|
241
|
-
headers["X-Service"] = serviceOrigin;
|
|
242
|
-
}
|
|
243
|
-
response = await proxyAwareFetch(url.toString(), {
|
|
244
|
-
method: "POST",
|
|
245
|
-
headers,
|
|
246
|
-
body: JSON.stringify(body),
|
|
247
|
-
signal: controller.signal,
|
|
248
|
-
});
|
|
249
|
-
clearTimeout(timeoutId);
|
|
250
|
-
}
|
|
251
|
-
catch (error) {
|
|
252
|
-
clearTimeout(timeoutId);
|
|
253
|
-
if (error instanceof Error && error.name === "AbortError") {
|
|
254
|
-
throw new Error(`Request timeout: Perplexity Search API did not respond within ${TIMEOUT_MS}ms. Consider increasing PERPLEXITY_TIMEOUT_MS.`);
|
|
255
|
-
}
|
|
256
|
-
throw new Error(`Network error while calling Perplexity Search API: ${error}`);
|
|
257
|
-
}
|
|
258
|
-
if (!response.ok) {
|
|
259
|
-
let errorText;
|
|
260
|
-
try {
|
|
261
|
-
errorText = await response.text();
|
|
262
|
-
}
|
|
263
|
-
catch (parseError) {
|
|
264
|
-
errorText = "Unable to parse error response";
|
|
265
|
-
}
|
|
266
|
-
throw new Error(`Perplexity Search API error: ${response.status} ${response.statusText}\n${errorText}`);
|
|
267
|
-
}
|
|
230
|
+
const response = await makeApiRequest("search", body, serviceOrigin);
|
|
268
231
|
let data;
|
|
269
232
|
try {
|
|
270
233
|
const json = await response.json();
|
|
@@ -278,7 +241,7 @@ export async function performSearch(query, maxResults = 10, maxTokensPerPage = 1
|
|
|
278
241
|
export function createPerplexityServer(serviceOrigin) {
|
|
279
242
|
const server = new McpServer({
|
|
280
243
|
name: "ai.perplexity/mcp-server",
|
|
281
|
-
version: "0.8.
|
|
244
|
+
version: "0.8.3",
|
|
282
245
|
}, {
|
|
283
246
|
instructions: "Perplexity AI server for web-grounded search, research, and reasoning. " +
|
|
284
247
|
"Use perplexity_search for finding URLs, facts, and recent news. " +
|
|
@@ -337,7 +300,8 @@ export function createPerplexityServer(serviceOrigin) {
|
|
|
337
300
|
annotations: {
|
|
338
301
|
readOnlyHint: true,
|
|
339
302
|
openWorldHint: true,
|
|
340
|
-
idempotentHint:
|
|
303
|
+
idempotentHint: false,
|
|
304
|
+
destructiveHint: false,
|
|
341
305
|
},
|
|
342
306
|
}, async (args) => {
|
|
343
307
|
const { messages, search_recency_filter, search_domain_filter, search_context_size } = args;
|
|
@@ -366,7 +330,8 @@ export function createPerplexityServer(serviceOrigin) {
|
|
|
366
330
|
annotations: {
|
|
367
331
|
readOnlyHint: true,
|
|
368
332
|
openWorldHint: true,
|
|
369
|
-
idempotentHint:
|
|
333
|
+
idempotentHint: false,
|
|
334
|
+
destructiveHint: false,
|
|
370
335
|
},
|
|
371
336
|
}, async (args) => {
|
|
372
337
|
const { messages, strip_thinking, reasoning_effort } = args;
|
|
@@ -394,7 +359,8 @@ export function createPerplexityServer(serviceOrigin) {
|
|
|
394
359
|
annotations: {
|
|
395
360
|
readOnlyHint: true,
|
|
396
361
|
openWorldHint: true,
|
|
397
|
-
idempotentHint:
|
|
362
|
+
idempotentHint: false,
|
|
363
|
+
destructiveHint: false,
|
|
398
364
|
},
|
|
399
365
|
}, async (args) => {
|
|
400
366
|
const { messages, strip_thinking, search_recency_filter, search_domain_filter, search_context_size } = args;
|
|
@@ -434,7 +400,8 @@ export function createPerplexityServer(serviceOrigin) {
|
|
|
434
400
|
annotations: {
|
|
435
401
|
readOnlyHint: true,
|
|
436
402
|
openWorldHint: true,
|
|
437
|
-
idempotentHint:
|
|
403
|
+
idempotentHint: false,
|
|
404
|
+
destructiveHint: false,
|
|
438
405
|
},
|
|
439
406
|
}, async (args) => {
|
|
440
407
|
const { query, max_results, max_tokens_per_page, country } = args;
|