perplexity-user-mcp 0.8.50 → 0.8.53

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/README.md CHANGED
@@ -273,6 +273,31 @@ Path: `~/.config/opencode/opencode.json`.
273
273
  - `perplexity_login` — returns login instructions (interactive login runs via the CLI / extension)
274
274
  - `perplexity_doctor` — run diagnostic checks across browser, profile, auth, and network and return a Markdown report (pass `probe:true` for a live search probe)
275
275
 
276
+ ## Prompts (custom slash-commands)
277
+
278
+ The server also exposes MCP **prompts** — reusable templates that show up as `/slash-commands` in clients that support them (Claude Desktop, Cursor, …). Five are built in:
279
+
280
+ - `perplexity.researchPlan` `{topic}` · `perplexity.reasoningPlan` `{question}`
281
+ - `perplexity-fact-check` `{claim}` · `perplexity-compare` `{optionA} {optionB}` · `perplexity-latest` `{topic}`
282
+
283
+ You can add your own (and override/reset the built-ins) without touching code — they're read from `~/.perplexity-mcp/prompts.json`:
284
+
285
+ ```json
286
+ {
287
+ "overrides": {},
288
+ "custom": [
289
+ {
290
+ "name": "my-summary",
291
+ "description": "Summarize a URL with citations",
292
+ "arguments": [{ "name": "url", "description": "Page to summarize", "required": true }],
293
+ "template": "Use perplexity_search to read {url} and summarize the key points with citations."
294
+ }
295
+ ]
296
+ }
297
+ ```
298
+
299
+ `{arg}` placeholders are substituted with the values the client passes. Built-in names live under `overrides`; everything else is a `custom` entry. The **VS Code extension's "Prompts" tab** is a visual editor for this file. Clients cache the prompt list at connect-time, so reconnect (or reload the window) after editing to pick up changes; the embedded daemon refreshes on its next connection automatically.
300
+
276
301
  ## Search sources and advanced queries
277
302
 
278
303
  Search-style tools support Perplexity source focus through a `sources` argument:
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  ensureDaemon
3
- } from "./chunk-MIHIG4M4.mjs";
3
+ } from "./chunk-OUQRRFAU.mjs";
4
4
  import {
5
5
  getPackageVersion
6
- } from "./chunk-OOSSV7G3.mjs";
6
+ } from "./chunk-ZUOZ5KXV.mjs";
7
7
 
8
8
  // src/daemon/client-http.ts
9
9
  import { randomUUID } from "crypto";
@@ -0,0 +1,127 @@
1
+ import {
2
+ safeAtomicWriteFileSync
3
+ } from "./chunk-MTDFKNXX.mjs";
4
+ import {
5
+ getConfigDir
6
+ } from "./chunk-E3GRJXXJ.mjs";
7
+
8
+ // src/prompts-config.ts
9
+ import { mkdirSync, readFileSync } from "fs";
10
+ import { dirname, join } from "path";
11
+ var CUSTOM_NAME_RE = /^[a-z][a-z0-9-]*$/;
12
+ var ARG_RE = /\{([a-z][a-zA-Z0-9]*)\}/g;
13
+ var BUILTIN_PROMPTS = [
14
+ {
15
+ name: "perplexity.researchPlan",
16
+ description: "Deep research brief on a topic, routed to perplexity_research.",
17
+ arguments: [{ name: "topic", description: "The subject to research", required: true }],
18
+ template: 'Use perplexity_research to produce a sourced research brief about "{topic}". Emphasize citations, key findings, and next questions.'
19
+ },
20
+ {
21
+ name: "perplexity.reasoningPlan",
22
+ description: "Step-by-step reasoning on a question, routed to perplexity_reason.",
23
+ arguments: [{ name: "question", description: "The question to reason about", required: true }],
24
+ template: "Use perplexity_reason on the following question and provide the reasoning trace plus a concise final answer: {question}"
25
+ },
26
+ {
27
+ name: "perplexity-fact-check",
28
+ description: "Verify a claim with cited primary sources via perplexity_search.",
29
+ arguments: [{ name: "claim", description: "The statement to verify", required: true }],
30
+ template: "Use perplexity_search to verify the following claim and cite primary sources. State clearly whether it is true, false, misleading, or unverifiable, and explain the evidence.\n\nClaim: {claim}"
31
+ },
32
+ {
33
+ name: "perplexity-compare",
34
+ description: "Compare two options with a sourced comparison table.",
35
+ arguments: [
36
+ { name: "optionA", description: "First option", required: true },
37
+ { name: "optionB", description: "Second option", required: true }
38
+ ],
39
+ template: "Use perplexity_search to compare {optionA} and {optionB}. Produce a concise comparison table of the key differences, then a recommendation backed by cited sources."
40
+ },
41
+ {
42
+ name: "perplexity-latest",
43
+ description: "Find the latest developments on a topic via perplexity_search.",
44
+ arguments: [{ name: "topic", description: "The topic to track", required: true }],
45
+ template: 'Use perplexity_search to find the latest developments about "{topic}" from the past few weeks. Prioritize recent, credible sources and cite publication dates.'
46
+ }
47
+ ];
48
+ function promptsConfigPath(configDir = getConfigDir()) {
49
+ return join(configDir, "prompts.json");
50
+ }
51
+ function normalizeConfig(raw) {
52
+ const obj = raw && typeof raw === "object" ? raw : {};
53
+ const overrides = obj.overrides && typeof obj.overrides === "object" && !Array.isArray(obj.overrides) ? obj.overrides : {};
54
+ const custom = Array.isArray(obj.custom) ? obj.custom : [];
55
+ return { overrides, custom };
56
+ }
57
+ function readPromptsConfig(configDir = getConfigDir()) {
58
+ try {
59
+ return normalizeConfig(JSON.parse(readFileSync(promptsConfigPath(configDir), "utf8")));
60
+ } catch {
61
+ return { overrides: {}, custom: [] };
62
+ }
63
+ }
64
+ function writePromptsConfig(config, configDir = getConfigDir()) {
65
+ const p = promptsConfigPath(configDir);
66
+ mkdirSync(dirname(p), { recursive: true });
67
+ safeAtomicWriteFileSync(p, JSON.stringify(config, null, 2) + "\n", "utf8");
68
+ }
69
+ function toStored(prompt) {
70
+ return {
71
+ name: prompt.name,
72
+ description: prompt.description,
73
+ arguments: (prompt.arguments ?? []).map((a) => ({
74
+ name: a.name,
75
+ description: a.description,
76
+ required: !!a.required
77
+ })),
78
+ template: prompt.template
79
+ };
80
+ }
81
+ function mergePrompts(config) {
82
+ const builtinNames = new Set(BUILTIN_PROMPTS.map((b) => b.name));
83
+ const builtins = BUILTIN_PROMPTS.map((b) => {
84
+ const override = config.overrides[b.name];
85
+ const base = override ?? b;
86
+ return { ...toStored(base), name: b.name, isBuiltin: true, isModified: !!override };
87
+ });
88
+ const custom = config.custom.filter((c) => c && c.name && !builtinNames.has(c.name)).map((c) => ({ ...toStored(c), isBuiltin: false, isModified: false }));
89
+ return [...builtins, ...custom];
90
+ }
91
+ function upsertPrompt(config, prompt) {
92
+ const stored = toStored(prompt);
93
+ if (BUILTIN_PROMPTS.some((b) => b.name === stored.name)) {
94
+ return { ...config, overrides: { ...config.overrides, [stored.name]: stored } };
95
+ }
96
+ const exists = config.custom.some((c) => c.name === stored.name);
97
+ const custom = exists ? config.custom.map((c) => c.name === stored.name ? stored : c) : [...config.custom, stored];
98
+ return { ...config, custom };
99
+ }
100
+ function deleteCustomPrompt(config, name) {
101
+ return { ...config, custom: config.custom.filter((c) => c.name !== name) };
102
+ }
103
+ function resetBuiltin(config, name) {
104
+ if (!(name in config.overrides)) return config;
105
+ const overrides = { ...config.overrides };
106
+ delete overrides[name];
107
+ return { ...config, overrides };
108
+ }
109
+ function substituteTemplate(template, args) {
110
+ return template.replace(ARG_RE, (_match, key) => {
111
+ const value = args[key];
112
+ return value == null ? "" : String(value);
113
+ });
114
+ }
115
+
116
+ export {
117
+ CUSTOM_NAME_RE,
118
+ BUILTIN_PROMPTS,
119
+ promptsConfigPath,
120
+ readPromptsConfig,
121
+ writePromptsConfig,
122
+ mergePrompts,
123
+ upsertPrompt,
124
+ deleteCustomPrompt,
125
+ resetBuiltin,
126
+ substituteTemplate
127
+ };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  ensureDaemon
3
- } from "./chunk-MIHIG4M4.mjs";
3
+ } from "./chunk-OUQRRFAU.mjs";
4
4
 
5
5
  // src/daemon/attach.ts
6
6
  import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
@@ -13,7 +13,7 @@ import {
13
13
  import {
14
14
  getPackageVersion,
15
15
  startDaemonServer
16
- } from "./chunk-OOSSV7G3.mjs";
16
+ } from "./chunk-ZUOZ5KXV.mjs";
17
17
  import {
18
18
  ensureToken,
19
19
  getTokenPath,
@@ -25,7 +25,7 @@ import {
25
25
  } from "./chunk-3LUO5ATM.mjs";
26
26
  import {
27
27
  PerplexityClient
28
- } from "./chunk-SF3BG2IA.mjs";
28
+ } from "./chunk-XQ32SABC.mjs";
29
29
  import {
30
30
  getActiveName,
31
31
  getConfigDir
@@ -2,7 +2,7 @@ import {
2
2
  PerplexityClient,
3
3
  getCloudThreadViaImpit,
4
4
  listCloudThreadsViaImpit
5
- } from "./chunk-SF3BG2IA.mjs";
5
+ } from "./chunk-XQ32SABC.mjs";
6
6
  import {
7
7
  hydrateCloudEntry,
8
8
  upsertFromCloud
@@ -1,23 +1,31 @@
1
+ import {
2
+ ensureToken,
3
+ getTokenPath,
4
+ rotateToken
5
+ } from "./chunk-DKEJZ4FI.mjs";
1
6
  import {
2
7
  appendAuditEntry,
3
8
  getAuditLogPath,
4
9
  readAuditTail
5
10
  } from "./chunk-TSLRTZYR.mjs";
6
11
  import {
7
- ensureToken,
8
- getTokenPath,
9
- rotateToken
10
- } from "./chunk-DKEJZ4FI.mjs";
12
+ mergePrompts,
13
+ readPromptsConfig,
14
+ substituteTemplate
15
+ } from "./chunk-5IKZJVZZ.mjs";
11
16
  import {
12
17
  hydrateCloudHistoryEntry,
13
18
  syncCloudHistory
14
- } from "./chunk-REY5WMXY.mjs";
19
+ } from "./chunk-V7HUK4A5.mjs";
15
20
  import {
16
21
  PerplexityClient,
17
22
  exportThreadViaImpit,
18
23
  readCachedAccountInfoFromDisk,
19
24
  retrieveThreadViaImpit
20
- } from "./chunk-SF3BG2IA.mjs";
25
+ } from "./chunk-XQ32SABC.mjs";
26
+ import {
27
+ safeAtomicWriteFileSync
28
+ } from "./chunk-MTDFKNXX.mjs";
21
29
  import {
22
30
  append,
23
31
  findPendingByThread,
@@ -27,9 +35,6 @@ import {
27
35
  list,
28
36
  update
29
37
  } from "./chunk-6E6XTHTG.mjs";
30
- import {
31
- safeAtomicWriteFileSync
32
- } from "./chunk-MTDFKNXX.mjs";
33
38
  import {
34
39
  getConfigDir
35
40
  } from "./chunk-E3GRJXXJ.mjs";
@@ -44,51 +49,49 @@ import express from "express";
44
49
 
45
50
  // src/prompts.ts
46
51
  import { z } from "zod";
52
+ function buildArgsSchema(args) {
53
+ const shape = {};
54
+ for (const arg of args) {
55
+ if (!arg?.name) continue;
56
+ let field = z.string();
57
+ if (arg.description) field = field.describe(arg.description);
58
+ shape[arg.name] = arg.required ? field : field.optional();
59
+ }
60
+ return shape;
61
+ }
47
62
  function registerPrompts(server) {
48
- server.registerPrompt(
49
- "perplexity.researchPlan",
50
- {
51
- title: "Perplexity Research Plan",
52
- description: "Generate a prompt that routes to the deep research tool.",
53
- argsSchema: {
54
- topic: z.string()
55
- }
56
- },
57
- ({ topic }) => ({
58
- description: `Deep research prompt for ${topic}`,
63
+ const prompts = mergePrompts(readPromptsConfig());
64
+ const seen = /* @__PURE__ */ new Set();
65
+ for (const prompt of prompts) {
66
+ if (!prompt.name || seen.has(prompt.name)) continue;
67
+ seen.add(prompt.name);
68
+ const render = (args = {}) => ({
69
+ description: prompt.description,
59
70
  messages: [
60
71
  {
61
72
  role: "user",
62
- content: {
63
- type: "text",
64
- text: `Use perplexity_research to produce a sourced research brief about "${topic}". Emphasize citations, key findings, and next questions.`
65
- }
73
+ content: { type: "text", text: substituteTemplate(prompt.template, args) }
66
74
  }
67
75
  ]
68
- })
69
- );
70
- server.registerPrompt(
71
- "perplexity.reasoningPlan",
72
- {
73
- title: "Perplexity Reasoning Plan",
74
- description: "Generate a prompt that routes to the reasoning tool.",
75
- argsSchema: {
76
- question: z.string()
76
+ });
77
+ try {
78
+ if (prompt.arguments.length === 0) {
79
+ server.registerPrompt(prompt.name, { title: prompt.name, description: prompt.description }, () => render());
80
+ } else {
81
+ server.registerPrompt(
82
+ prompt.name,
83
+ {
84
+ title: prompt.name,
85
+ description: prompt.description,
86
+ argsSchema: buildArgsSchema(prompt.arguments)
87
+ },
88
+ (args) => render(args)
89
+ );
77
90
  }
78
- },
79
- ({ question }) => ({
80
- description: `Reasoning prompt for ${question}`,
81
- messages: [
82
- {
83
- role: "user",
84
- content: {
85
- type: "text",
86
- text: `Use perplexity_reason on the following question and provide the reasoning trace plus a concise final answer: ${question}`
87
- }
88
- }
89
- ]
90
- })
91
- );
91
+ } catch (err) {
92
+ console.error(`[perplexity-mcp] failed to register prompt '${prompt.name}':`, err);
93
+ }
94
+ }
92
95
  }
93
96
 
94
97
  // src/resources.ts
package/dist/client.mjs CHANGED
@@ -8,10 +8,10 @@ import {
8
8
  readCachedAccountInfoFromDisk,
9
9
  retrieveThreadViaImpit,
10
10
  searchPerplexityViaImpit
11
- } from "./chunk-SF3BG2IA.mjs";
11
+ } from "./chunk-XQ32SABC.mjs";
12
12
  import "./chunk-KVV3JBSN.mjs";
13
- import "./chunk-2GOOGBD6.mjs";
14
13
  import "./chunk-ZQZC634I.mjs";
14
+ import "./chunk-2GOOGBD6.mjs";
15
15
  import "./chunk-2FBDBRC5.mjs";
16
16
  import "./chunk-C5I7KXHK.mjs";
17
17
  import "./chunk-MTDFKNXX.mjs";
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  hydrateCloudHistoryEntry,
3
3
  syncCloudHistory
4
- } from "./chunk-REY5WMXY.mjs";
5
- import "./chunk-SF3BG2IA.mjs";
4
+ } from "./chunk-V7HUK4A5.mjs";
5
+ import "./chunk-XQ32SABC.mjs";
6
6
  import "./chunk-KVV3JBSN.mjs";
7
- import "./chunk-2GOOGBD6.mjs";
8
- import "./chunk-6E6XTHTG.mjs";
9
7
  import "./chunk-ZQZC634I.mjs";
8
+ import "./chunk-2GOOGBD6.mjs";
10
9
  import "./chunk-2FBDBRC5.mjs";
11
10
  import "./chunk-C5I7KXHK.mjs";
12
11
  import "./chunk-MTDFKNXX.mjs";
12
+ import "./chunk-6E6XTHTG.mjs";
13
13
  import "./chunk-E3GRJXXJ.mjs";
14
14
  import "./chunk-4UEJOM6W.mjs";
15
15
  export {
@@ -1,25 +1,26 @@
1
1
  import {
2
2
  DaemonAttachError,
3
3
  attachToDaemon
4
- } from "../chunk-E7GU4PUX.mjs";
5
- import "../chunk-MIHIG4M4.mjs";
4
+ } from "../chunk-HAO6U55U.mjs";
5
+ import "../chunk-OUQRRFAU.mjs";
6
6
  import "../chunk-LGH5BSUY.mjs";
7
7
  import "../chunk-6YMQVLFX.mjs";
8
8
  import "../chunk-TIWHN4IW.mjs";
9
9
  import "../chunk-NMKNEEZB.mjs";
10
- import "../chunk-OOSSV7G3.mjs";
11
- import "../chunk-TSLRTZYR.mjs";
10
+ import "../chunk-ZUOZ5KXV.mjs";
12
11
  import "../chunk-DKEJZ4FI.mjs";
12
+ import "../chunk-TSLRTZYR.mjs";
13
13
  import "../chunk-3LUO5ATM.mjs";
14
- import "../chunk-REY5WMXY.mjs";
15
- import "../chunk-SF3BG2IA.mjs";
14
+ import "../chunk-5IKZJVZZ.mjs";
15
+ import "../chunk-V7HUK4A5.mjs";
16
+ import "../chunk-XQ32SABC.mjs";
16
17
  import "../chunk-KVV3JBSN.mjs";
17
- import "../chunk-2GOOGBD6.mjs";
18
- import "../chunk-6E6XTHTG.mjs";
19
18
  import "../chunk-ZQZC634I.mjs";
19
+ import "../chunk-2GOOGBD6.mjs";
20
20
  import "../chunk-2FBDBRC5.mjs";
21
21
  import "../chunk-C5I7KXHK.mjs";
22
22
  import "../chunk-MTDFKNXX.mjs";
23
+ import "../chunk-6E6XTHTG.mjs";
23
24
  import "../chunk-E3GRJXXJ.mjs";
24
25
  import "../chunk-4UEJOM6W.mjs";
25
26
  export {
@@ -2,25 +2,26 @@ import {
2
2
  exportHistoryViaDaemon,
3
3
  hydrateCloudHistoryEntryViaDaemon,
4
4
  syncCloudHistoryViaDaemon
5
- } from "../chunk-CV6NITDS.mjs";
6
- import "../chunk-MIHIG4M4.mjs";
5
+ } from "../chunk-2PXHRVDZ.mjs";
6
+ import "../chunk-OUQRRFAU.mjs";
7
7
  import "../chunk-LGH5BSUY.mjs";
8
8
  import "../chunk-6YMQVLFX.mjs";
9
9
  import "../chunk-TIWHN4IW.mjs";
10
10
  import "../chunk-NMKNEEZB.mjs";
11
- import "../chunk-OOSSV7G3.mjs";
12
- import "../chunk-TSLRTZYR.mjs";
11
+ import "../chunk-ZUOZ5KXV.mjs";
13
12
  import "../chunk-DKEJZ4FI.mjs";
13
+ import "../chunk-TSLRTZYR.mjs";
14
14
  import "../chunk-3LUO5ATM.mjs";
15
- import "../chunk-REY5WMXY.mjs";
16
- import "../chunk-SF3BG2IA.mjs";
15
+ import "../chunk-5IKZJVZZ.mjs";
16
+ import "../chunk-V7HUK4A5.mjs";
17
+ import "../chunk-XQ32SABC.mjs";
17
18
  import "../chunk-KVV3JBSN.mjs";
18
- import "../chunk-2GOOGBD6.mjs";
19
- import "../chunk-6E6XTHTG.mjs";
20
19
  import "../chunk-ZQZC634I.mjs";
20
+ import "../chunk-2GOOGBD6.mjs";
21
21
  import "../chunk-2FBDBRC5.mjs";
22
22
  import "../chunk-C5I7KXHK.mjs";
23
23
  import "../chunk-MTDFKNXX.mjs";
24
+ import "../chunk-6E6XTHTG.mjs";
24
25
  import "../chunk-E3GRJXXJ.mjs";
25
26
  import "../chunk-4UEJOM6W.mjs";
26
27
  export {
@@ -2,10 +2,10 @@ import {
2
2
  exportHistoryViaDaemon,
3
3
  hydrateCloudHistoryEntryViaDaemon,
4
4
  syncCloudHistoryViaDaemon
5
- } from "../chunk-CV6NITDS.mjs";
5
+ } from "../chunk-2PXHRVDZ.mjs";
6
6
  import {
7
7
  attachToDaemon
8
- } from "../chunk-E7GU4PUX.mjs";
8
+ } from "../chunk-HAO6U55U.mjs";
9
9
  import {
10
10
  disableDaemonTunnel,
11
11
  enableDaemonTunnel,
@@ -21,7 +21,7 @@ import {
21
21
  rotateDaemonToken,
22
22
  startDaemon,
23
23
  stopDaemon
24
- } from "../chunk-MIHIG4M4.mjs";
24
+ } from "../chunk-OUQRRFAU.mjs";
25
25
  import "../chunk-LGH5BSUY.mjs";
26
26
  import {
27
27
  extractTunnelUrl,
@@ -43,12 +43,7 @@ import {
43
43
  } from "../chunk-NMKNEEZB.mjs";
44
44
  import {
45
45
  startDaemonServer
46
- } from "../chunk-OOSSV7G3.mjs";
47
- import {
48
- appendAuditEntry,
49
- getAuditLogPath,
50
- readAuditTail
51
- } from "../chunk-TSLRTZYR.mjs";
46
+ } from "../chunk-ZUOZ5KXV.mjs";
52
47
  import {
53
48
  ensureToken,
54
49
  generateBearerToken,
@@ -56,16 +51,22 @@ import {
56
51
  readToken,
57
52
  rotateToken
58
53
  } from "../chunk-DKEJZ4FI.mjs";
54
+ import {
55
+ appendAuditEntry,
56
+ getAuditLogPath,
57
+ readAuditTail
58
+ } from "../chunk-TSLRTZYR.mjs";
59
59
  import "../chunk-3LUO5ATM.mjs";
60
- import "../chunk-REY5WMXY.mjs";
61
- import "../chunk-SF3BG2IA.mjs";
60
+ import "../chunk-5IKZJVZZ.mjs";
61
+ import "../chunk-V7HUK4A5.mjs";
62
+ import "../chunk-XQ32SABC.mjs";
62
63
  import "../chunk-KVV3JBSN.mjs";
63
- import "../chunk-2GOOGBD6.mjs";
64
- import "../chunk-6E6XTHTG.mjs";
65
64
  import "../chunk-ZQZC634I.mjs";
65
+ import "../chunk-2GOOGBD6.mjs";
66
66
  import "../chunk-2FBDBRC5.mjs";
67
67
  import "../chunk-C5I7KXHK.mjs";
68
68
  import "../chunk-MTDFKNXX.mjs";
69
+ import "../chunk-6E6XTHTG.mjs";
69
70
  import "../chunk-E3GRJXXJ.mjs";
70
71
  import "../chunk-4UEJOM6W.mjs";
71
72
  export {
@@ -13,24 +13,25 @@ import {
13
13
  rotateDaemonToken,
14
14
  startDaemon,
15
15
  stopDaemon
16
- } from "../chunk-MIHIG4M4.mjs";
16
+ } from "../chunk-OUQRRFAU.mjs";
17
17
  import "../chunk-LGH5BSUY.mjs";
18
18
  import "../chunk-6YMQVLFX.mjs";
19
19
  import "../chunk-TIWHN4IW.mjs";
20
20
  import "../chunk-NMKNEEZB.mjs";
21
- import "../chunk-OOSSV7G3.mjs";
22
- import "../chunk-TSLRTZYR.mjs";
21
+ import "../chunk-ZUOZ5KXV.mjs";
23
22
  import "../chunk-DKEJZ4FI.mjs";
23
+ import "../chunk-TSLRTZYR.mjs";
24
24
  import "../chunk-3LUO5ATM.mjs";
25
- import "../chunk-REY5WMXY.mjs";
26
- import "../chunk-SF3BG2IA.mjs";
25
+ import "../chunk-5IKZJVZZ.mjs";
26
+ import "../chunk-V7HUK4A5.mjs";
27
+ import "../chunk-XQ32SABC.mjs";
27
28
  import "../chunk-KVV3JBSN.mjs";
28
- import "../chunk-2GOOGBD6.mjs";
29
- import "../chunk-6E6XTHTG.mjs";
30
29
  import "../chunk-ZQZC634I.mjs";
30
+ import "../chunk-2GOOGBD6.mjs";
31
31
  import "../chunk-2FBDBRC5.mjs";
32
32
  import "../chunk-C5I7KXHK.mjs";
33
33
  import "../chunk-MTDFKNXX.mjs";
34
+ import "../chunk-6E6XTHTG.mjs";
34
35
  import "../chunk-E3GRJXXJ.mjs";
35
36
  import "../chunk-4UEJOM6W.mjs";
36
37
  export {
@@ -1,18 +1,19 @@
1
1
  import {
2
2
  resolveRequestResource,
3
3
  startDaemonServer
4
- } from "../chunk-OOSSV7G3.mjs";
5
- import "../chunk-TSLRTZYR.mjs";
4
+ } from "../chunk-ZUOZ5KXV.mjs";
6
5
  import "../chunk-DKEJZ4FI.mjs";
7
- import "../chunk-REY5WMXY.mjs";
8
- import "../chunk-SF3BG2IA.mjs";
6
+ import "../chunk-TSLRTZYR.mjs";
7
+ import "../chunk-5IKZJVZZ.mjs";
8
+ import "../chunk-V7HUK4A5.mjs";
9
+ import "../chunk-XQ32SABC.mjs";
9
10
  import "../chunk-KVV3JBSN.mjs";
10
- import "../chunk-2GOOGBD6.mjs";
11
- import "../chunk-6E6XTHTG.mjs";
12
11
  import "../chunk-ZQZC634I.mjs";
12
+ import "../chunk-2GOOGBD6.mjs";
13
13
  import "../chunk-2FBDBRC5.mjs";
14
14
  import "../chunk-C5I7KXHK.mjs";
15
15
  import "../chunk-MTDFKNXX.mjs";
16
+ import "../chunk-6E6XTHTG.mjs";
16
17
  import "../chunk-E3GRJXXJ.mjs";
17
18
  import "../chunk-4UEJOM6W.mjs";
18
19
  export {
package/dist/doctor.mjs CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  formatReportMarkdown,
5
5
  rollupStatus,
6
6
  runAll
7
- } from "./chunk-S2XSNVXF.mjs";
7
+ } from "./chunk-ANX7Q4F5.mjs";
8
8
  import "./chunk-E3GRJXXJ.mjs";
9
9
  import "./chunk-4UEJOM6W.mjs";
10
10
  export {
package/dist/index.mjs CHANGED
@@ -1,22 +1,11 @@
1
1
  #!/usr/bin/env node
2
- import {
3
- CATEGORIES,
4
- formatReportMarkdown,
5
- runAll
6
- } from "./chunk-S2XSNVXF.mjs";
7
- import {
8
- buildIssueBody,
9
- buildIssueUrl,
10
- decideTransport,
11
- redactIssueBody
12
- } from "./chunk-DPGMKSSA.mjs";
13
2
  import {
14
3
  attachToDaemon
15
- } from "./chunk-E7GU4PUX.mjs";
4
+ } from "./chunk-HAO6U55U.mjs";
16
5
  import {
17
6
  ensureDaemon,
18
7
  startDaemon
19
- } from "./chunk-MIHIG4M4.mjs";
8
+ } from "./chunk-OUQRRFAU.mjs";
20
9
  import "./chunk-LGH5BSUY.mjs";
21
10
  import "./chunk-6YMQVLFX.mjs";
22
11
  import "./chunk-TIWHN4IW.mjs";
@@ -35,31 +24,53 @@ import {
35
24
  registerTools,
36
25
  saveToolConfig,
37
26
  watchToolConfig
38
- } from "./chunk-OOSSV7G3.mjs";
39
- import "./chunk-TSLRTZYR.mjs";
27
+ } from "./chunk-ZUOZ5KXV.mjs";
40
28
  import "./chunk-DKEJZ4FI.mjs";
29
+ import "./chunk-TSLRTZYR.mjs";
41
30
  import {
42
31
  watchActiveProfile,
43
32
  watchReinit
44
33
  } from "./chunk-3LUO5ATM.mjs";
34
+ import {
35
+ CATEGORIES,
36
+ formatReportMarkdown,
37
+ runAll
38
+ } from "./chunk-ANX7Q4F5.mjs";
39
+ import {
40
+ buildIssueBody,
41
+ buildIssueUrl,
42
+ decideTransport,
43
+ redactIssueBody
44
+ } from "./chunk-DPGMKSSA.mjs";
45
45
  import {
46
46
  isMainModule
47
47
  } from "./chunk-GPUGKWXH.mjs";
48
48
  import "./chunk-HMKLWVXB.mjs";
49
+ import "./chunk-5IKZJVZZ.mjs";
49
50
  import {
50
51
  hydrateCloudHistoryEntry,
51
52
  syncCloudHistory
52
- } from "./chunk-REY5WMXY.mjs";
53
+ } from "./chunk-V7HUK4A5.mjs";
53
54
  import {
54
55
  PerplexityClient
55
- } from "./chunk-SF3BG2IA.mjs";
56
+ } from "./chunk-XQ32SABC.mjs";
56
57
  import "./chunk-KVV3JBSN.mjs";
58
+ import {
59
+ exportThread
60
+ } from "./chunk-ZQZC634I.mjs";
57
61
  import {
58
62
  getImpitRuntimeDir,
59
63
  getModelsCacheInfo,
60
64
  isImpitAvailable,
61
65
  refreshAccountInfo
62
66
  } from "./chunk-2GOOGBD6.mjs";
67
+ import {
68
+ findBrowser
69
+ } from "./chunk-2FBDBRC5.mjs";
70
+ import {
71
+ getUnsealMaterial
72
+ } from "./chunk-C5I7KXHK.mjs";
73
+ import "./chunk-MTDFKNXX.mjs";
63
74
  import {
64
75
  append,
65
76
  countAll,
@@ -80,16 +91,6 @@ import {
80
91
  update,
81
92
  upsertFromCloud
82
93
  } from "./chunk-6E6XTHTG.mjs";
83
- import {
84
- exportThread
85
- } from "./chunk-ZQZC634I.mjs";
86
- import {
87
- findBrowser
88
- } from "./chunk-2FBDBRC5.mjs";
89
- import {
90
- getUnsealMaterial
91
- } from "./chunk-C5I7KXHK.mjs";
92
- import "./chunk-MTDFKNXX.mjs";
93
94
  import {
94
95
  getActiveName
95
96
  } from "./chunk-E3GRJXXJ.mjs";
@@ -0,0 +1,56 @@
1
+ /** A single declared argument of a prompt template. */
2
+ export interface PromptArg {
3
+ name: string;
4
+ description: string;
5
+ required: boolean;
6
+ }
7
+ /** A prompt as persisted on disk (no computed flags). */
8
+ export interface StoredPrompt {
9
+ name: string;
10
+ description: string;
11
+ arguments: PromptArg[];
12
+ template: string;
13
+ }
14
+ /** A merged prompt as rendered in the dashboard + registered with the server. */
15
+ export interface PromptDef extends StoredPrompt {
16
+ isBuiltin: boolean;
17
+ isModified: boolean;
18
+ }
19
+ /** On-disk shape of `prompts.json`. */
20
+ export interface PromptsConfig {
21
+ /** Built-in name → user override of that built-in. */
22
+ overrides: Record<string, StoredPrompt>;
23
+ /** Fully user-defined prompts. */
24
+ custom: StoredPrompt[];
25
+ }
26
+ /** Valid custom slash-command name: lowercase, digits, hyphens; leading letter. */
27
+ export declare const CUSTOM_NAME_RE: RegExp;
28
+ /**
29
+ * Shipped prompts. Always present (unless overridden); cannot be deleted.
30
+ * Names mix the original dotted built-ins (kept for back-compat) with the
31
+ * hyphenated convention recommended for new custom prompts.
32
+ */
33
+ export declare const BUILTIN_PROMPTS: StoredPrompt[];
34
+ /** Absolute path to the prompts file. */
35
+ export declare function promptsConfigPath(configDir?: string): string;
36
+ /** Read + normalize `prompts.json`. Returns an empty config on miss/parse error. */
37
+ export declare function readPromptsConfig(configDir?: string): PromptsConfig;
38
+ /** Atomically persist `prompts.json` (creates the config dir if needed). */
39
+ export declare function writePromptsConfig(config: PromptsConfig, configDir?: string): void;
40
+ /**
41
+ * Merge built-ins + overrides + custom into the flat list the UI/server use.
42
+ * Built-ins come first (overridden in place), then custom prompts. A custom
43
+ * prompt may not shadow a built-in name.
44
+ */
45
+ export declare function mergePrompts(config: PromptsConfig): PromptDef[];
46
+ /**
47
+ * Upsert a prompt. A built-in name writes/updates an override; any other name
48
+ * upserts the custom list. Returns a new config (pure).
49
+ */
50
+ export declare function upsertPrompt(config: PromptsConfig, prompt: StoredPrompt): PromptsConfig;
51
+ /** Remove a custom prompt by name. Built-ins are unaffected. */
52
+ export declare function deleteCustomPrompt(config: PromptsConfig, name: string): PromptsConfig;
53
+ /** Clear a built-in's override, reverting it to the shipped default. */
54
+ export declare function resetBuiltin(config: PromptsConfig, name: string): PromptsConfig;
55
+ /** Replace `{arg}` placeholders with provided values (missing → empty string). */
56
+ export declare function substituteTemplate(template: string, args: Record<string, unknown>): string;
@@ -0,0 +1,27 @@
1
+ import {
2
+ BUILTIN_PROMPTS,
3
+ CUSTOM_NAME_RE,
4
+ deleteCustomPrompt,
5
+ mergePrompts,
6
+ promptsConfigPath,
7
+ readPromptsConfig,
8
+ resetBuiltin,
9
+ substituteTemplate,
10
+ upsertPrompt,
11
+ writePromptsConfig
12
+ } from "./chunk-5IKZJVZZ.mjs";
13
+ import "./chunk-MTDFKNXX.mjs";
14
+ import "./chunk-E3GRJXXJ.mjs";
15
+ import "./chunk-4UEJOM6W.mjs";
16
+ export {
17
+ BUILTIN_PROMPTS,
18
+ CUSTOM_NAME_RE,
19
+ deleteCustomPrompt,
20
+ mergePrompts,
21
+ promptsConfigPath,
22
+ readPromptsConfig,
23
+ resetBuiltin,
24
+ substituteTemplate,
25
+ upsertPrompt,
26
+ writePromptsConfig
27
+ };
package/dist/prompts.d.ts CHANGED
@@ -1,2 +1,11 @@
1
1
  import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ /**
3
+ * Register all prompts — shipped built-ins (merged with any user overrides)
4
+ * plus user-defined custom prompts from `<configDir>/prompts.json`. Called by
5
+ * the stdio entrypoint once at startup and by the daemon per HTTP request
6
+ * (which is why daemon clients pick up edits on their next connection).
7
+ *
8
+ * Reads the config synchronously; never throws. A single malformed prompt is
9
+ * logged and skipped rather than failing the whole registration.
10
+ */
2
11
  export declare function registerPrompts(server: McpServer): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "perplexity-user-mcp",
3
- "version": "0.8.50",
3
+ "version": "0.8.53",
4
4
  "mcpName": "io.github.Automations-Project/perplexity-user-mcp",
5
5
  "type": "module",
6
6
  "description": "Perplexity AI MCP server — browser automation for search, reasoning, research, and compute. Not affiliated with Perplexity AI, Inc.",
@@ -88,6 +88,10 @@
88
88
  "types": "./dist/config.d.ts",
89
89
  "import": "./dist/config.mjs"
90
90
  },
91
+ "./prompts-config": {
92
+ "types": "./dist/prompts-config.d.ts",
93
+ "import": "./dist/prompts-config.mjs"
94
+ },
91
95
  "./refresh": {
92
96
  "types": "./dist/refresh.d.ts",
93
97
  "import": "./dist/refresh.mjs"
File without changes
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  OFFSCREEN_POSITION_ARG
3
3
  } from "./chunk-KVV3JBSN.mjs";
4
- import {
5
- impitFetchJson,
6
- isImpitAvailable
7
- } from "./chunk-2GOOGBD6.mjs";
8
4
  import {
9
5
  FORMAT_TO_CONTENT_TYPE,
10
6
  exportThread,
11
7
  resolveExportApiFormat
12
8
  } from "./chunk-ZQZC634I.mjs";
9
+ import {
10
+ impitFetchJson,
11
+ isImpitAvailable
12
+ } from "./chunk-2GOOGBD6.mjs";
13
13
  import {
14
14
  ASI_ACCESS_ENDPOINT,
15
15
  AUTH_SESSION_ENDPOINT,