@kkaminsk/modelcontextprotocol 0.2.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/dist/utils.js ADDED
@@ -0,0 +1,124 @@
1
+ /**
2
+ * Shared utility functions and types for the Perplexity MCP Server.
3
+ * This module contains testable code without side effects.
4
+ */
5
+ // Configuration constants
6
+ export const DEFAULT_TIMEOUT_MS = 300000;
7
+ export const MAX_DOMAIN_FILTERS = 20;
8
+ export const MAX_BATCH_QUERIES = 5;
9
+ export const DEFAULT_MODEL = "sonar-pro";
10
+ /**
11
+ * Builds common options from tool arguments with validation.
12
+ * Extracts and validates shared parameters used across multiple tools.
13
+ *
14
+ * @param {Record<string, unknown>} args - The tool arguments.
15
+ * @returns {CommonOptions} The validated options object.
16
+ */
17
+ export function buildCommonOptions(args) {
18
+ const options = {};
19
+ // Extract and validate search_domain_filter
20
+ if (Array.isArray(args.search_domain_filter)) {
21
+ const filtered = args.search_domain_filter.filter((d) => typeof d === "string");
22
+ if (filtered.length > 0) {
23
+ options.search_domain_filter = filtered;
24
+ }
25
+ }
26
+ // Extract numeric parameters with type checking
27
+ if (typeof args.temperature === "number") {
28
+ options.temperature = args.temperature;
29
+ }
30
+ if (typeof args.max_tokens === "number") {
31
+ options.max_tokens = args.max_tokens;
32
+ }
33
+ if (typeof args.top_p === "number") {
34
+ options.top_p = args.top_p;
35
+ }
36
+ if (typeof args.top_k === "number") {
37
+ options.top_k = args.top_k;
38
+ }
39
+ // Extract search_mode with validation
40
+ if (typeof args.search_mode === "string" && ["web", "academic", "sec"].includes(args.search_mode)) {
41
+ options.search_mode = args.search_mode;
42
+ }
43
+ // Extract search_recency_filter with validation
44
+ if (typeof args.search_recency_filter === "string" && ["day", "week", "month", "year"].includes(args.search_recency_filter)) {
45
+ options.search_recency_filter = args.search_recency_filter;
46
+ }
47
+ // Extract date filters
48
+ if (typeof args.search_after_date === "string") {
49
+ options.search_after_date = args.search_after_date;
50
+ }
51
+ if (typeof args.search_before_date === "string") {
52
+ options.search_before_date = args.search_before_date;
53
+ }
54
+ if (typeof args.last_updated_after === "string") {
55
+ options.last_updated_after = args.last_updated_after;
56
+ }
57
+ if (typeof args.last_updated_before === "string") {
58
+ options.last_updated_before = args.last_updated_before;
59
+ }
60
+ // Extract boolean options
61
+ if (args.return_images === true) {
62
+ options.return_images = true;
63
+ }
64
+ if (args.return_related_questions === true) {
65
+ options.return_related_questions = true;
66
+ }
67
+ return options;
68
+ }
69
+ /**
70
+ * Formats search results into a readable string.
71
+ *
72
+ * @param {PerplexitySearchResponse} data - The search response data.
73
+ * @returns {string} Formatted search results.
74
+ */
75
+ export function formatSearchResults(data) {
76
+ if (!data.results || !Array.isArray(data.results)) {
77
+ return "No search results found.";
78
+ }
79
+ let formattedResults = `Found ${data.results.length} search results:\n\n`;
80
+ data.results.forEach((result, index) => {
81
+ formattedResults += `${index + 1}. **${result.title}**\n`;
82
+ formattedResults += ` URL: ${result.url}\n`;
83
+ if (result.snippet) {
84
+ formattedResults += ` ${result.snippet}\n`;
85
+ }
86
+ if (result.date) {
87
+ formattedResults += ` Date: ${result.date}\n`;
88
+ }
89
+ formattedResults += `\n`;
90
+ });
91
+ return formattedResults;
92
+ }
93
+ /**
94
+ * Formats multi-query search results into a readable string.
95
+ *
96
+ * @param {Array<{query: string, data: PerplexitySearchResponse | null, error: string | null}>} results - The search results per query.
97
+ * @returns {string} Formatted multi-query search results.
98
+ */
99
+ export function formatMultiQueryResults(results) {
100
+ const sections = results.map((result, queryIndex) => {
101
+ var _a;
102
+ const header = `## Query ${queryIndex + 1}: "${result.query}"\n`;
103
+ if (result.error) {
104
+ return header + `\n**Error:** ${result.error}\n`;
105
+ }
106
+ if (!((_a = result.data) === null || _a === void 0 ? void 0 : _a.results) || !Array.isArray(result.data.results)) {
107
+ return header + `\nNo search results found.\n`;
108
+ }
109
+ let formattedResults = `\nFound ${result.data.results.length} results:\n\n`;
110
+ result.data.results.forEach((r, index) => {
111
+ formattedResults += `${index + 1}. **${r.title}**\n`;
112
+ formattedResults += ` URL: ${r.url}\n`;
113
+ if (r.snippet) {
114
+ formattedResults += ` ${r.snippet}\n`;
115
+ }
116
+ if (r.date) {
117
+ formattedResults += ` Date: ${r.date}\n`;
118
+ }
119
+ formattedResults += `\n`;
120
+ });
121
+ return header + formattedResults;
122
+ });
123
+ return sections.join("\n---\n\n");
124
+ }
@@ -0,0 +1,15 @@
1
+ import { defineConfig } from "vitest/config";
2
+ export default defineConfig({
3
+ test: {
4
+ globals: true,
5
+ environment: "node",
6
+ include: ["**/*.test.ts"],
7
+ exclude: ["node_modules", "dist"],
8
+ coverage: {
9
+ provider: "v8",
10
+ reporter: ["text", "html"],
11
+ include: ["index.ts", "utils.ts"],
12
+ exclude: ["**/*.test.ts", "vitest.config.ts"],
13
+ },
14
+ },
15
+ });
package/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "@kkaminsk/modelcontextprotocol",
3
+ "version": "0.2.2",
4
+ "description": "MCP server for the Perplexity API Platform (fork of @perplexity-ai/mcp-server)",
5
+ "keywords": [
6
+ "ai",
7
+ "perplexity",
8
+ "mcp",
9
+ "modelcontextprotocol"
10
+ ],
11
+ "homepage": "https://github.com/kkaminsk/modelcontextprotocol#readme",
12
+ "bugs": {
13
+ "url": "https://github.com/kkaminsk/modelcontextprotocol/issues"
14
+ },
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/kkaminsk/modelcontextprotocol.git"
18
+ },
19
+ "license": "MIT",
20
+ "author": "Perplexity <>",
21
+ "publishConfig": {
22
+ "access": "public"
23
+ },
24
+ "type": "module",
25
+ "main": "dist/index.js",
26
+ "bin": {
27
+ "perplexity-mcp": "dist/index.js"
28
+ },
29
+ "files": [
30
+ "dist",
31
+ "README.md"
32
+ ],
33
+ "scripts": {
34
+ "build": "tsc && shx chmod +x dist/*.js",
35
+ "build:installer": "powershell -ExecutionPolicy Bypass -File installer/Build-Installer.ps1",
36
+ "build:installer:clean": "powershell -ExecutionPolicy Bypass -File installer/Build-Installer.ps1 -Clean",
37
+ "prepare": "npm run build",
38
+ "test": "vitest run",
39
+ "test:watch": "vitest",
40
+ "test:coverage": "vitest run --coverage",
41
+ "watch": "tsc --watch"
42
+ },
43
+ "dependencies": {
44
+ "@modelcontextprotocol/sdk": "^1.25.3"
45
+ },
46
+ "devDependencies": {
47
+ "@types/node": "^22.19.7",
48
+ "@vitest/coverage-v8": "^3.2.4",
49
+ "axios": "^1.13.2",
50
+ "dotenv": "^16.3.1",
51
+ "openspec": "^0.0.0",
52
+ "shx": "^0.4.0",
53
+ "typescript": "^5.9.3",
54
+ "vitest": "^3.2.4"
55
+ },
56
+ "engines": {
57
+ "node": ">=18"
58
+ }
59
+ }