mcp-trust 0.1.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.
Files changed (55) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +153 -0
  3. package/bin/mcp-trust.js +2 -0
  4. package/dist/checks/github.d.ts +4 -0
  5. package/dist/checks/github.js +175 -0
  6. package/dist/checks/github.js.map +1 -0
  7. package/dist/checks/index.d.ts +2 -0
  8. package/dist/checks/index.js +3 -0
  9. package/dist/checks/index.js.map +1 -0
  10. package/dist/checks/scorer.d.ts +2 -0
  11. package/dist/checks/scorer.js +109 -0
  12. package/dist/checks/scorer.js.map +1 -0
  13. package/dist/commands/audit.d.ts +9 -0
  14. package/dist/commands/audit.js +53 -0
  15. package/dist/commands/audit.js.map +1 -0
  16. package/dist/commands/index.d.ts +2 -0
  17. package/dist/commands/index.js +2 -0
  18. package/dist/commands/index.js.map +1 -0
  19. package/dist/index.d.ts +2 -0
  20. package/dist/index.js +96 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/prober/index.d.ts +1 -0
  23. package/dist/prober/index.js +2 -0
  24. package/dist/prober/index.js.map +1 -0
  25. package/dist/prober/spawner.d.ts +2 -0
  26. package/dist/prober/spawner.js +230 -0
  27. package/dist/prober/spawner.js.map +1 -0
  28. package/dist/readers/claude.d.ts +2 -0
  29. package/dist/readers/claude.js +48 -0
  30. package/dist/readers/claude.js.map +1 -0
  31. package/dist/readers/cline.d.ts +2 -0
  32. package/dist/readers/cline.js +58 -0
  33. package/dist/readers/cline.js.map +1 -0
  34. package/dist/readers/codex.d.ts +2 -0
  35. package/dist/readers/codex.js +104 -0
  36. package/dist/readers/codex.js.map +1 -0
  37. package/dist/readers/cursor.d.ts +2 -0
  38. package/dist/readers/cursor.js +53 -0
  39. package/dist/readers/cursor.js.map +1 -0
  40. package/dist/readers/index.d.ts +2 -0
  41. package/dist/readers/index.js +18 -0
  42. package/dist/readers/index.js.map +1 -0
  43. package/dist/reporters/index.d.ts +2 -0
  44. package/dist/reporters/index.js +3 -0
  45. package/dist/reporters/index.js.map +1 -0
  46. package/dist/reporters/json.d.ts +2 -0
  47. package/dist/reporters/json.js +23 -0
  48. package/dist/reporters/json.js.map +1 -0
  49. package/dist/reporters/terminal.d.ts +3 -0
  50. package/dist/reporters/terminal.js +120 -0
  51. package/dist/reporters/terminal.js.map +1 -0
  52. package/dist/types.d.ts +50 -0
  53. package/dist/types.js +2 -0
  54. package/dist/types.js.map +1 -0
  55. package/package.json +43 -0
package/dist/index.js ADDED
@@ -0,0 +1,96 @@
1
+ #!/usr/bin/env node
2
+ import pc from "picocolors";
3
+ import { runAudit } from "./commands/index.js";
4
+ const HELP = `${pc.bold("mcp-trust")} ${pc.gray("v0.1.0")}
5
+
6
+ Audit the MCP servers installed on your machine. Detects dead, dangerous,
7
+ or fake servers before they hit production.
8
+
9
+ ${pc.bold("Usage:")}
10
+ mcp-trust [command] [options]
11
+
12
+ ${pc.bold("Commands:")}
13
+ audit Probe all configured MCP servers and report health (default)
14
+ version Print version
15
+ help Show this message
16
+
17
+ ${pc.bold("Options:")}
18
+ --json Output machine-readable JSON
19
+ --config-only List configured servers without probing
20
+ --fail-on-dead Exit with code 1 if any server is dead, broken, or missing
21
+ --concurrency <n> Probe N servers in parallel (default: 4)
22
+ --no-health Skip GitHub/npm health lookups (faster)
23
+
24
+ ${pc.bold("Examples:")}
25
+ mcp-trust
26
+ mcp-trust audit --json
27
+ mcp-trust audit --fail-on-dead
28
+ mcp-trust audit --concurrency 1
29
+ `;
30
+ function parseArgs(argv) {
31
+ const args = argv.slice(2);
32
+ let command = "audit";
33
+ const options = {};
34
+ for (let i = 0; i < args.length; i++) {
35
+ const arg = args[i];
36
+ if (arg === "help" || arg === "--help" || arg === "-h") {
37
+ command = "help";
38
+ }
39
+ else if (arg === "version" || arg === "--version" || arg === "-v") {
40
+ command = "version";
41
+ }
42
+ else if (arg === "audit") {
43
+ command = "audit";
44
+ }
45
+ else if (arg === "--json") {
46
+ options.json = true;
47
+ }
48
+ else if (arg === "--config-only") {
49
+ options.configOnly = true;
50
+ }
51
+ else if (arg === "--fail-on-dead") {
52
+ options.failOnDead = true;
53
+ }
54
+ else if (arg === "--no-health") {
55
+ options.githubToken = ""; // signal to skip
56
+ }
57
+ else if (arg === "--concurrency") {
58
+ const next = args[++i];
59
+ const n = next ? parseInt(next, 10) : NaN;
60
+ if (!Number.isFinite(n) || n < 1) {
61
+ console.error(pc.red("error:") + " --concurrency requires a positive integer");
62
+ process.exit(2);
63
+ }
64
+ options.concurrency = n;
65
+ }
66
+ else {
67
+ console.error(pc.red("error:") + " unknown argument: " + arg);
68
+ console.error("Run " + pc.cyan("mcp-trust help") + " for usage");
69
+ process.exit(2);
70
+ }
71
+ }
72
+ return { command, options };
73
+ }
74
+ async function main() {
75
+ const { command, options } = parseArgs(process.argv);
76
+ if (command === "help") {
77
+ console.log(HELP);
78
+ return;
79
+ }
80
+ if (command === "version") {
81
+ console.log("mcp-trust v0.1.0");
82
+ return;
83
+ }
84
+ if (command === "audit") {
85
+ await runAudit(options);
86
+ return;
87
+ }
88
+ }
89
+ main().catch((err) => {
90
+ console.error(pc.red("fatal:") + " " + (err instanceof Error ? err.message : String(err)));
91
+ if (process.env.MCP_DOCTOR_DEBUG) {
92
+ console.error(err);
93
+ }
94
+ process.exit(1);
95
+ });
96
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export { probeServer } from "./spawner.js";
@@ -0,0 +1,2 @@
1
+ export { probeServer } from "./spawner.js";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/prober/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { ProbedServer, ServerConfig } from "../types.js";
2
+ export declare function probeServer(config: ServerConfig): Promise<ProbedServer>;
@@ -0,0 +1,230 @@
1
+ import { spawn } from "node:child_process";
2
+ const PROTOCOL_VERSION = "2024-11-05";
3
+ const PROBE_TIMEOUT_MS = 15_000;
4
+ const HANG_THRESHOLD_MS = 5_000;
5
+ function send(child, id, method, params = {}) {
6
+ const payload = JSON.stringify({ jsonrpc: "2.0", id, method, params }) + "\n";
7
+ child.stdin?.write(payload);
8
+ }
9
+ export async function probeServer(config) {
10
+ const start = Date.now();
11
+ const base = {
12
+ config,
13
+ probedAt: start,
14
+ protocolVersion: undefined,
15
+ errorMessage: undefined,
16
+ stderr: undefined,
17
+ };
18
+ let child;
19
+ try {
20
+ child = spawn(config.command, config.args, {
21
+ stdio: ["pipe", "pipe", "pipe"],
22
+ env: { ...process.env, ...(config.env ?? {}) },
23
+ shell: false,
24
+ windowsHide: true,
25
+ });
26
+ }
27
+ catch (err) {
28
+ return {
29
+ ...base,
30
+ status: classifySpawnError(err),
31
+ durationMs: 0,
32
+ toolCount: 0,
33
+ emptyArgTools: 0,
34
+ toolNames: [],
35
+ errorMessage: err instanceof Error ? err.message : String(err),
36
+ };
37
+ }
38
+ const initResponse = await new Promise((resolve) => {
39
+ let buf = "";
40
+ let resolved = false;
41
+ const onData = (chunk) => {
42
+ buf += chunk.toString("utf8");
43
+ const lines = buf.split("\n");
44
+ buf = lines.pop() ?? "";
45
+ for (const line of lines) {
46
+ if (!line.trim())
47
+ continue;
48
+ try {
49
+ const parsed = JSON.parse(line);
50
+ if (parsed.id === 1) {
51
+ resolved = true;
52
+ resolve(parsed);
53
+ return;
54
+ }
55
+ }
56
+ catch {
57
+ // non-JSON output, keep reading
58
+ }
59
+ }
60
+ };
61
+ const onStderr = (chunk) => {
62
+ // capture but don't resolve
63
+ base.stderr = (base.stderr ?? "") + chunk.toString("utf8");
64
+ };
65
+ const timer = setTimeout(() => {
66
+ if (!resolved)
67
+ resolve("hang");
68
+ }, HANG_THRESHOLD_MS);
69
+ const killTimer = setTimeout(() => {
70
+ if (!resolved)
71
+ resolve("hang");
72
+ child.kill();
73
+ }, PROBE_TIMEOUT_MS);
74
+ child.stdout?.on("data", onData);
75
+ child.stderr?.on("data", onStderr);
76
+ child.on("exit", () => {
77
+ if (!resolved)
78
+ resolve("exit");
79
+ });
80
+ child.on("error", (err) => {
81
+ if (!resolved) {
82
+ resolved = true;
83
+ clearTimeout(timer);
84
+ clearTimeout(killTimer);
85
+ base.errorMessage = err.message;
86
+ resolve("exit");
87
+ }
88
+ });
89
+ send(child, 1, "initialize", {
90
+ protocolVersion: PROTOCOL_VERSION,
91
+ capabilities: {},
92
+ clientInfo: { name: "mcp-doctor", version: "0.1.0" },
93
+ });
94
+ });
95
+ if (initResponse === "hang") {
96
+ child.kill();
97
+ return {
98
+ ...base,
99
+ status: "hangs",
100
+ durationMs: Date.now() - start,
101
+ toolCount: 0,
102
+ emptyArgTools: 0,
103
+ toolNames: [],
104
+ errorMessage: "Server did not respond to initialize within " + HANG_THRESHOLD_MS + "ms",
105
+ };
106
+ }
107
+ if (initResponse === "exit") {
108
+ return {
109
+ ...base,
110
+ status: classifyError(base.errorMessage, base.stderr),
111
+ durationMs: Date.now() - start,
112
+ toolCount: 0,
113
+ emptyArgTools: 0,
114
+ toolNames: [],
115
+ errorMessage: base.errorMessage ?? base.stderr?.split("\n")[0],
116
+ };
117
+ }
118
+ if (initResponse.error) {
119
+ child.kill();
120
+ return {
121
+ ...base,
122
+ status: "auth_required",
123
+ durationMs: Date.now() - start,
124
+ toolCount: 0,
125
+ emptyArgTools: 0,
126
+ toolNames: [],
127
+ errorMessage: initResponse.error.message,
128
+ };
129
+ }
130
+ const initResult = initResponse.result;
131
+ const protocolVersion = initResult?.protocolVersion;
132
+ // Send initialized notification
133
+ send(child, 0, "notifications/initialized", {});
134
+ // Now list tools
135
+ const toolsResponse = await new Promise((resolve) => {
136
+ let buf = "";
137
+ let resolved = false;
138
+ const onData = (chunk) => {
139
+ buf += chunk.toString("utf8");
140
+ const lines = buf.split("\n");
141
+ buf = lines.pop() ?? "";
142
+ for (const line of lines) {
143
+ if (!line.trim())
144
+ continue;
145
+ try {
146
+ const parsed = JSON.parse(line);
147
+ if (parsed.id === 2) {
148
+ resolved = true;
149
+ resolve(parsed);
150
+ return;
151
+ }
152
+ }
153
+ catch {
154
+ // ignore
155
+ }
156
+ }
157
+ };
158
+ setTimeout(() => {
159
+ if (!resolved)
160
+ resolve("hang");
161
+ child.kill();
162
+ }, PROBE_TIMEOUT_MS - (Date.now() - start));
163
+ child.stdout?.on("data", onData);
164
+ send(child, 2, "tools/list", {});
165
+ });
166
+ child.kill();
167
+ if (toolsResponse === "hang") {
168
+ return {
169
+ ...base,
170
+ status: "hangs",
171
+ durationMs: Date.now() - start,
172
+ protocolVersion,
173
+ toolCount: 0,
174
+ emptyArgTools: 0,
175
+ toolNames: [],
176
+ errorMessage: "Server responded to initialize but hung on tools/list",
177
+ };
178
+ }
179
+ if (toolsResponse.error) {
180
+ return {
181
+ ...base,
182
+ status: "broken",
183
+ durationMs: Date.now() - start,
184
+ protocolVersion,
185
+ toolCount: 0,
186
+ emptyArgTools: 0,
187
+ toolNames: [],
188
+ errorMessage: toolsResponse.error.message,
189
+ };
190
+ }
191
+ const result = toolsResponse.result;
192
+ const tools = result?.tools ?? [];
193
+ const toolNames = tools.map((t) => t.name);
194
+ const emptyArgTools = tools.filter((t) => {
195
+ const req = t.inputSchema?.required;
196
+ return !req || req.length === 0;
197
+ }).length;
198
+ return {
199
+ ...base,
200
+ status: "alive",
201
+ durationMs: Date.now() - start,
202
+ protocolVersion,
203
+ toolCount: tools.length,
204
+ emptyArgTools,
205
+ toolNames,
206
+ };
207
+ }
208
+ function classifySpawnError(err) {
209
+ const msg = err instanceof Error ? err.message : String(err);
210
+ if (msg.includes("ENOENT"))
211
+ return "install_error";
212
+ if (msg.includes("EACCES") || msg.includes("EPERM"))
213
+ return "install_error";
214
+ return "broken";
215
+ }
216
+ function classifyError(errorMessage, stderr) {
217
+ const text = `${errorMessage ?? ""} ${stderr ?? ""}`.toLowerCase();
218
+ if (text.includes("api_key") || text.includes("token") || text.includes("auth"))
219
+ return "auth_required";
220
+ if (text.includes("--config") || text.includes("usage") || text.includes("requires"))
221
+ return "needs_args";
222
+ if (text.includes("env") || text.includes("not set"))
223
+ return "needs_env";
224
+ if (text.includes("enoent") || text.includes("cannot find"))
225
+ return "install_error";
226
+ if (text.includes("syntax") || text.includes("unexpected"))
227
+ return "broken";
228
+ return "broken";
229
+ }
230
+ //# sourceMappingURL=spawner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spawner.js","sourceRoot":"","sources":["../../src/prober/spawner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { ServerConfig } from "../types.js";
2
+ export declare function readClaudeDesktop(): ServerConfig[];
@@ -0,0 +1,48 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { homedir, platform } from "node:os";
4
+ function expandHome(p) {
5
+ if (p.startsWith("~/") || p === "~") {
6
+ return join(homedir(), p.slice(1));
7
+ }
8
+ return p;
9
+ }
10
+ function claudeConfigPath() {
11
+ if (platform() === "win32") {
12
+ return join(process.env.APPDATA ?? join(homedir(), "AppData", "Roaming"), "Claude", "claude_desktop_config.json");
13
+ }
14
+ if (platform() === "darwin") {
15
+ return join(homedir(), "Library", "Application Support", "Claude", "claude_desktop_config.json");
16
+ }
17
+ const xdg = process.env.XDG_CONFIG_HOME ?? join(homedir(), ".config");
18
+ return join(xdg, "Claude", "claude_desktop_config.json");
19
+ }
20
+ export function readClaudeDesktop() {
21
+ const path = claudeConfigPath();
22
+ if (!existsSync(path))
23
+ return [];
24
+ let raw;
25
+ try {
26
+ raw = readFileSync(path, "utf8");
27
+ }
28
+ catch {
29
+ return [];
30
+ }
31
+ let parsed;
32
+ try {
33
+ parsed = JSON.parse(raw);
34
+ }
35
+ catch {
36
+ return [];
37
+ }
38
+ const servers = parsed.mcpServers ?? {};
39
+ return Object.entries(servers).map(([name, cfg]) => ({
40
+ name,
41
+ command: cfg.command,
42
+ args: cfg.args ?? [],
43
+ env: cfg.env,
44
+ source: "claude",
45
+ configPath: path,
46
+ }));
47
+ }
48
+ //# sourceMappingURL=claude.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/readers/claude.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAG5C,SAAS,UAAU,CAAC,CAAS;IAC3B,IAAI,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QACpC,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAMD,SAAS,gBAAgB;IACvB,IAAI,QAAQ,EAAE,KAAK,OAAO,EAAE,CAAC;QAC3B,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,SAAS,CAAC,EAAE,QAAQ,EAAE,4BAA4B,CAAC,CAAC;IACpH,CAAC;IACD,IAAI,QAAQ,EAAE,KAAK,QAAQ,EAAE,CAAC;QAC5B,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,qBAAqB,EAAE,QAAQ,EAAE,4BAA4B,CAAC,CAAC;IACnG,CAAC;IACD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC;IACtE,OAAO,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,4BAA4B,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,MAAM,IAAI,GAAG,gBAAgB,EAAE,CAAC;IAChC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IACjC,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,IAAI,MAA2B,CAAC;IAChC,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAwB,CAAC;IAClD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC;IACxC,OAAO,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;QACnD,IAAI;QACJ,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,EAAE;QACpB,GAAG,EAAE,GAAG,CAAC,GAAG;QACZ,MAAM,EAAE,QAAQ;QAChB,UAAU,EAAE,IAAI;KACjB,CAAC,CAAC,CAAC;AACN,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { ServerConfig } from "../types.js";
2
+ export declare function readCline(): ServerConfig[];
@@ -0,0 +1,58 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { homedir, platform } from "node:os";
4
+ function clineConfigPaths() {
5
+ const home = homedir();
6
+ if (platform() === "win32") {
7
+ return [
8
+ join(process.env.APPDATA ?? join(home, "AppData", "Roaming"), "Code", "User", "globalStorage", "saoudrizwan.claude-dev", "settings", "cline_mcp_settings.json"),
9
+ join(home, ".cline", "mcp.json"),
10
+ ];
11
+ }
12
+ if (platform() === "darwin") {
13
+ return [
14
+ join(home, "Library", "Application Support", "Code", "User", "globalStorage", "saoudrizwan.claude-dev", "settings", "cline_mcp_settings.json"),
15
+ join(home, ".cline", "mcp.json"),
16
+ ];
17
+ }
18
+ return [
19
+ join(home, ".config", "Code", "User", "globalStorage", "saoudrizwan.claude-dev", "settings", "cline_mcp_settings.json"),
20
+ join(home, ".cline", "mcp.json"),
21
+ ];
22
+ }
23
+ export function readCline() {
24
+ const out = [];
25
+ for (const path of clineConfigPaths()) {
26
+ if (!existsSync(path))
27
+ continue;
28
+ let raw;
29
+ try {
30
+ raw = readFileSync(path, "utf8");
31
+ }
32
+ catch {
33
+ continue;
34
+ }
35
+ let parsed;
36
+ try {
37
+ parsed = JSON.parse(raw);
38
+ }
39
+ catch {
40
+ continue;
41
+ }
42
+ const servers = parsed.mcpServers ?? {};
43
+ for (const [name, cfg] of Object.entries(servers)) {
44
+ if (cfg.disabled)
45
+ continue;
46
+ out.push({
47
+ name,
48
+ command: cfg.command,
49
+ args: cfg.args ?? [],
50
+ env: cfg.env,
51
+ source: "cline",
52
+ configPath: path,
53
+ });
54
+ }
55
+ }
56
+ return out;
57
+ }
58
+ //# sourceMappingURL=cline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cline.js","sourceRoot":"","sources":["../../src/readers/cline.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAO5C,SAAS,gBAAgB;IACvB,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IACvB,IAAI,QAAQ,EAAE,KAAK,OAAO,EAAE,CAAC;QAC3B,OAAO;YACL,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,wBAAwB,EAAE,UAAU,EAAE,yBAAyB,CAAC;YAC/J,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,UAAU,CAAC;SACjC,CAAC;IACJ,CAAC;IACD,IAAI,QAAQ,EAAE,KAAK,QAAQ,EAAE,CAAC;QAC5B,OAAO;YACL,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,qBAAqB,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,wBAAwB,EAAE,UAAU,EAAE,yBAAyB,CAAC;YAC9I,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,UAAU,CAAC;SACjC,CAAC;IACJ,CAAC;IACD,OAAO;QACL,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,wBAAwB,EAAE,UAAU,EAAE,yBAAyB,CAAC;QACvH,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,UAAU,CAAC;KACjC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,MAAM,GAAG,GAAmB,EAAE,CAAC;IAC/B,KAAK,MAAM,IAAI,IAAI,gBAAgB,EAAE,EAAE,CAAC;QACtC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,SAAS;QAChC,IAAI,GAAW,CAAC;QAChB,IAAI,CAAC;YACH,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACnC,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QACD,IAAI,MAAmB,CAAC;QACxB,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAgB,CAAC;QAC1C,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC;QACxC,KAAK,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YAClD,IAAI,GAAG,CAAC,QAAQ;gBAAE,SAAS;YAC3B,GAAG,CAAC,IAAI,CAAC;gBACP,IAAI;gBACJ,OAAO,EAAE,GAAG,CAAC,OAAO;gBACpB,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,EAAE;gBACpB,GAAG,EAAE,GAAG,CAAC,GAAG;gBACZ,MAAM,EAAE,OAAO;gBACf,UAAU,EAAE,IAAI;aACjB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { ServerConfig } from "../types.js";
2
+ export declare function readCodex(): ServerConfig[];
@@ -0,0 +1,104 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { homedir, platform } from "node:os";
4
+ function codexConfigPath() {
5
+ const home = homedir();
6
+ if (platform() === "win32") {
7
+ return join(home, ".codex", "config.toml");
8
+ }
9
+ return join(home, ".codex", "config.toml");
10
+ }
11
+ function parseTomlServers(content) {
12
+ const servers = {};
13
+ const lines = content.split(/\r?\n/);
14
+ let inServers = false;
15
+ let currentName = null;
16
+ for (const line of lines) {
17
+ const trimmed = line.trim();
18
+ if (!trimmed || trimmed.startsWith("#"))
19
+ continue;
20
+ if (trimmed === "[mcp_servers]") {
21
+ inServers = true;
22
+ continue;
23
+ }
24
+ if (trimmed.startsWith("[")) {
25
+ inServers = false;
26
+ currentName = null;
27
+ continue;
28
+ }
29
+ if (!inServers)
30
+ continue;
31
+ const sectionMatch = trimmed.match(/^\[mcp_servers\.([^\]]+)\]$/);
32
+ if (sectionMatch) {
33
+ currentName = sectionMatch[1] ?? null;
34
+ if (currentName) {
35
+ servers[currentName] = { command: "", args: [] };
36
+ }
37
+ continue;
38
+ }
39
+ if (!currentName)
40
+ continue;
41
+ const kv = trimmed.match(/^([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.+)$/);
42
+ if (!kv)
43
+ continue;
44
+ const key = kv[1];
45
+ let value = (kv[2] ?? "").trim();
46
+ if (value.startsWith('"') && value.endsWith('"')) {
47
+ value = value.slice(1, -1);
48
+ }
49
+ else if (value.startsWith("'") && value.endsWith("'")) {
50
+ value = value.slice(1, -1);
51
+ }
52
+ else if (value.startsWith("[") && value.endsWith("]")) {
53
+ try {
54
+ const arr = JSON.parse(value.replace(/'/g, '"'));
55
+ if (Array.isArray(arr)) {
56
+ value = arr.join(" ");
57
+ }
58
+ }
59
+ catch {
60
+ value = value.slice(1, -1);
61
+ }
62
+ }
63
+ const target = servers[currentName];
64
+ if (!target)
65
+ continue;
66
+ if (key === "command")
67
+ target.command = value;
68
+ else if (key === "args")
69
+ target.args = value.split(/\s+/).filter(Boolean);
70
+ else if (key === "env" && value.startsWith("{")) {
71
+ try {
72
+ target.env = JSON.parse(value);
73
+ }
74
+ catch {
75
+ target.env = {};
76
+ }
77
+ }
78
+ }
79
+ return servers;
80
+ }
81
+ export function readCodex() {
82
+ const path = codexConfigPath();
83
+ if (!existsSync(path))
84
+ return [];
85
+ let raw;
86
+ try {
87
+ raw = readFileSync(path, "utf8");
88
+ }
89
+ catch {
90
+ return [];
91
+ }
92
+ const servers = parseTomlServers(raw);
93
+ return Object.entries(servers)
94
+ .filter(([, cfg]) => cfg.command)
95
+ .map(([name, cfg]) => ({
96
+ name,
97
+ command: cfg.command,
98
+ args: cfg.args ?? [],
99
+ env: cfg.env,
100
+ source: "codex",
101
+ configPath: path,
102
+ }));
103
+ }
104
+ //# sourceMappingURL=codex.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex.js","sourceRoot":"","sources":["../../src/readers/codex.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { ServerConfig } from "../types.js";
2
+ export declare function readCursor(): ServerConfig[];
@@ -0,0 +1,53 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { homedir, platform } from "node:os";
4
+ function cursorConfigPaths() {
5
+ const home = homedir();
6
+ if (platform() === "win32") {
7
+ return [
8
+ join(process.env.APPDATA ?? join(home, "AppData", "Roaming"), "Cursor", "mcp.json"),
9
+ join(home, ".cursor", "mcp.json"),
10
+ ];
11
+ }
12
+ if (platform() === "darwin") {
13
+ return [
14
+ join(home, "Library", "Application Support", "Cursor", "mcp.json"),
15
+ join(home, ".cursor", "mcp.json"),
16
+ ];
17
+ }
18
+ return [join(home, ".config", "Cursor", "mcp.json"), join(home, ".cursor", "mcp.json")];
19
+ }
20
+ export function readCursor() {
21
+ const out = [];
22
+ for (const path of cursorConfigPaths()) {
23
+ if (!existsSync(path))
24
+ continue;
25
+ let raw;
26
+ try {
27
+ raw = readFileSync(path, "utf8");
28
+ }
29
+ catch {
30
+ continue;
31
+ }
32
+ let parsed;
33
+ try {
34
+ parsed = JSON.parse(raw);
35
+ }
36
+ catch {
37
+ continue;
38
+ }
39
+ const servers = parsed.mcpServers ?? {};
40
+ for (const [name, cfg] of Object.entries(servers)) {
41
+ out.push({
42
+ name,
43
+ command: cfg.command,
44
+ args: cfg.args ?? [],
45
+ env: cfg.env,
46
+ source: "cursor",
47
+ configPath: path,
48
+ });
49
+ }
50
+ }
51
+ return out;
52
+ }
53
+ //# sourceMappingURL=cursor.js.map