@perplexity-ai/mcp-server 0.2.2 → 0.13.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/LICENSE +201 -21
- package/README.md +169 -73
- package/compat.d.mts +58 -0
- package/compat.d.mts.map +1 -0
- package/compat.d.ts +58 -0
- package/compat.d.ts.map +1 -0
- package/compat.js +387 -0
- package/compat.js.map +1 -0
- package/compat.mjs +378 -0
- package/compat.mjs.map +1 -0
- package/dynamic-tools.d.mts +12 -0
- package/dynamic-tools.d.mts.map +1 -0
- package/dynamic-tools.d.ts +12 -0
- package/dynamic-tools.d.ts.map +1 -0
- package/dynamic-tools.js +135 -0
- package/dynamic-tools.js.map +1 -0
- package/dynamic-tools.mjs +132 -0
- package/dynamic-tools.mjs.map +1 -0
- package/filtering.d.mts +2 -0
- package/filtering.d.mts.map +1 -0
- package/filtering.d.ts +2 -0
- package/filtering.d.ts.map +1 -0
- package/filtering.js +20 -0
- package/filtering.js.map +1 -0
- package/filtering.mjs +13 -0
- package/filtering.mjs.map +1 -0
- package/headers.d.mts +4 -0
- package/headers.d.mts.map +1 -0
- package/headers.d.ts +4 -0
- package/headers.d.ts.map +1 -0
- package/headers.js +22 -0
- package/headers.js.map +1 -0
- package/headers.mjs +18 -0
- package/headers.mjs.map +1 -0
- package/http.d.mts +9 -0
- package/http.d.mts.map +1 -0
- package/http.d.ts +9 -0
- package/http.d.ts.map +1 -0
- package/http.js +108 -0
- package/http.js.map +1 -0
- package/http.mjs +100 -0
- package/http.mjs.map +1 -0
- package/index.d.mts +3 -0
- package/index.d.mts.map +1 -0
- package/index.d.ts +3 -0
- package/index.d.ts.map +1 -0
- package/index.js +91 -0
- package/index.js.map +1 -0
- package/index.mjs +89 -0
- package/index.mjs.map +1 -0
- package/options.d.mts +18 -0
- package/options.d.mts.map +1 -0
- package/options.d.ts +18 -0
- package/options.d.ts.map +1 -0
- package/options.js +415 -0
- package/options.js.map +1 -0
- package/options.mjs +408 -0
- package/options.mjs.map +1 -0
- package/package.json +156 -37
- package/server.d.mts +35 -0
- package/server.d.mts.map +1 -0
- package/server.d.ts +35 -0
- package/server.d.ts.map +1 -0
- package/server.js +166 -0
- package/server.js.map +1 -0
- package/server.mjs +152 -0
- package/server.mjs.map +1 -0
- package/src/compat.ts +483 -0
- package/src/dynamic-tools.ts +159 -0
- package/src/filtering.ts +14 -0
- package/src/headers.ts +23 -0
- package/src/http.ts +127 -0
- package/src/index.ts +108 -0
- package/src/options.ts +453 -0
- package/src/server.ts +201 -0
- package/src/stdio.ts +13 -0
- package/src/tools/chat/completions/create-chat-completions.ts +1360 -0
- package/src/tools/index.ts +73 -0
- package/src/tools/search/create-search.ts +89 -0
- package/src/tools/types.ts +103 -0
- package/src/tools.ts +1 -0
- package/src/tsconfig.json +11 -0
- package/stdio.d.mts +3 -0
- package/stdio.d.mts.map +1 -0
- package/stdio.d.ts +3 -0
- package/stdio.d.ts.map +1 -0
- package/stdio.js +14 -0
- package/stdio.js.map +1 -0
- package/stdio.mjs +10 -0
- package/stdio.mjs.map +1 -0
- package/tools/chat/completions/create-chat-completions.d.mts +45 -0
- package/tools/chat/completions/create-chat-completions.d.mts.map +1 -0
- package/tools/chat/completions/create-chat-completions.d.ts +45 -0
- package/tools/chat/completions/create-chat-completions.d.ts.map +1 -0
- package/tools/chat/completions/create-chat-completions.js +1357 -0
- package/tools/chat/completions/create-chat-completions.js.map +1 -0
- package/tools/chat/completions/create-chat-completions.mjs +1353 -0
- package/tools/chat/completions/create-chat-completions.mjs.map +1 -0
- package/tools/index.d.mts +10 -0
- package/tools/index.d.mts.map +1 -0
- package/tools/index.d.ts +10 -0
- package/tools/index.d.ts.map +1 -0
- package/tools/index.js +57 -0
- package/tools/index.js.map +1 -0
- package/tools/index.mjs +50 -0
- package/tools/index.mjs.map +1 -0
- package/tools/search/create-search.d.mts +45 -0
- package/tools/search/create-search.d.mts.map +1 -0
- package/tools/search/create-search.d.ts +45 -0
- package/tools/search/create-search.d.ts.map +1 -0
- package/tools/search/create-search.js +86 -0
- package/tools/search/create-search.js.map +1 -0
- package/tools/search/create-search.mjs +82 -0
- package/tools/search/create-search.mjs.map +1 -0
- package/tools/types.d.mts +51 -0
- package/tools/types.d.mts.map +1 -0
- package/tools/types.d.ts +51 -0
- package/tools/types.d.ts.map +1 -0
- package/tools/types.js +46 -0
- package/tools/types.js.map +1 -0
- package/tools/types.mjs +42 -0
- package/tools/types.mjs.map +1 -0
- package/tools.d.mts +2 -0
- package/tools.d.mts.map +1 -0
- package/tools.d.ts +2 -0
- package/tools.d.ts.map +1 -0
- package/tools.js +18 -0
- package/tools.js.map +1 -0
- package/tools.mjs +2 -0
- package/tools.mjs.map +1 -0
- package/dist/index.js +0 -446
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/tools/types.ts"],"names":[],"mappings":";AAAA,sFAAsF;;AAiDtF,kDASC;AAED,sDA2BC;AAtCD,SAAgB,mBAAmB,CAAC,MAAe;IACjD,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;aACtC;SACF;KACF,CAAC;AACJ,CAAC;AAEM,KAAK,UAAU,qBAAqB,CAAC,QAAkB;IAC5D,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IACnC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC;IAC3B,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACtE,IAAI,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAClC,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;SAC7C,CAAC;IACJ,CAAC;SAAM,IAAI,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzC,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;SAC7C,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,UAAU;oBAChB,QAAQ,EAAE;wBACR,uEAAuE;wBACvE,GAAG,EAAE,0BAA0B;wBAC/B,QAAQ;wBACR,IAAI,EAAE,IAAI;qBACX;iBACF;aACF;SACF,CAAC;IACJ,CAAC;AACH,CAAC"}
|
package/tools/types.mjs
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
2
|
+
export function asTextContentResult(result) {
|
|
3
|
+
return {
|
|
4
|
+
content: [
|
|
5
|
+
{
|
|
6
|
+
type: 'text',
|
|
7
|
+
text: JSON.stringify(result, null, 2),
|
|
8
|
+
},
|
|
9
|
+
],
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export async function asBinaryContentResult(response) {
|
|
13
|
+
const blob = await response.blob();
|
|
14
|
+
const mimeType = blob.type;
|
|
15
|
+
const data = Buffer.from(await blob.arrayBuffer()).toString('base64');
|
|
16
|
+
if (mimeType.startsWith('image/')) {
|
|
17
|
+
return {
|
|
18
|
+
content: [{ type: 'image', mimeType, data }],
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
else if (mimeType.startsWith('audio/')) {
|
|
22
|
+
return {
|
|
23
|
+
content: [{ type: 'audio', mimeType, data }],
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
return {
|
|
28
|
+
content: [
|
|
29
|
+
{
|
|
30
|
+
type: 'resource',
|
|
31
|
+
resource: {
|
|
32
|
+
// We must give a URI, even though this isn't actually an MCP resource.
|
|
33
|
+
uri: 'resource://tool-response',
|
|
34
|
+
mimeType,
|
|
35
|
+
blob: data,
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=types.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.mjs","sourceRoot":"","sources":["../src/tools/types.ts"],"names":[],"mappings":"AAAA,sFAAsF;AAiDtF,MAAM,UAAU,mBAAmB,CAAC,MAAe;IACjD,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;aACtC;SACF;KACF,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,QAAkB;IAC5D,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IACnC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC;IAC3B,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACtE,IAAI,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAClC,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;SAC7C,CAAC;IACJ,CAAC;SAAM,IAAI,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzC,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;SAC7C,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,UAAU;oBAChB,QAAQ,EAAE;wBACR,uEAAuE;wBACvE,GAAG,EAAE,0BAA0B;wBAC/B,QAAQ;wBACR,IAAI,EAAE,IAAI;qBACX;iBACF;aACF;SACF,CAAC;IACJ,CAAC;AACH,CAAC"}
|
package/tools.d.mts
ADDED
package/tools.d.mts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.d.mts","sourceRoot":"","sources":["src/tools.ts"],"names":[],"mappings":""}
|
package/tools.d.ts
ADDED
package/tools.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["src/tools.ts"],"names":[],"mappings":""}
|
package/tools.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./tools/index.js"), exports);
|
|
18
|
+
//# sourceMappingURL=tools.js.map
|
package/tools.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["src/tools.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,mDAA8B"}
|
package/tools.mjs
ADDED
package/tools.mjs.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.mjs","sourceRoot":"","sources":["src/tools.ts"],"names":[],"mappings":""}
|
package/dist/index.js
DELETED
|
@@ -1,446 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
12
|
-
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
13
|
-
import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
14
|
-
/**
|
|
15
|
-
* Definition of the Perplexity Ask Tool.
|
|
16
|
-
* This tool accepts an array of messages and returns a chat completion response
|
|
17
|
-
* from the Perplexity API, with citations appended to the message if provided.
|
|
18
|
-
*/
|
|
19
|
-
const PERPLEXITY_ASK_TOOL = {
|
|
20
|
-
name: "perplexity_ask",
|
|
21
|
-
description: "Engages in a conversation using the Sonar API. " +
|
|
22
|
-
"Accepts an array of messages (each with a role and content) " +
|
|
23
|
-
"and returns a ask completion response from the Perplexity model.",
|
|
24
|
-
inputSchema: {
|
|
25
|
-
type: "object",
|
|
26
|
-
properties: {
|
|
27
|
-
messages: {
|
|
28
|
-
type: "array",
|
|
29
|
-
items: {
|
|
30
|
-
type: "object",
|
|
31
|
-
properties: {
|
|
32
|
-
role: {
|
|
33
|
-
type: "string",
|
|
34
|
-
description: "Role of the message (e.g., system, user, assistant)",
|
|
35
|
-
},
|
|
36
|
-
content: {
|
|
37
|
-
type: "string",
|
|
38
|
-
description: "The content of the message",
|
|
39
|
-
},
|
|
40
|
-
},
|
|
41
|
-
required: ["role", "content"],
|
|
42
|
-
},
|
|
43
|
-
description: "Array of conversation messages",
|
|
44
|
-
},
|
|
45
|
-
},
|
|
46
|
-
required: ["messages"],
|
|
47
|
-
},
|
|
48
|
-
};
|
|
49
|
-
/**
|
|
50
|
-
* Definition of the Perplexity Research Tool.
|
|
51
|
-
* This tool performs deep research queries using the Perplexity API.
|
|
52
|
-
*/
|
|
53
|
-
const PERPLEXITY_RESEARCH_TOOL = {
|
|
54
|
-
name: "perplexity_research",
|
|
55
|
-
description: "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
|
-
* Definition of the Perplexity Reason Tool.
|
|
85
|
-
* This tool performs reasoning queries using the Perplexity API.
|
|
86
|
-
*/
|
|
87
|
-
const PERPLEXITY_REASON_TOOL = {
|
|
88
|
-
name: "perplexity_reason",
|
|
89
|
-
description: "Performs reasoning tasks using the Perplexity API. " +
|
|
90
|
-
"Accepts an array of messages (each with a role and content) " +
|
|
91
|
-
"and returns a well-reasoned response using the sonar-reasoning-pro model.",
|
|
92
|
-
inputSchema: {
|
|
93
|
-
type: "object",
|
|
94
|
-
properties: {
|
|
95
|
-
messages: {
|
|
96
|
-
type: "array",
|
|
97
|
-
items: {
|
|
98
|
-
type: "object",
|
|
99
|
-
properties: {
|
|
100
|
-
role: {
|
|
101
|
-
type: "string",
|
|
102
|
-
description: "Role of the message (e.g., system, user, assistant)",
|
|
103
|
-
},
|
|
104
|
-
content: {
|
|
105
|
-
type: "string",
|
|
106
|
-
description: "The content of the message",
|
|
107
|
-
},
|
|
108
|
-
},
|
|
109
|
-
required: ["role", "content"],
|
|
110
|
-
},
|
|
111
|
-
description: "Array of conversation messages",
|
|
112
|
-
},
|
|
113
|
-
},
|
|
114
|
-
required: ["messages"],
|
|
115
|
-
},
|
|
116
|
-
};
|
|
117
|
-
/**
|
|
118
|
-
* Definition of the Perplexity Search Tool.
|
|
119
|
-
* This tool performs web search using the Perplexity Search API.
|
|
120
|
-
*/
|
|
121
|
-
const PERPLEXITY_SEARCH_TOOL = {
|
|
122
|
-
name: "perplexity_search",
|
|
123
|
-
description: "Performs web search using the Perplexity Search API. " +
|
|
124
|
-
"Returns ranked search results with titles, URLs, snippets, and metadata.",
|
|
125
|
-
inputSchema: {
|
|
126
|
-
type: "object",
|
|
127
|
-
properties: {
|
|
128
|
-
query: {
|
|
129
|
-
type: "string",
|
|
130
|
-
description: "Search query string",
|
|
131
|
-
},
|
|
132
|
-
max_results: {
|
|
133
|
-
type: "number",
|
|
134
|
-
description: "Maximum number of results to return (1-20, default: 10)",
|
|
135
|
-
minimum: 1,
|
|
136
|
-
maximum: 20,
|
|
137
|
-
},
|
|
138
|
-
max_tokens_per_page: {
|
|
139
|
-
type: "number",
|
|
140
|
-
description: "Maximum tokens to extract per webpage (default: 1024)",
|
|
141
|
-
minimum: 256,
|
|
142
|
-
maximum: 2048,
|
|
143
|
-
},
|
|
144
|
-
country: {
|
|
145
|
-
type: "string",
|
|
146
|
-
description: "ISO 3166-1 alpha-2 country code for regional results (e.g., 'US', 'GB')",
|
|
147
|
-
},
|
|
148
|
-
},
|
|
149
|
-
required: ["query"],
|
|
150
|
-
},
|
|
151
|
-
};
|
|
152
|
-
// Retrieve the Perplexity API key from environment variables
|
|
153
|
-
const PERPLEXITY_API_KEY = process.env.PERPLEXITY_API_KEY;
|
|
154
|
-
if (!PERPLEXITY_API_KEY) {
|
|
155
|
-
console.error("Error: PERPLEXITY_API_KEY environment variable is required");
|
|
156
|
-
process.exit(1);
|
|
157
|
-
}
|
|
158
|
-
// Configure timeout for API requests (default: 5 minutes)
|
|
159
|
-
// Can be overridden via PERPLEXITY_TIMEOUT_MS environment variable
|
|
160
|
-
const TIMEOUT_MS = parseInt(process.env.PERPLEXITY_TIMEOUT_MS || "300000", 10);
|
|
161
|
-
/**
|
|
162
|
-
* Performs a chat completion by sending a request to the Perplexity API.
|
|
163
|
-
* Appends citations to the returned message content if they exist.
|
|
164
|
-
*
|
|
165
|
-
* @param {Array<{ role: string; content: string }>} messages - An array of message objects.
|
|
166
|
-
* @param {string} model - The model to use for the completion.
|
|
167
|
-
* @returns {Promise<string>} The chat completion result with appended citations.
|
|
168
|
-
* @throws Will throw an error if the API request fails.
|
|
169
|
-
*/
|
|
170
|
-
function performChatCompletion(messages_1) {
|
|
171
|
-
return __awaiter(this, arguments, void 0, function* (messages, model = "sonar-pro") {
|
|
172
|
-
// Construct the API endpoint URL and request body
|
|
173
|
-
const url = new URL("https://api.perplexity.ai/chat/completions");
|
|
174
|
-
const body = {
|
|
175
|
-
model: model, // Model identifier passed as parameter
|
|
176
|
-
messages: messages,
|
|
177
|
-
// Additional parameters can be added here if required (e.g., max_tokens, temperature, etc.)
|
|
178
|
-
// See the Sonar API documentation for more details:
|
|
179
|
-
// https://docs.perplexity.ai/api-reference/chat-completions
|
|
180
|
-
};
|
|
181
|
-
const controller = new AbortController();
|
|
182
|
-
const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS);
|
|
183
|
-
let response;
|
|
184
|
-
try {
|
|
185
|
-
response = yield fetch(url.toString(), {
|
|
186
|
-
method: "POST",
|
|
187
|
-
headers: {
|
|
188
|
-
"Content-Type": "application/json",
|
|
189
|
-
"Authorization": `Bearer ${PERPLEXITY_API_KEY}`,
|
|
190
|
-
},
|
|
191
|
-
body: JSON.stringify(body),
|
|
192
|
-
signal: controller.signal,
|
|
193
|
-
});
|
|
194
|
-
clearTimeout(timeoutId);
|
|
195
|
-
}
|
|
196
|
-
catch (error) {
|
|
197
|
-
clearTimeout(timeoutId);
|
|
198
|
-
if (error instanceof Error && error.name === "AbortError") {
|
|
199
|
-
throw new Error(`Request timeout: Perplexity API did not respond within ${TIMEOUT_MS}ms. Consider increasing PERPLEXITY_TIMEOUT_MS.`);
|
|
200
|
-
}
|
|
201
|
-
throw new Error(`Network error while calling Perplexity API: ${error}`);
|
|
202
|
-
}
|
|
203
|
-
// Check for non-successful HTTP status
|
|
204
|
-
if (!response.ok) {
|
|
205
|
-
let errorText;
|
|
206
|
-
try {
|
|
207
|
-
errorText = yield response.text();
|
|
208
|
-
}
|
|
209
|
-
catch (parseError) {
|
|
210
|
-
errorText = "Unable to parse error response";
|
|
211
|
-
}
|
|
212
|
-
throw new Error(`Perplexity API error: ${response.status} ${response.statusText}\n${errorText}`);
|
|
213
|
-
}
|
|
214
|
-
// Attempt to parse the JSON response from the API
|
|
215
|
-
let data;
|
|
216
|
-
try {
|
|
217
|
-
data = yield response.json();
|
|
218
|
-
}
|
|
219
|
-
catch (jsonError) {
|
|
220
|
-
throw new Error(`Failed to parse JSON response from Perplexity API: ${jsonError}`);
|
|
221
|
-
}
|
|
222
|
-
// Directly retrieve the main message content from the response
|
|
223
|
-
let messageContent = data.choices[0].message.content;
|
|
224
|
-
// If citations are provided, append them to the message content
|
|
225
|
-
if (data.citations && Array.isArray(data.citations) && data.citations.length > 0) {
|
|
226
|
-
messageContent += "\n\nCitations:\n";
|
|
227
|
-
data.citations.forEach((citation, index) => {
|
|
228
|
-
messageContent += `[${index + 1}] ${citation}\n`;
|
|
229
|
-
});
|
|
230
|
-
}
|
|
231
|
-
return messageContent;
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
|
-
/**
|
|
235
|
-
* Formats search results from the Perplexity Search API into a readable string.
|
|
236
|
-
*
|
|
237
|
-
* @param {any} data - The search response data from the API.
|
|
238
|
-
* @returns {string} Formatted search results.
|
|
239
|
-
*/
|
|
240
|
-
function formatSearchResults(data) {
|
|
241
|
-
if (!data.results || !Array.isArray(data.results)) {
|
|
242
|
-
return "No search results found.";
|
|
243
|
-
}
|
|
244
|
-
let formattedResults = `Found ${data.results.length} search results:\n\n`;
|
|
245
|
-
data.results.forEach((result, index) => {
|
|
246
|
-
formattedResults += `${index + 1}. **${result.title}**\n`;
|
|
247
|
-
formattedResults += ` URL: ${result.url}\n`;
|
|
248
|
-
if (result.snippet) {
|
|
249
|
-
formattedResults += ` ${result.snippet}\n`;
|
|
250
|
-
}
|
|
251
|
-
if (result.date) {
|
|
252
|
-
formattedResults += ` Date: ${result.date}\n`;
|
|
253
|
-
}
|
|
254
|
-
formattedResults += `\n`;
|
|
255
|
-
});
|
|
256
|
-
return formattedResults;
|
|
257
|
-
}
|
|
258
|
-
/**
|
|
259
|
-
* Performs a web search using the Perplexity Search API.
|
|
260
|
-
*
|
|
261
|
-
* @param {string} query - The search query string.
|
|
262
|
-
* @param {number} maxResults - Maximum number of results to return (1-20).
|
|
263
|
-
* @param {number} maxTokensPerPage - Maximum tokens to extract per webpage.
|
|
264
|
-
* @param {string} country - Optional ISO country code for regional results.
|
|
265
|
-
* @returns {Promise<string>} The formatted search results.
|
|
266
|
-
* @throws Will throw an error if the API request fails.
|
|
267
|
-
*/
|
|
268
|
-
function performSearch(query_1) {
|
|
269
|
-
return __awaiter(this, arguments, void 0, function* (query, maxResults = 10, maxTokensPerPage = 1024, country) {
|
|
270
|
-
const url = new URL("https://api.perplexity.ai/search");
|
|
271
|
-
const body = {
|
|
272
|
-
query: query,
|
|
273
|
-
max_results: maxResults,
|
|
274
|
-
max_tokens_per_page: maxTokensPerPage,
|
|
275
|
-
};
|
|
276
|
-
if (country) {
|
|
277
|
-
body.country = country;
|
|
278
|
-
}
|
|
279
|
-
const controller = new AbortController();
|
|
280
|
-
const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS);
|
|
281
|
-
let response;
|
|
282
|
-
try {
|
|
283
|
-
response = yield fetch(url.toString(), {
|
|
284
|
-
method: "POST",
|
|
285
|
-
headers: {
|
|
286
|
-
"Content-Type": "application/json",
|
|
287
|
-
"Authorization": `Bearer ${PERPLEXITY_API_KEY}`,
|
|
288
|
-
},
|
|
289
|
-
body: JSON.stringify(body),
|
|
290
|
-
signal: controller.signal,
|
|
291
|
-
});
|
|
292
|
-
clearTimeout(timeoutId);
|
|
293
|
-
}
|
|
294
|
-
catch (error) {
|
|
295
|
-
clearTimeout(timeoutId);
|
|
296
|
-
if (error instanceof Error && error.name === "AbortError") {
|
|
297
|
-
throw new Error(`Request timeout: Perplexity Search API did not respond within ${TIMEOUT_MS}ms. Consider increasing PERPLEXITY_TIMEOUT_MS.`);
|
|
298
|
-
}
|
|
299
|
-
throw new Error(`Network error while calling Perplexity Search API: ${error}`);
|
|
300
|
-
}
|
|
301
|
-
// Check for non-successful HTTP status
|
|
302
|
-
if (!response.ok) {
|
|
303
|
-
let errorText;
|
|
304
|
-
try {
|
|
305
|
-
errorText = yield response.text();
|
|
306
|
-
}
|
|
307
|
-
catch (parseError) {
|
|
308
|
-
errorText = "Unable to parse error response";
|
|
309
|
-
}
|
|
310
|
-
throw new Error(`Perplexity Search API error: ${response.status} ${response.statusText}\n${errorText}`);
|
|
311
|
-
}
|
|
312
|
-
let data;
|
|
313
|
-
try {
|
|
314
|
-
data = yield response.json();
|
|
315
|
-
}
|
|
316
|
-
catch (jsonError) {
|
|
317
|
-
throw new Error(`Failed to parse JSON response from Perplexity Search API: ${jsonError}`);
|
|
318
|
-
}
|
|
319
|
-
return formatSearchResults(data);
|
|
320
|
-
});
|
|
321
|
-
}
|
|
322
|
-
// Initialize the server with tool metadata and capabilities
|
|
323
|
-
const server = new Server({
|
|
324
|
-
name: "example-servers/perplexity-ask",
|
|
325
|
-
version: "0.1.0",
|
|
326
|
-
}, {
|
|
327
|
-
capabilities: {
|
|
328
|
-
tools: {},
|
|
329
|
-
},
|
|
330
|
-
});
|
|
331
|
-
/**
|
|
332
|
-
* Registers a handler for listing available tools.
|
|
333
|
-
* When the client requests a list of tools, this handler returns all available Perplexity tools.
|
|
334
|
-
*/
|
|
335
|
-
server.setRequestHandler(ListToolsRequestSchema, () => __awaiter(void 0, void 0, void 0, function* () {
|
|
336
|
-
return ({
|
|
337
|
-
tools: [PERPLEXITY_ASK_TOOL, PERPLEXITY_RESEARCH_TOOL, PERPLEXITY_REASON_TOOL, PERPLEXITY_SEARCH_TOOL],
|
|
338
|
-
});
|
|
339
|
-
}));
|
|
340
|
-
/**
|
|
341
|
-
* Registers a handler for calling a specific tool.
|
|
342
|
-
* Processes requests by validating input and invoking the appropriate tool.
|
|
343
|
-
*
|
|
344
|
-
* @param {object} request - The incoming tool call request.
|
|
345
|
-
* @returns {Promise<object>} The response containing the tool's result or an error.
|
|
346
|
-
*/
|
|
347
|
-
server.setRequestHandler(CallToolRequestSchema, (request) => __awaiter(void 0, void 0, void 0, function* () {
|
|
348
|
-
try {
|
|
349
|
-
const { name, arguments: args } = request.params;
|
|
350
|
-
if (!args) {
|
|
351
|
-
throw new Error("No arguments provided");
|
|
352
|
-
}
|
|
353
|
-
switch (name) {
|
|
354
|
-
case "perplexity_ask": {
|
|
355
|
-
if (!Array.isArray(args.messages)) {
|
|
356
|
-
throw new Error("Invalid arguments for perplexity_ask: 'messages' must be an array");
|
|
357
|
-
}
|
|
358
|
-
// Invoke the chat completion function with the provided messages
|
|
359
|
-
const messages = args.messages;
|
|
360
|
-
const result = yield performChatCompletion(messages, "sonar-pro");
|
|
361
|
-
return {
|
|
362
|
-
content: [{ type: "text", text: result }],
|
|
363
|
-
isError: false,
|
|
364
|
-
};
|
|
365
|
-
}
|
|
366
|
-
case "perplexity_research": {
|
|
367
|
-
if (!Array.isArray(args.messages)) {
|
|
368
|
-
throw new Error("Invalid arguments for perplexity_research: 'messages' must be an array");
|
|
369
|
-
}
|
|
370
|
-
// Invoke the chat completion function with the provided messages using the deep research model
|
|
371
|
-
const messages = args.messages;
|
|
372
|
-
const result = yield performChatCompletion(messages, "sonar-deep-research");
|
|
373
|
-
return {
|
|
374
|
-
content: [{ type: "text", text: result }],
|
|
375
|
-
isError: false,
|
|
376
|
-
};
|
|
377
|
-
}
|
|
378
|
-
case "perplexity_reason": {
|
|
379
|
-
if (!Array.isArray(args.messages)) {
|
|
380
|
-
throw new Error("Invalid arguments for perplexity_reason: 'messages' must be an array");
|
|
381
|
-
}
|
|
382
|
-
// Invoke the chat completion function with the provided messages using the reasoning model
|
|
383
|
-
const messages = args.messages;
|
|
384
|
-
const result = yield performChatCompletion(messages, "sonar-reasoning-pro");
|
|
385
|
-
return {
|
|
386
|
-
content: [{ type: "text", text: result }],
|
|
387
|
-
isError: false,
|
|
388
|
-
};
|
|
389
|
-
}
|
|
390
|
-
case "perplexity_search": {
|
|
391
|
-
if (typeof args.query !== "string") {
|
|
392
|
-
throw new Error("Invalid arguments for perplexity_search: 'query' must be a string");
|
|
393
|
-
}
|
|
394
|
-
const { query, max_results, max_tokens_per_page, country } = args;
|
|
395
|
-
const maxResults = typeof max_results === "number" ? max_results : undefined;
|
|
396
|
-
const maxTokensPerPage = typeof max_tokens_per_page === "number" ? max_tokens_per_page : undefined;
|
|
397
|
-
const countryCode = typeof country === "string" ? country : undefined;
|
|
398
|
-
const result = yield performSearch(query, maxResults, maxTokensPerPage, countryCode);
|
|
399
|
-
return {
|
|
400
|
-
content: [{ type: "text", text: result }],
|
|
401
|
-
isError: false,
|
|
402
|
-
};
|
|
403
|
-
}
|
|
404
|
-
default:
|
|
405
|
-
// Respond with an error if an unknown tool is requested
|
|
406
|
-
return {
|
|
407
|
-
content: [{ type: "text", text: `Unknown tool: ${name}` }],
|
|
408
|
-
isError: true,
|
|
409
|
-
};
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
catch (error) {
|
|
413
|
-
// Return error details in the response
|
|
414
|
-
return {
|
|
415
|
-
content: [
|
|
416
|
-
{
|
|
417
|
-
type: "text",
|
|
418
|
-
text: `Error: ${error instanceof Error ? error.message : String(error)}`,
|
|
419
|
-
},
|
|
420
|
-
],
|
|
421
|
-
isError: true,
|
|
422
|
-
};
|
|
423
|
-
}
|
|
424
|
-
}));
|
|
425
|
-
/**
|
|
426
|
-
* Initializes and runs the server using standard I/O for communication.
|
|
427
|
-
* Logs an error and exits if the server fails to start.
|
|
428
|
-
*/
|
|
429
|
-
function runServer() {
|
|
430
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
431
|
-
try {
|
|
432
|
-
const transport = new StdioServerTransport();
|
|
433
|
-
yield server.connect(transport);
|
|
434
|
-
console.error("Perplexity MCP Server running on stdio with Ask, Research, Reason, and Search tools");
|
|
435
|
-
}
|
|
436
|
-
catch (error) {
|
|
437
|
-
console.error("Fatal error running server:", error);
|
|
438
|
-
process.exit(1);
|
|
439
|
-
}
|
|
440
|
-
});
|
|
441
|
-
}
|
|
442
|
-
// Start the server and catch any startup errors
|
|
443
|
-
runServer().catch((error) => {
|
|
444
|
-
console.error("Fatal error running server:", error);
|
|
445
|
-
process.exit(1);
|
|
446
|
-
});
|