perplexity-user-mcp 0.8.39 → 0.8.44

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.
Files changed (133) hide show
  1. package/README.md +5 -0
  2. package/dist/attachments.d.ts +10 -20
  3. package/dist/browser-window.d.ts +1 -0
  4. package/dist/cf-warmup.d.ts +32 -0
  5. package/dist/checks/browser.d.ts +12 -100
  6. package/dist/checks/config.d.ts +25 -91
  7. package/dist/checks/ide.d.ts +31 -89
  8. package/dist/checks/mcp.d.ts +12 -61
  9. package/dist/checks/native-deps.d.ts +46 -131
  10. package/dist/checks/network.d.ts +13 -71
  11. package/dist/checks/probe.d.ts +20 -92
  12. package/dist/checks/profiles.d.ts +13 -99
  13. package/dist/checks/profiles.mjs +35 -0
  14. package/dist/checks/runtime.d.ts +24 -89
  15. package/dist/checks/vault.d.ts +13 -142
  16. package/dist/checks/vault.mjs +6 -11
  17. package/dist/{chunk-T6ARJK2P.mjs → chunk-2B5OQUXR.mjs} +6 -6
  18. package/dist/{chunk-2FPGJKCA.mjs → chunk-2EE7MNP2.mjs} +2 -2
  19. package/dist/{chunk-NJX4RBO6.mjs → chunk-2OVLCZHU.mjs} +28 -3
  20. package/dist/{chunk-WDIW33DA.mjs → chunk-3LUO5ATM.mjs} +1 -1
  21. package/dist/{chunk-B65IJQZJ.mjs → chunk-6E6XTHTG.mjs} +1 -1
  22. package/dist/{chunk-S677V2JU.mjs → chunk-C5I7KXHK.mjs} +32 -2
  23. package/dist/{chunk-TDXETAQT.mjs → chunk-DKEJZ4FI.mjs} +1 -1
  24. package/dist/{chunk-U7QPUNRH.mjs → chunk-DXR6EEZH.mjs} +26 -7
  25. package/dist/{chunk-HJIXH6CL.mjs → chunk-E3GRJXXJ.mjs} +2 -0
  26. package/dist/{chunk-RK4EBZJ3.mjs → chunk-E75J42W5.mjs} +11 -8
  27. package/dist/{chunk-452DK6OS.mjs → chunk-FNHYUE22.mjs} +2 -2
  28. package/dist/{chunk-D254EFYB.mjs → chunk-GBI2U336.mjs} +1 -1
  29. package/dist/chunk-GPUGKWXH.mjs +17 -0
  30. package/dist/{chunk-HNSPNCFH.mjs → chunk-KSNV3ZVY.mjs} +1 -1
  31. package/dist/{chunk-XTRJSV72.mjs → chunk-LGH5BSUY.mjs} +1 -1
  32. package/dist/{chunk-KJFX2ZXR.mjs → chunk-NMKNEEZB.mjs} +1 -1
  33. package/dist/{chunk-FKQ3HP4Q.mjs → chunk-TIWHN4IW.mjs} +1 -1
  34. package/dist/{chunk-V4U3JM4R.mjs → chunk-TSLRTZYR.mjs} +1 -1
  35. package/dist/{chunk-DQQISMYN.mjs → chunk-V4LHDNWJ.mjs} +2 -2
  36. package/dist/{chunk-C3HPFFTD.mjs → chunk-WHVJ724K.mjs} +84 -44
  37. package/dist/cli.d.ts +14 -1298
  38. package/dist/cli.mjs +35 -27
  39. package/dist/client.d.ts +27 -24
  40. package/dist/client.mjs +6 -6
  41. package/dist/cloud-sync.d.ts +65 -42
  42. package/dist/cloud-sync.mjs +8 -8
  43. package/dist/config.d.ts +35 -39
  44. package/dist/config.mjs +3 -3
  45. package/dist/cookie-jar.d.ts +77 -0
  46. package/dist/daemon/attach.d.ts +10 -11
  47. package/dist/daemon/attach.mjs +19 -17
  48. package/dist/daemon/audit.d.ts +5 -7
  49. package/dist/daemon/audit.mjs +2 -2
  50. package/dist/daemon/client-http.d.ts +10 -16
  51. package/dist/daemon/client-http.mjs +17 -17
  52. package/dist/daemon/index.d.ts +17 -14
  53. package/dist/daemon/index.mjs +18 -18
  54. package/dist/daemon/install-tunnel.d.ts +8 -34
  55. package/dist/daemon/install-tunnel.mjs +2 -2
  56. package/dist/daemon/launcher.d.ts +24 -29
  57. package/dist/daemon/launcher.mjs +16 -16
  58. package/dist/daemon/local-tokens.d.ts +23 -0
  59. package/dist/daemon/lockfile.d.ts +10 -12
  60. package/dist/daemon/lockfile.mjs +2 -2
  61. package/dist/daemon/oauth-consent-cache.d.ts +86 -0
  62. package/dist/daemon/oauth-provider.d.ts +132 -0
  63. package/dist/daemon/public-pages.d.ts +9 -0
  64. package/dist/daemon/security.d.ts +52 -0
  65. package/dist/daemon/server.d.ts +12 -83
  66. package/dist/daemon/server.mjs +11 -11
  67. package/dist/daemon/token.d.ts +7 -9
  68. package/dist/daemon/token.mjs +2 -2
  69. package/dist/daemon/tunnel-providers/cloudflared-named-setup.d.ts +140 -0
  70. package/dist/daemon/tunnel-providers/cloudflared-named.d.ts +45 -0
  71. package/dist/daemon/tunnel-providers/cloudflared-quick.d.ts +8 -0
  72. package/dist/daemon/tunnel-providers/index.d.ts +16 -327
  73. package/dist/daemon/tunnel-providers/index.mjs +3 -3
  74. package/dist/daemon/tunnel-providers/ngrok-config.d.ts +18 -0
  75. package/dist/daemon/tunnel-providers/ngrok.d.ts +68 -0
  76. package/dist/daemon/tunnel-providers/types.d.ts +56 -0
  77. package/dist/daemon/tunnel.d.ts +5 -7
  78. package/dist/debug-tracer.d.ts +2 -0
  79. package/dist/doctor-report.d.ts +17 -22
  80. package/dist/doctor.d.ts +12 -44
  81. package/dist/doctor.mjs +2 -2
  82. package/dist/export.d.ts +11 -18
  83. package/dist/export.mjs +4 -4
  84. package/dist/format.d.ts +52 -0
  85. package/dist/fs-utils.d.ts +8 -0
  86. package/dist/health-check.d.ts +1 -108
  87. package/dist/health-check.mjs +3 -3
  88. package/dist/history-store.d.ts +29 -65
  89. package/dist/history-store.mjs +2 -2
  90. package/dist/impit-login-runner.d.ts +1 -469
  91. package/dist/impit-login-runner.mjs +4 -4
  92. package/dist/index.d.ts +25 -149
  93. package/dist/index.mjs +22 -20
  94. package/dist/is-main-module.d.ts +9 -0
  95. package/dist/login-runner.d.ts +1 -333
  96. package/dist/login-runner.mjs +13 -13
  97. package/dist/login.d.ts +5 -0
  98. package/dist/logout.d.ts +2 -28
  99. package/dist/logout.mjs +3 -2
  100. package/dist/manual-login-runner.d.ts +1 -150
  101. package/dist/manual-login-runner.mjs +11 -11
  102. package/dist/{native-deps-IE4B55EL.mjs → native-deps-FCSYDL4W.mjs} +4 -4
  103. package/dist/native-deps.d.ts +36 -0
  104. package/dist/package-version.d.ts +1 -0
  105. package/dist/profiles.d.ts +41 -41
  106. package/dist/profiles.mjs +1 -1
  107. package/dist/prompts.d.ts +2 -0
  108. package/dist/redact.d.ts +14 -142
  109. package/dist/refresh.d.ts +11 -16
  110. package/dist/refresh.mjs +4 -4
  111. package/dist/reinit-watcher.d.ts +15 -24
  112. package/dist/reinit-watcher.mjs +2 -2
  113. package/dist/resources.d.ts +5 -0
  114. package/dist/safe-write.d.ts +16 -0
  115. package/dist/session-metadata.d.ts +45 -0
  116. package/dist/tool-config.d.ts +10 -0
  117. package/dist/tools.d.ts +23 -0
  118. package/dist/tty-prompt.d.ts +18 -34
  119. package/dist/vault.d.ts +114 -34
  120. package/dist/vault.mjs +6 -4
  121. package/dist/viewer-detect.d.ts +2 -4
  122. package/dist/viewers.d.ts +13 -18
  123. package/dist/viewers.mjs +1 -1
  124. package/package.json +3 -3
  125. package/dist/cloud-sync.d-Cqt6y18U.d.ts +0 -42
  126. package/dist/doctor.d-CXmUqOXX.d.ts +0 -43
  127. package/dist/history-store.d-BzjBF2m3.d.ts +0 -65
  128. package/dist/native-deps-BNThFHxa.d.ts +0 -175
  129. package/dist/profiles.d-DqS1oZWr.d.ts +0 -41
  130. package/dist/session-metadata-B9aV_n5g.d.ts +0 -148
  131. package/dist/vault.d-BSJWDLhp.d.ts +0 -37
  132. package/dist/viewer-detect.d-HWGnyFAA.d.ts +0 -4
  133. package/dist/viewers.d-BGCK6sw6.d.ts +0 -10
package/README.md CHANGED
@@ -377,6 +377,11 @@ Logging in still goes through the CLI (`npx perplexity-user-mcp login`) — the
377
377
  - A browser runtime — any of: real Chrome, Microsoft Edge, Brave, system Chromium, or patchright's bundled Chromium (see the [Browser requirement](#browser-requirement) section)
378
378
  - An active Perplexity account (free tier works; Pro/Max unlock reason/research/compute)
379
379
 
380
+ ## Troubleshooting
381
+
382
+ - **External MCP clients hitting "Vault locked":** [Troubleshooting external MCP clients](../../docs/troubleshooting/external-mcp-clients.md)
383
+ - **Vault unseal model and recovery:** [docs/vault-unseal.md](../../docs/vault-unseal.md)
384
+
380
385
  ## Issues
381
386
 
382
387
  Bug reports and feature requests: <https://github.com/Automations-Project/VSCode-Perplexity-MCP/issues>.
@@ -1,20 +1,10 @@
1
- interface DownloadedAttachment {
2
- filename: string;
3
- path: string;
4
- sizeBytes: number;
5
- mimeType?: string;
6
- kind: "image" | "file";
7
- }
8
-
9
- declare const MAX_ATTACHMENT_BYTES: number;
10
- declare function sanitizeAttachmentFilename(name: string): string;
11
- declare function inferAttachmentKind(mimeType?: string): "image" | "file";
12
- declare function downloadAttachment(options: {
13
- download: (url: string, targetPath: string) => Promise<unknown>;
14
- url: string;
15
- attachmentsDir: string;
16
- filename?: string;
17
- mimeType?: string;
18
- }): Promise<DownloadedAttachment>;
19
-
20
- export { type DownloadedAttachment, MAX_ATTACHMENT_BYTES, downloadAttachment, inferAttachmentKind, sanitizeAttachmentFilename };
1
+ export function sanitizeAttachmentFilename(name: any): string;
2
+ export function inferAttachmentKind(mimeType: any): "image" | "file";
3
+ export function downloadAttachment(options: any): Promise<{
4
+ filename: string;
5
+ path: string;
6
+ sizeBytes: number;
7
+ mimeType: any;
8
+ kind: string;
9
+ }>;
10
+ export const MAX_ATTACHMENT_BYTES: number;
@@ -0,0 +1 @@
1
+ export function minimizePageWindow(page: any): Promise<boolean>;
@@ -0,0 +1,32 @@
1
+ import { type PlaywrightCookie } from "./config.js";
2
+ export interface WarmCloudflareOptions {
3
+ /** Hard cap on the initial page.goto. Default 15_000ms. */
4
+ navigationTimeoutMs?: number;
5
+ /** How often to recheck context cookies for `cf_clearance`. Default 250ms. */
6
+ pollIntervalMs?: number;
7
+ /** Total wall-clock budget for the cookie poll loop after navigation. Default 10_000ms. */
8
+ cookieWaitMs?: number;
9
+ }
10
+ export interface WarmCloudflareResult {
11
+ /**
12
+ * True iff the browser launched and navigation succeeded. May be true even
13
+ * when `hasCfClearance` is false — distinguishes "browser unusable" from
14
+ * "browser fine, CF just didn't issue clearance this time".
15
+ */
16
+ ok: boolean;
17
+ /** All cookies present in the ephemeral context at teardown. Empty on launch failure. */
18
+ cookies: PlaywrightCookie[];
19
+ /** Whether `cf_clearance` was observed in `cookies`. */
20
+ hasCfClearance: boolean;
21
+ /** Wall-clock duration of the warmup attempt, in milliseconds. */
22
+ elapsedMs: number;
23
+ /** Populated when `ok=false`. Single-line, human-readable. */
24
+ error?: string;
25
+ }
26
+ /**
27
+ * Brief headless launch to capture cf_clearance for the impit-login flow.
28
+ *
29
+ * Always returns a result object — never throws. Caller falls back to the
30
+ * full browser-based login when ok=false or hasCfClearance=false.
31
+ */
32
+ export declare function warmCloudflare(opts?: WarmCloudflareOptions): Promise<WarmCloudflareResult>;
@@ -1,100 +1,12 @@
1
- import { spawn } from 'node:child_process';
2
-
3
- const CATEGORY = "browser";
4
-
5
- /**
6
- * Read the Chrome-family browser's version string without launching the
7
- * browser GUI.
8
- *
9
- * Why this is non-trivial: on Windows, `chrome.exe --version` invoked from a
10
- * non-console parent (the VS Code extension host) forks the browser process —
11
- * the original exits with code 0 and empty stdout (which is why the doctor
12
- * report's `chrome-family` message was blank), and the forked children stay
13
- * alive as visible Chrome windows. Every `runDoctor()` call (Run, Deep check,
14
- * Capture diagnostics, Export) was therefore spawning a permanent visible
15
- * window.
16
- *
17
- * Fix: on Windows, query the PE header's ProductVersion via PowerShell's
18
- * `Get-Item ... .VersionInfo.ProductVersion` — no browser launch, returns
19
- * the same string the user sees in File Properties → Details. On macOS /
20
- * Linux, `--version` is a true CLI app contract and remains safe.
21
- */
22
- function probeVersion(path) {
23
- if (process.platform === "win32") {
24
- return new Promise((resolve, reject) => {
25
- // Single-quote escape: PowerShell single-quoted strings need '' to
26
- // represent a literal '. -LiteralPath bypasses wildcard expansion so
27
- // bracketed install paths (e.g. Program Files (x86)) are safe.
28
- const escaped = path.replace(/'/g, "''");
29
- const child = spawn(
30
- "powershell.exe",
31
- [
32
- "-NoProfile",
33
- "-NonInteractive",
34
- "-Command",
35
- `(Get-Item -LiteralPath '${escaped}').VersionInfo.ProductVersion`,
36
- ],
37
- { timeout: 3000, windowsHide: true },
38
- );
39
- let out = "";
40
- let err = "";
41
- child.stdout?.on("data", (d) => { out += d.toString(); });
42
- child.stderr?.on("data", (d) => { err += d.toString(); });
43
- child.on("close", (code) => {
44
- const trimmed = out.trim();
45
- if (code === 0 && trimmed) resolve(trimmed);
46
- else reject(new Error(err.trim() || `version probe exited ${code}`));
47
- });
48
- child.on("error", reject);
49
- });
50
- }
51
- return new Promise((resolve, reject) => {
52
- const child = spawn(path, ["--version"], { timeout: 2000 });
53
- let out = "";
54
- let err = "";
55
- child.stdout?.on("data", (d) => { out += d.toString(); });
56
- child.stderr?.on("data", (d) => { err += d.toString(); });
57
- child.on("close", (code) => {
58
- if (code === 0) resolve(out.trim() || err.trim());
59
- else reject(new Error(err.trim() || `version probe exited ${code}`));
60
- });
61
- child.on("error", reject);
62
- });
63
- }
64
-
65
- async function run(opts = {}) {
66
- const results = [];
67
- const findChrome = opts.findChromeOverride ?? (await import('../config.d.ts')).findChromeExecutable;
68
- const versionProbe = opts.versionProbeOverride ?? probeVersion;
69
-
70
- let chromePath = null;
71
- try { chromePath = findChrome(); } catch { chromePath = null; }
72
-
73
- if (!chromePath) {
74
- results.push({
75
- category: CATEGORY,
76
- name: "chrome-family",
77
- status: "fail",
78
- message: "No Chrome / Edge / Chromium binary found on PATH or in standard locations.",
79
- hint: "Run `npx perplexity-user-mcp install-browser` (Phase 4) or install Chrome/Edge manually.",
80
- });
81
- return results;
82
- }
83
-
84
- try {
85
- const v = await versionProbe(chromePath);
86
- results.push({ category: CATEGORY, name: "chrome-family", status: "pass", message: v });
87
- } catch (err) {
88
- results.push({ category: CATEGORY, name: "chrome-family", status: "pass", message: chromePath });
89
- results.push({
90
- category: CATEGORY,
91
- name: "chrome-version",
92
- status: "warn",
93
- message: `version probe failed: ${err.message}`,
94
- });
95
- }
96
-
97
- return results;
98
- }
99
-
100
- export { run };
1
+ export function run(opts?: {}): Promise<{
2
+ category: string;
3
+ name: string;
4
+ status: string;
5
+ message: string;
6
+ hint: string;
7
+ }[] | {
8
+ category: string;
9
+ name: string;
10
+ status: string;
11
+ message: any;
12
+ }[]>;
@@ -1,91 +1,25 @@
1
- import { existsSync, statSync, readFileSync } from 'node:fs';
2
- import { join } from 'node:path';
3
-
4
- const CATEGORY = "config";
5
-
6
- async function run(opts = {}) {
7
- const dir = opts.configDir;
8
- const results = [];
9
-
10
- if (!existsSync(dir)) {
11
- results.push({
12
- category: CATEGORY,
13
- name: "config-dir",
14
- status: "fail",
15
- message: `Config dir not found: ${dir}`,
16
- hint: "Run `npx perplexity-user-mcp login` to initialize it.",
17
- });
18
- return results;
19
- }
20
- results.push({
21
- category: CATEGORY,
22
- name: "config-dir",
23
- status: "pass",
24
- message: `Config dir present at ${dir}`,
25
- });
26
-
27
- if (process.platform !== "win32") {
28
- const mode = statSync(dir).mode & 0o777;
29
- if (mode & 0o077) {
30
- results.push({
31
- category: CATEGORY,
32
- name: "config-perms",
33
- status: "warn",
34
- message: `Config dir is world/group readable (mode 0${mode.toString(8)})`,
35
- hint: "Run `chmod 700 ~/.perplexity-mcp`.",
36
- });
37
- } else {
38
- results.push({ category: CATEGORY, name: "config-perms", status: "pass", message: "0700" });
39
- }
40
- } else {
41
- results.push({ category: CATEGORY, name: "config-perms", status: "skip", message: "NTFS ACL (see icacls)" });
42
- }
43
-
44
- const activePath = join(dir, "active");
45
- if (!existsSync(activePath)) {
46
- results.push({
47
- category: CATEGORY,
48
- name: "active-pointer",
49
- status: "warn",
50
- message: "No active profile set.",
51
- hint: "Add an account to create and activate your first profile.",
52
- action: { label: "Add account", commandId: "Perplexity.addAccount" },
53
- });
54
- } else {
55
- const name = readFileSync(activePath, "utf8").trim();
56
- const metaPath = join(dir, "profiles", name, "meta.json");
57
- if (!existsSync(metaPath)) {
58
- results.push({
59
- category: CATEGORY,
60
- name: "active-pointer",
61
- status: "fail",
62
- message: `active -> '${name}' but profile does not exist`,
63
- hint: "Run `npx perplexity-user-mcp list-accounts` and pick a real profile.",
64
- });
65
- } else {
66
- results.push({ category: CATEGORY, name: "active-pointer", status: "pass", message: name });
67
- }
68
- }
69
-
70
- const cfgJson = join(dir, "config.json");
71
- if (!existsSync(cfgJson)) {
72
- results.push({ category: CATEGORY, name: "config-json", status: "skip", message: "optional file absent" });
73
- } else {
74
- try {
75
- JSON.parse(readFileSync(cfgJson, "utf8"));
76
- results.push({ category: CATEGORY, name: "config-json", status: "pass", message: "valid" });
77
- } catch (err) {
78
- results.push({
79
- category: CATEGORY,
80
- name: "config-json",
81
- status: "warn",
82
- message: `config.json malformed: ${err.message}`,
83
- hint: "Delete or fix the file — doctor reads it for reporting.githubIssueButton etc.",
84
- });
85
- }
86
- }
87
-
88
- return results;
89
- }
90
-
91
- export { run };
1
+ export function run(opts?: {}): Promise<({
2
+ category: string;
3
+ name: string;
4
+ status: string;
5
+ message: string;
6
+ hint?: undefined;
7
+ action?: undefined;
8
+ } | {
9
+ category: string;
10
+ name: string;
11
+ status: string;
12
+ message: string;
13
+ hint: string;
14
+ action?: undefined;
15
+ } | {
16
+ category: string;
17
+ name: string;
18
+ status: string;
19
+ message: string;
20
+ hint: string;
21
+ action: {
22
+ label: string;
23
+ commandId: string;
24
+ };
25
+ })[]>;
@@ -1,89 +1,31 @@
1
- const CATEGORY = "ide";
2
-
3
- async function run(opts = {}) {
4
- const results = [];
5
- const statuses = opts.ideStatuses;
6
-
7
- if (!statuses) {
8
- results.push({
9
- category: CATEGORY,
10
- name: "ide-audit",
11
- status: "skip",
12
- message: "IDE audit requires the VS Code extension (or pass ideStatuses explicitly).",
13
- });
14
- return results;
15
- }
16
-
17
- for (const [id, s] of Object.entries(statuses)) {
18
- if (!s.detected) {
19
- results.push({ category: CATEGORY, name: id, status: "skip", message: `${s.displayName} not installed` });
20
- continue;
21
- }
22
- if (!s.configured) {
23
- results.push({
24
- category: CATEGORY,
25
- name: id,
26
- status: "warn",
27
- message: `${s.displayName} installed but Perplexity MCP is not configured.`,
28
- hint: "Open the IDEs dashboard tab and click Configure.",
29
- action: { label: "Configure", commandId: "Perplexity.generateConfigs", args: [id] },
30
- });
31
- continue;
32
- }
33
- // Order of evaluation: stale-args (the launcher path no longer exists)
34
- // wins over a bad-command warning. A stale launcher is the higher-impact
35
- // breakage — the IDE will fail to spawn anything at all — so the doctor
36
- // surfaces that first and elides the command-health note for the same row.
37
- if (s.health === "stale") {
38
- results.push({
39
- category: CATEGORY,
40
- name: id,
41
- status: "warn",
42
- message: `${s.displayName} config is stale.`,
43
- hint: "Click Configure to refresh.",
44
- action: { label: "Refresh config", commandId: "Perplexity.generateConfigs", args: [id] },
45
- });
46
- continue;
47
- }
48
- if (s.commandHealth && s.commandHealth !== "ok") {
49
- results.push({
50
- category: CATEGORY,
51
- name: id,
52
- status: "warn",
53
- message: `${s.displayName} configured but command path is ${s.commandHealth} — re-run 'Configure for All' to refresh.`,
54
- hint: "The MCP config's `command` field doesn't look like a Node.js binary. Re-running Configure rewrites it with a resolved Node path.",
55
- action: { label: "Refresh config", commandId: "Perplexity.generateConfigs", args: [id] },
56
- });
57
- continue;
58
- }
59
- results.push({ category: CATEGORY, name: id, status: "pass", message: `${s.displayName} configured` });
60
- }
61
-
62
- try {
63
- const { detectAllViewers } = await import('../viewer-detect.d-HWGnyFAA.d.ts');
64
- const viewers = await detectAllViewers();
65
- const detected = Object.entries(viewers)
66
- .filter(([, present]) => present)
67
- .map(([id]) => id);
68
- results.push({
69
- category: CATEGORY,
70
- name: "mdViewers",
71
- status: "pass",
72
- message: detected.length > 0
73
- ? `Detected MD viewers: ${detected.join(", ")}`
74
- : "No external MD viewers detected (VS Code preview and Rich View remain available).",
75
- detail: { viewers },
76
- });
77
- } catch (err) {
78
- results.push({
79
- category: CATEGORY,
80
- name: "mdViewers",
81
- status: "warn",
82
- message: `Viewer detection failed: ${(err instanceof Error ? err.message : String(err))}`,
83
- });
84
- }
85
-
86
- return results;
87
- }
88
-
89
- export { run };
1
+ export function run(opts?: {}): Promise<({
2
+ category: string;
3
+ name: string;
4
+ status: string;
5
+ message: string;
6
+ hint?: undefined;
7
+ action?: undefined;
8
+ detail?: undefined;
9
+ } | {
10
+ category: string;
11
+ name: string;
12
+ status: string;
13
+ message: string;
14
+ hint: string;
15
+ action: {
16
+ label: string;
17
+ commandId: string;
18
+ args: string[];
19
+ };
20
+ detail?: undefined;
21
+ } | {
22
+ category: string;
23
+ name: string;
24
+ status: string;
25
+ message: string;
26
+ detail: {
27
+ viewers: Record<string, boolean>;
28
+ };
29
+ hint?: undefined;
30
+ action?: undefined;
31
+ })[]>;
@@ -1,61 +1,12 @@
1
- import { existsSync, readFileSync } from 'node:fs';
2
- import { join } from 'node:path';
3
-
4
- const CATEGORY = "mcp";
5
- const KNOWN_PROFILES = new Set(["read-only", "full", "custom"]);
6
-
7
- async function run(opts = {}) {
8
- const results = [];
9
- const dir = opts.configDir;
10
- const toolCfgPath = join(dir, "tools-config.json");
11
-
12
- if (!existsSync(toolCfgPath)) {
13
- results.push({
14
- category: CATEGORY,
15
- name: "tool-config",
16
- status: "skip",
17
- message: "no tools-config.json (default: full)",
18
- });
19
- results.push({
20
- category: CATEGORY,
21
- name: "enabled-tools",
22
- status: "pass",
23
- message: "default profile 'full'",
24
- });
25
- return results;
26
- }
27
- let cfg;
28
- try {
29
- cfg = JSON.parse(readFileSync(toolCfgPath, "utf8"));
30
- } catch (err) {
31
- results.push({
32
- category: CATEGORY,
33
- name: "tool-config",
34
- status: "fail",
35
- message: `tools-config.json malformed: ${err.message}`,
36
- hint: "Delete the file to restore defaults.",
37
- });
38
- return results;
39
- }
40
-
41
- if (!KNOWN_PROFILES.has(cfg.profile)) {
42
- results.push({
43
- category: CATEGORY,
44
- name: "tool-config",
45
- status: "warn",
46
- message: `unknown profile '${cfg.profile}' — falling back to 'full'`,
47
- });
48
- } else {
49
- results.push({ category: CATEGORY, name: "tool-config", status: "pass", message: `profile=${cfg.profile}` });
50
- }
51
- const count = cfg.profile === "custom"
52
- ? (cfg.customEnabled?.length ?? 0)
53
- : cfg.profile === "read-only"
54
- ? 9
55
- : 11;
56
- results.push({ category: CATEGORY, name: "enabled-tools", status: "pass", message: `${count} tools enabled` });
57
-
58
- return results;
59
- }
60
-
61
- export { run };
1
+ export function run(opts?: {}): Promise<{
2
+ category: string;
3
+ name: string;
4
+ status: string;
5
+ message: string;
6
+ }[] | {
7
+ category: string;
8
+ name: string;
9
+ status: string;
10
+ message: string;
11
+ hint: string;
12
+ }[]>;