@perplexity-ai/mcp-server 0.3.1 → 0.4.1
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 +49 -0
- package/README.md +66 -2
- package/dist/index.js +102 -8
- package/dist/index.test.js +79 -0
- package/package.json +5 -3
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "perplexity-mcp-server",
|
|
3
|
+
"owner": {
|
|
4
|
+
"name": "Perplexity AI",
|
|
5
|
+
"email": "api@perplexity.ai"
|
|
6
|
+
},
|
|
7
|
+
"metadata": {
|
|
8
|
+
"description": "Official Perplexity AI plugin providing real-time web search, reasoning, and research capabilities",
|
|
9
|
+
"version": "0.4.1"
|
|
10
|
+
},
|
|
11
|
+
"plugins": [
|
|
12
|
+
{
|
|
13
|
+
"name": "perplexity",
|
|
14
|
+
"source": "./",
|
|
15
|
+
"description": "Real-time web search, reasoning, and research through Perplexity's API",
|
|
16
|
+
"version": "0.4.1",
|
|
17
|
+
"author": {
|
|
18
|
+
"name": "Perplexity AI",
|
|
19
|
+
"email": "api@perplexity.ai"
|
|
20
|
+
},
|
|
21
|
+
"homepage": "https://docs.perplexity.ai/guides/mcp-server",
|
|
22
|
+
"repository": "https://github.com/perplexityai/modelcontextprotocol",
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"keywords": [
|
|
25
|
+
"mcp",
|
|
26
|
+
"search",
|
|
27
|
+
"web-search",
|
|
28
|
+
"perplexity",
|
|
29
|
+
"research",
|
|
30
|
+
"reasoning",
|
|
31
|
+
"ai"
|
|
32
|
+
],
|
|
33
|
+
"category": "productivity",
|
|
34
|
+
"strict": false,
|
|
35
|
+
"mcpServers": {
|
|
36
|
+
"perplexity": {
|
|
37
|
+
"type": "stdio",
|
|
38
|
+
"command": "npx",
|
|
39
|
+
"args": ["-y", "@perplexity-ai/mcp-server"],
|
|
40
|
+
"env": {
|
|
41
|
+
"PERPLEXITY_API_KEY": "${PERPLEXITY_API_KEY}",
|
|
42
|
+
"PERPLEXITY_TIMEOUT_MS": "${PERPLEXITY_TIMEOUT_MS:-600000}"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
]
|
|
48
|
+
}
|
|
49
|
+
|
package/README.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Perplexity API Platform MCP Server
|
|
2
2
|
|
|
3
|
+
[](https://cursor.com/en/install-mcp?name=perplexity&config=eyJ0eXBlIjoic3RkaW8iLCJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBwZXJwbGV4aXR5LWFpL21jcC1zZXJ2ZXIiXX0=)
|
|
4
|
+
|
|
5
|
+
[](https://vscode.dev/redirect/mcp/install?name=perplexity&config=%7B%22type%22%3A%22stdio%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40perplexity-ai%2Fmcp-server%22%5D%7D)
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/@perplexity-ai/mcp-server)
|
|
8
|
+
|
|
3
9
|
The official MCP server implementation for the Perplexity API Platform, providing AI assistants with real-time web search, reasoning, and research capabilities through Sonar models and the Search API.
|
|
4
10
|
|
|
5
11
|
Please refer to the official [DeepWiki page](https://deepwiki.com/ppl-ai/modelcontextprotocol) for assistance with implementation.
|
|
@@ -18,6 +24,11 @@ Deep, comprehensive research using the `sonar-deep-research` model. Ideal for th
|
|
|
18
24
|
### **perplexity_reason**
|
|
19
25
|
Advanced reasoning and problem-solving using the `sonar-reasoning-pro` model. Perfect for complex analytical tasks.
|
|
20
26
|
|
|
27
|
+
> [!TIP]
|
|
28
|
+
> Available as an optional parameter for **perplexity_reason** and **perplexity_research**: `strip_thinking`
|
|
29
|
+
>
|
|
30
|
+
> Set to `true` to remove `<think>...</think>` tags from the response, saving context tokens. Default: `false`
|
|
31
|
+
|
|
21
32
|
## Configuration
|
|
22
33
|
|
|
23
34
|
### Get Your API Key
|
|
@@ -27,6 +38,25 @@ Advanced reasoning and problem-solving using the `sonar-reasoning-pro` model. Pe
|
|
|
27
38
|
|
|
28
39
|
### Claude Code
|
|
29
40
|
|
|
41
|
+
#### Option 1: Install via Plugin (Recommended)
|
|
42
|
+
|
|
43
|
+
The easiest way to get started with Perplexity in Claude Code:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# Add the Perplexity marketplace
|
|
47
|
+
/plugin marketplace add perplexityai/modelcontextprotocol
|
|
48
|
+
|
|
49
|
+
# Install the plugin
|
|
50
|
+
/plugin install perplexity
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Then set your API key:
|
|
54
|
+
```bash
|
|
55
|
+
export PERPLEXITY_API_KEY="your_key_here"
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
#### Option 2: Manual Configuration
|
|
59
|
+
|
|
30
60
|
Run in your terminal:
|
|
31
61
|
|
|
32
62
|
```bash
|
|
@@ -52,9 +82,9 @@ Or add to your `claude.json`:
|
|
|
52
82
|
}
|
|
53
83
|
```
|
|
54
84
|
|
|
55
|
-
### Cursor
|
|
85
|
+
### Cursor / VS Code
|
|
56
86
|
|
|
57
|
-
Add to your `mcp.json
|
|
87
|
+
Add to your `mcp.json` (Cursor) or `.vscode/mcp.json` (VS Code):
|
|
58
88
|
|
|
59
89
|
```json
|
|
60
90
|
{
|
|
@@ -71,6 +101,8 @@ Add to your `mcp.json`:
|
|
|
71
101
|
}
|
|
72
102
|
```
|
|
73
103
|
|
|
104
|
+
Or use the one-click install badges at the top of this README.
|
|
105
|
+
|
|
74
106
|
### Codex
|
|
75
107
|
|
|
76
108
|
Run in your terminal:
|
|
@@ -106,12 +138,44 @@ For any MCP-compatible client, use:
|
|
|
106
138
|
npx @perplexity-ai/mcp-server
|
|
107
139
|
```
|
|
108
140
|
|
|
141
|
+
### Proxy Setup (For Corporate Networks)
|
|
142
|
+
|
|
143
|
+
If you are running this server at work—especially behind a company firewall or proxy—you may need to tell the program how to send its internet traffic through your network's proxy. Follow these steps:
|
|
144
|
+
|
|
145
|
+
**1. Get your proxy details**
|
|
146
|
+
|
|
147
|
+
- Ask your IT department for your HTTPS proxy address and port.
|
|
148
|
+
- You may also need a username and password.
|
|
149
|
+
|
|
150
|
+
**2. Set the proxy environment variable**
|
|
151
|
+
|
|
152
|
+
The easiest and most reliable way for Perplexity MCP is to use `PERPLEXITY_PROXY`. For example:
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
export PERPLEXITY_PROXY=https://your-proxy-host:8080
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
If your proxy needs a username and password, use:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
export PERPLEXITY_PROXY=https://username:password@your-proxy-host:8080
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
**3. Alternate: Standard environment variables**
|
|
165
|
+
|
|
166
|
+
If you'd rather use the standard variables, we support `HTTPS_PROXY` and `HTTP_PROXY`.
|
|
167
|
+
|
|
168
|
+
> [!NOTE]
|
|
169
|
+
> The server checks proxy settings in this order: `PERPLEXITY_PROXY` → `HTTPS_PROXY` → `HTTP_PROXY`. If none are set, it connects directly to the internet.
|
|
170
|
+
> URLs must include `https://`. Typical ports are `8080`, `3128`, and `80`.
|
|
171
|
+
|
|
109
172
|
## Troubleshooting
|
|
110
173
|
|
|
111
174
|
- **API Key Issues**: Ensure `PERPLEXITY_API_KEY` is set correctly
|
|
112
175
|
- **Connection Errors**: Check your internet connection and API key validity
|
|
113
176
|
- **Tool Not Found**: Make sure the package is installed and the command path is correct
|
|
114
177
|
- **Timeout Errors**: For very long research queries, set `PERPLEXITY_TIMEOUT_MS` to a higher value
|
|
178
|
+
- **Proxy Issues**: Verify your `PERPLEXITY_PROXY` or `HTTPS_PROXY` setup and ensure `api.perplexity.ai` isn't blocked by your firewall.
|
|
115
179
|
|
|
116
180
|
For support, visit [community.perplexity.ai](https://community.perplexity.ai) or [file an issue](https://github.com/perplexityai/modelcontextprotocol/issues).
|
|
117
181
|
|
package/dist/index.js
CHANGED
|
@@ -11,6 +11,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
11
11
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
12
12
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
13
13
|
import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
14
|
+
import { fetch as undiciFetch, ProxyAgent } from "undici";
|
|
14
15
|
/**
|
|
15
16
|
* Definition of the Perplexity Ask Tool.
|
|
16
17
|
* This tool accepts an array of messages and returns a chat completion response
|
|
@@ -18,6 +19,7 @@ import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextpro
|
|
|
18
19
|
*/
|
|
19
20
|
const PERPLEXITY_ASK_TOOL = {
|
|
20
21
|
name: "perplexity_ask",
|
|
22
|
+
title: "Ask Perplexity",
|
|
21
23
|
description: "Engages in a conversation using the Sonar API. " +
|
|
22
24
|
"Accepts an array of messages (each with a role and content) " +
|
|
23
25
|
"and returns a ask completion response from the Perplexity model.",
|
|
@@ -45,6 +47,10 @@ const PERPLEXITY_ASK_TOOL = {
|
|
|
45
47
|
},
|
|
46
48
|
required: ["messages"],
|
|
47
49
|
},
|
|
50
|
+
annotations: {
|
|
51
|
+
readOnlyHint: true,
|
|
52
|
+
openWorldHint: true,
|
|
53
|
+
},
|
|
48
54
|
};
|
|
49
55
|
/**
|
|
50
56
|
* Definition of the Perplexity Research Tool.
|
|
@@ -52,6 +58,7 @@ const PERPLEXITY_ASK_TOOL = {
|
|
|
52
58
|
*/
|
|
53
59
|
const PERPLEXITY_RESEARCH_TOOL = {
|
|
54
60
|
name: "perplexity_research",
|
|
61
|
+
title: "Deep Research",
|
|
55
62
|
description: "Performs deep research using the Perplexity API. " +
|
|
56
63
|
"Accepts an array of messages (each with a role and content) " +
|
|
57
64
|
"and returns a comprehensive research response with citations.",
|
|
@@ -76,9 +83,17 @@ const PERPLEXITY_RESEARCH_TOOL = {
|
|
|
76
83
|
},
|
|
77
84
|
description: "Array of conversation messages",
|
|
78
85
|
},
|
|
86
|
+
strip_thinking: {
|
|
87
|
+
type: "boolean",
|
|
88
|
+
description: "If true, removes <think>...</think> tags and their content from the response to save context tokens. Default is false.",
|
|
89
|
+
},
|
|
79
90
|
},
|
|
80
91
|
required: ["messages"],
|
|
81
92
|
},
|
|
93
|
+
annotations: {
|
|
94
|
+
readOnlyHint: true,
|
|
95
|
+
openWorldHint: true,
|
|
96
|
+
},
|
|
82
97
|
};
|
|
83
98
|
/**
|
|
84
99
|
* Definition of the Perplexity Reason Tool.
|
|
@@ -86,6 +101,7 @@ const PERPLEXITY_RESEARCH_TOOL = {
|
|
|
86
101
|
*/
|
|
87
102
|
const PERPLEXITY_REASON_TOOL = {
|
|
88
103
|
name: "perplexity_reason",
|
|
104
|
+
title: "Advanced Reasoning",
|
|
89
105
|
description: "Performs reasoning tasks using the Perplexity API. " +
|
|
90
106
|
"Accepts an array of messages (each with a role and content) " +
|
|
91
107
|
"and returns a well-reasoned response using the sonar-reasoning-pro model.",
|
|
@@ -110,9 +126,17 @@ const PERPLEXITY_REASON_TOOL = {
|
|
|
110
126
|
},
|
|
111
127
|
description: "Array of conversation messages",
|
|
112
128
|
},
|
|
129
|
+
strip_thinking: {
|
|
130
|
+
type: "boolean",
|
|
131
|
+
description: "If true, removes <think>...</think> tags and their content from the response to save context tokens. Default is false.",
|
|
132
|
+
},
|
|
113
133
|
},
|
|
114
134
|
required: ["messages"],
|
|
115
135
|
},
|
|
136
|
+
annotations: {
|
|
137
|
+
readOnlyHint: true,
|
|
138
|
+
openWorldHint: true,
|
|
139
|
+
},
|
|
116
140
|
};
|
|
117
141
|
/**
|
|
118
142
|
* Definition of the Perplexity Search Tool.
|
|
@@ -120,8 +144,10 @@ const PERPLEXITY_REASON_TOOL = {
|
|
|
120
144
|
*/
|
|
121
145
|
const PERPLEXITY_SEARCH_TOOL = {
|
|
122
146
|
name: "perplexity_search",
|
|
147
|
+
title: "Search the Web",
|
|
123
148
|
description: "Performs web search using the Perplexity Search API. " +
|
|
124
|
-
"Returns ranked search results with titles, URLs, snippets, and metadata."
|
|
149
|
+
"Returns ranked search results with titles, URLs, snippets, and metadata. " +
|
|
150
|
+
"Perfect for finding up-to-date facts, news, or specific information.",
|
|
125
151
|
inputSchema: {
|
|
126
152
|
type: "object",
|
|
127
153
|
properties: {
|
|
@@ -148,6 +174,10 @@ const PERPLEXITY_SEARCH_TOOL = {
|
|
|
148
174
|
},
|
|
149
175
|
required: ["query"],
|
|
150
176
|
},
|
|
177
|
+
annotations: {
|
|
178
|
+
readOnlyHint: true,
|
|
179
|
+
openWorldHint: true,
|
|
180
|
+
},
|
|
151
181
|
};
|
|
152
182
|
// Retrieve the Perplexity API key from environment variables
|
|
153
183
|
const PERPLEXITY_API_KEY = process.env.PERPLEXITY_API_KEY;
|
|
@@ -155,6 +185,42 @@ if (!PERPLEXITY_API_KEY) {
|
|
|
155
185
|
console.error("Error: PERPLEXITY_API_KEY environment variable is required");
|
|
156
186
|
process.exit(1);
|
|
157
187
|
}
|
|
188
|
+
/**
|
|
189
|
+
* Gets the proxy URL from environment variables.
|
|
190
|
+
* Checks PERPLEXITY_PROXY, HTTPS_PROXY, HTTP_PROXY in order.
|
|
191
|
+
*
|
|
192
|
+
* @returns {string | undefined} The proxy URL if configured, undefined otherwise
|
|
193
|
+
*/
|
|
194
|
+
function getProxyUrl() {
|
|
195
|
+
return process.env.PERPLEXITY_PROXY ||
|
|
196
|
+
process.env.HTTPS_PROXY ||
|
|
197
|
+
process.env.HTTP_PROXY ||
|
|
198
|
+
undefined;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Creates a proxy-aware fetch function.
|
|
202
|
+
* Uses undici with ProxyAgent when a proxy is configured, otherwise uses native fetch.
|
|
203
|
+
*
|
|
204
|
+
* @param {string} url - The URL to fetch
|
|
205
|
+
* @param {RequestInit} options - Fetch options
|
|
206
|
+
* @returns {Promise<Response>} The fetch response
|
|
207
|
+
*/
|
|
208
|
+
function proxyAwareFetch(url_1) {
|
|
209
|
+
return __awaiter(this, arguments, void 0, function* (url, options = {}) {
|
|
210
|
+
const proxyUrl = getProxyUrl();
|
|
211
|
+
if (proxyUrl) {
|
|
212
|
+
// Use undici with ProxyAgent when proxy is configured
|
|
213
|
+
const proxyAgent = new ProxyAgent(proxyUrl);
|
|
214
|
+
const response = yield undiciFetch(url, Object.assign(Object.assign({}, options), { dispatcher: proxyAgent }));
|
|
215
|
+
// Cast to native Response type for compatibility
|
|
216
|
+
return response;
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
// Use native fetch when no proxy is configured
|
|
220
|
+
return fetch(url, options);
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
}
|
|
158
224
|
/**
|
|
159
225
|
* Validates an array of message objects for chat completion tools.
|
|
160
226
|
* Ensures each message has a valid role and content field.
|
|
@@ -180,17 +246,28 @@ function validateMessages(messages, toolName) {
|
|
|
180
246
|
}
|
|
181
247
|
}
|
|
182
248
|
}
|
|
249
|
+
/**
|
|
250
|
+
* Strips thinking tokens (content within <think>...</think> tags) from the response.
|
|
251
|
+
* This helps reduce context usage when the thinking process is not needed.
|
|
252
|
+
*
|
|
253
|
+
* @param {string} content - The content to process
|
|
254
|
+
* @returns {string} The content with thinking tokens removed
|
|
255
|
+
*/
|
|
256
|
+
function stripThinkingTokens(content) {
|
|
257
|
+
return content.replace(/<think>[\s\S]*?<\/think>/g, '').trim();
|
|
258
|
+
}
|
|
183
259
|
/**
|
|
184
260
|
* Performs a chat completion by sending a request to the Perplexity API.
|
|
185
261
|
* Appends citations to the returned message content if they exist.
|
|
186
262
|
*
|
|
187
263
|
* @param {Array<{ role: string; content: string }>} messages - An array of message objects.
|
|
188
264
|
* @param {string} model - The model to use for the completion.
|
|
265
|
+
* @param {boolean} stripThinking - If true, removes <think>...</think> tags from the response.
|
|
189
266
|
* @returns {Promise<string>} The chat completion result with appended citations.
|
|
190
267
|
* @throws Will throw an error if the API request fails.
|
|
191
268
|
*/
|
|
192
269
|
export function performChatCompletion(messages_1) {
|
|
193
|
-
return __awaiter(this, arguments, void 0, function* (messages, model = "sonar-pro") {
|
|
270
|
+
return __awaiter(this, arguments, void 0, function* (messages, model = "sonar-pro", stripThinking = false) {
|
|
194
271
|
// Read timeout fresh each time to respect env var changes
|
|
195
272
|
const TIMEOUT_MS = parseInt(process.env.PERPLEXITY_TIMEOUT_MS || "300000", 10);
|
|
196
273
|
// Construct the API endpoint URL and request body
|
|
@@ -206,7 +283,7 @@ export function performChatCompletion(messages_1) {
|
|
|
206
283
|
const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS);
|
|
207
284
|
let response;
|
|
208
285
|
try {
|
|
209
|
-
response = yield
|
|
286
|
+
response = yield proxyAwareFetch(url.toString(), {
|
|
210
287
|
method: "POST",
|
|
211
288
|
headers: {
|
|
212
289
|
"Content-Type": "application/json",
|
|
@@ -253,6 +330,10 @@ export function performChatCompletion(messages_1) {
|
|
|
253
330
|
}
|
|
254
331
|
// Directly retrieve the main message content from the response
|
|
255
332
|
let messageContent = firstChoice.message.content;
|
|
333
|
+
// Strip thinking tokens if requested
|
|
334
|
+
if (stripThinking) {
|
|
335
|
+
messageContent = stripThinkingTokens(messageContent);
|
|
336
|
+
}
|
|
256
337
|
// If citations are provided, append them to the message content
|
|
257
338
|
if (data.citations && Array.isArray(data.citations) && data.citations.length > 0) {
|
|
258
339
|
messageContent += "\n\nCitations:\n";
|
|
@@ -314,7 +395,7 @@ export function performSearch(query_1) {
|
|
|
314
395
|
const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS);
|
|
315
396
|
let response;
|
|
316
397
|
try {
|
|
317
|
-
response = yield
|
|
398
|
+
response = yield proxyAwareFetch(url.toString(), {
|
|
318
399
|
method: "POST",
|
|
319
400
|
headers: {
|
|
320
401
|
"Content-Type": "application/json",
|
|
@@ -355,12 +436,23 @@ export function performSearch(query_1) {
|
|
|
355
436
|
}
|
|
356
437
|
// Initialize the server with tool metadata and capabilities
|
|
357
438
|
const server = new Server({
|
|
358
|
-
name: "
|
|
359
|
-
version: "0.1
|
|
439
|
+
name: "io.github.perplexityai/mcp-server",
|
|
440
|
+
version: "0.4.1",
|
|
360
441
|
}, {
|
|
361
442
|
capabilities: {
|
|
362
443
|
tools: {},
|
|
363
444
|
},
|
|
445
|
+
instructions: `You are the Perplexity MCP Server. Use these tools appropriately:
|
|
446
|
+
|
|
447
|
+
- perplexity_search: For quick web searches when you need current information or facts. Returns ranked search results.
|
|
448
|
+
|
|
449
|
+
- perplexity_ask: For general questions and conversational queries with real-time web search using the sonar-pro model.
|
|
450
|
+
|
|
451
|
+
- perplexity_research: For deep, comprehensive research requiring thorough analysis using the sonar-deep-research model. Use this for complex topics that require detailed investigation.
|
|
452
|
+
|
|
453
|
+
- perplexity_reason: For complex analytical tasks requiring advanced reasoning using the sonar-reasoning-pro model. Use this for logical problems, analysis, and decision-making.
|
|
454
|
+
|
|
455
|
+
When using perplexity_research or perplexity_reason, consider setting strip_thinking=true to save context tokens if the reasoning process isn't needed in the final output.`,
|
|
364
456
|
});
|
|
365
457
|
/**
|
|
366
458
|
* Registers a handler for listing available tools.
|
|
@@ -397,7 +489,8 @@ server.setRequestHandler(CallToolRequestSchema, (request) => __awaiter(void 0, v
|
|
|
397
489
|
case "perplexity_research": {
|
|
398
490
|
validateMessages(args.messages, "perplexity_research");
|
|
399
491
|
const messages = args.messages;
|
|
400
|
-
const
|
|
492
|
+
const stripThinking = typeof args.strip_thinking === "boolean" ? args.strip_thinking : false;
|
|
493
|
+
const result = yield performChatCompletion(messages, "sonar-deep-research", stripThinking);
|
|
401
494
|
return {
|
|
402
495
|
content: [{ type: "text", text: result }],
|
|
403
496
|
isError: false,
|
|
@@ -406,7 +499,8 @@ server.setRequestHandler(CallToolRequestSchema, (request) => __awaiter(void 0, v
|
|
|
406
499
|
case "perplexity_reason": {
|
|
407
500
|
validateMessages(args.messages, "perplexity_reason");
|
|
408
501
|
const messages = args.messages;
|
|
409
|
-
const
|
|
502
|
+
const stripThinking = typeof args.strip_thinking === "boolean" ? args.strip_thinking : false;
|
|
503
|
+
const result = yield performChatCompletion(messages, "sonar-reasoning-pro", stripThinking);
|
|
410
504
|
return {
|
|
411
505
|
content: [{ type: "text", text: result }],
|
|
412
506
|
isError: false,
|
package/dist/index.test.js
CHANGED
|
@@ -484,4 +484,83 @@ describe("Perplexity MCP Server", () => {
|
|
|
484
484
|
expect(formatted).not.toContain("12345");
|
|
485
485
|
});
|
|
486
486
|
});
|
|
487
|
+
describe("strip_thinking parameter", () => {
|
|
488
|
+
it("should strip thinking tokens when true and keep them when false", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
489
|
+
const mockResponse = {
|
|
490
|
+
choices: [
|
|
491
|
+
{
|
|
492
|
+
message: {
|
|
493
|
+
content: "<think>This is my reasoning process</think>\n\nThe answer is 4.",
|
|
494
|
+
},
|
|
495
|
+
},
|
|
496
|
+
],
|
|
497
|
+
};
|
|
498
|
+
// Test with stripThinking = true
|
|
499
|
+
global.fetch = vi.fn().mockResolvedValue({
|
|
500
|
+
ok: true,
|
|
501
|
+
json: () => __awaiter(void 0, void 0, void 0, function* () { return mockResponse; }),
|
|
502
|
+
});
|
|
503
|
+
const messages = [{ role: "user", content: "What is 2+2?" }];
|
|
504
|
+
const resultStripped = yield performChatCompletion(messages, "sonar-reasoning-pro", true);
|
|
505
|
+
expect(resultStripped).not.toContain("<think>");
|
|
506
|
+
expect(resultStripped).not.toContain("</think>");
|
|
507
|
+
expect(resultStripped).not.toContain("This is my reasoning process");
|
|
508
|
+
expect(resultStripped).toContain("The answer is 4.");
|
|
509
|
+
// Test with stripThinking = false
|
|
510
|
+
global.fetch = vi.fn().mockResolvedValue({
|
|
511
|
+
ok: true,
|
|
512
|
+
json: () => __awaiter(void 0, void 0, void 0, function* () { return mockResponse; }),
|
|
513
|
+
});
|
|
514
|
+
const resultKept = yield performChatCompletion(messages, "sonar-reasoning-pro", false);
|
|
515
|
+
expect(resultKept).toContain("<think>This is my reasoning process</think>");
|
|
516
|
+
expect(resultKept).toContain("The answer is 4.");
|
|
517
|
+
}));
|
|
518
|
+
});
|
|
519
|
+
describe("Proxy Support", () => {
|
|
520
|
+
const originalEnv = process.env;
|
|
521
|
+
beforeEach(() => {
|
|
522
|
+
// Reset environment variables
|
|
523
|
+
process.env = Object.assign({}, originalEnv);
|
|
524
|
+
delete process.env.PERPLEXITY_PROXY;
|
|
525
|
+
delete process.env.HTTPS_PROXY;
|
|
526
|
+
delete process.env.HTTP_PROXY;
|
|
527
|
+
});
|
|
528
|
+
afterEach(() => {
|
|
529
|
+
process.env = originalEnv;
|
|
530
|
+
});
|
|
531
|
+
it("should use native fetch when no proxy is configured", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
532
|
+
const mockResponse = {
|
|
533
|
+
choices: [{ message: { content: "Test response" } }],
|
|
534
|
+
};
|
|
535
|
+
global.fetch = vi.fn().mockResolvedValue({
|
|
536
|
+
ok: true,
|
|
537
|
+
json: () => __awaiter(void 0, void 0, void 0, function* () { return mockResponse; }),
|
|
538
|
+
});
|
|
539
|
+
const messages = [{ role: "user", content: "test" }];
|
|
540
|
+
yield performChatCompletion(messages);
|
|
541
|
+
// Verify native fetch was called (not undici)
|
|
542
|
+
expect(global.fetch).toHaveBeenCalled();
|
|
543
|
+
}));
|
|
544
|
+
it("should read PERPLEXITY_PROXY environment variable", () => {
|
|
545
|
+
process.env.PERPLEXITY_PROXY = "http://proxy.example.com:8080";
|
|
546
|
+
expect(process.env.PERPLEXITY_PROXY).toBe("http://proxy.example.com:8080");
|
|
547
|
+
});
|
|
548
|
+
it("should prioritize PERPLEXITY_PROXY over HTTPS_PROXY", () => {
|
|
549
|
+
process.env.PERPLEXITY_PROXY = "http://perplexity-proxy.example.com:8080";
|
|
550
|
+
process.env.HTTPS_PROXY = "http://https-proxy.example.com:8080";
|
|
551
|
+
// PERPLEXITY_PROXY should take precedence
|
|
552
|
+
expect(process.env.PERPLEXITY_PROXY).toBe("http://perplexity-proxy.example.com:8080");
|
|
553
|
+
});
|
|
554
|
+
it("should fall back to HTTPS_PROXY when PERPLEXITY_PROXY is not set", () => {
|
|
555
|
+
delete process.env.PERPLEXITY_PROXY;
|
|
556
|
+
process.env.HTTPS_PROXY = "http://https-proxy.example.com:8080";
|
|
557
|
+
expect(process.env.HTTPS_PROXY).toBe("http://https-proxy.example.com:8080");
|
|
558
|
+
});
|
|
559
|
+
it("should fall back to HTTP_PROXY when others are not set", () => {
|
|
560
|
+
delete process.env.PERPLEXITY_PROXY;
|
|
561
|
+
delete process.env.HTTPS_PROXY;
|
|
562
|
+
process.env.HTTP_PROXY = "http://http-proxy.example.com:8080";
|
|
563
|
+
expect(process.env.HTTP_PROXY).toBe("http://http-proxy.example.com:8080");
|
|
564
|
+
});
|
|
565
|
+
});
|
|
487
566
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@perplexity-ai/mcp-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"mcpName": "io.github.perplexityai/mcp-server",
|
|
5
5
|
"description": "Real-time web search, reasoning, and research through Perplexity's API",
|
|
6
6
|
"keywords": [
|
|
@@ -29,7 +29,8 @@
|
|
|
29
29
|
},
|
|
30
30
|
"files": [
|
|
31
31
|
"dist",
|
|
32
|
-
"README.md"
|
|
32
|
+
"README.md",
|
|
33
|
+
".claude-plugin"
|
|
33
34
|
],
|
|
34
35
|
"scripts": {
|
|
35
36
|
"build": "tsc && shx chmod +x dist/*.js",
|
|
@@ -41,7 +42,8 @@
|
|
|
41
42
|
},
|
|
42
43
|
"dependencies": {
|
|
43
44
|
"@modelcontextprotocol/sdk": "^1.21.1",
|
|
44
|
-
"dotenv": "^16.6.1"
|
|
45
|
+
"dotenv": "^16.6.1",
|
|
46
|
+
"undici": "^6.20.0"
|
|
45
47
|
},
|
|
46
48
|
"devDependencies": {
|
|
47
49
|
"@types/node": "^20",
|