@kryptosai/mcp-observatory 1.33.0 → 1.34.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 (107) hide show
  1. package/README.md +8 -121
  2. package/dist/src/auth.d.ts +22 -0
  3. package/dist/src/auth.js +140 -0
  4. package/dist/src/auth.js.map +1 -0
  5. package/dist/src/cli.js +48 -3
  6. package/dist/src/cli.js.map +1 -1
  7. package/dist/src/commands/demo.d.ts +2 -0
  8. package/dist/src/commands/demo.js +247 -0
  9. package/dist/src/commands/demo.js.map +1 -0
  10. package/dist/src/commands/helpers.d.ts +11 -0
  11. package/dist/src/commands/helpers.js +26 -0
  12. package/dist/src/commands/helpers.js.map +1 -1
  13. package/dist/src/commands/init-ci.d.ts +1 -0
  14. package/dist/src/commands/init-ci.js +157 -10
  15. package/dist/src/commands/init-ci.js.map +1 -1
  16. package/dist/src/commands/receipt.js +13 -3
  17. package/dist/src/commands/receipt.js.map +1 -1
  18. package/dist/src/commands/scan.js +10 -1
  19. package/dist/src/commands/scan.js.map +1 -1
  20. package/dist/src/commands/setup-ci-conversion.js +4 -4
  21. package/dist/src/commands/setup-ci-conversion.js.map +1 -1
  22. package/dist/src/commands/test.js +9 -1
  23. package/dist/src/commands/test.js.map +1 -1
  24. package/dist/src/commercial.d.ts +3 -0
  25. package/dist/src/commercial.js +12 -1
  26. package/dist/src/commercial.js.map +1 -1
  27. package/dist/src/index.d.ts +1 -1
  28. package/dist/src/index.js +1 -1
  29. package/dist/src/index.js.map +1 -1
  30. package/dist/src/receipt.d.ts +9 -0
  31. package/dist/src/receipt.js +24 -1
  32. package/dist/src/receipt.js.map +1 -1
  33. package/dist/src/telemetry.js +4 -0
  34. package/dist/src/telemetry.js.map +1 -1
  35. package/dist/src/utils/failure-diagnosis.d.ts +7 -0
  36. package/dist/src/utils/failure-diagnosis.js +14 -0
  37. package/dist/src/utils/failure-diagnosis.js.map +1 -1
  38. package/docs/mcp-server-safety-index.md +1 -1
  39. package/docs/safety-index/artifacts/antv-chart-server.json +21 -21
  40. package/docs/safety-index/artifacts/antv-chart-server.md +10 -10
  41. package/docs/safety-index/artifacts/browsermcp-server.json +18 -18
  42. package/docs/safety-index/artifacts/browsermcp-server.md +9 -9
  43. package/docs/safety-index/artifacts/chrome-devtools-mcp-server.json +19 -19
  44. package/docs/safety-index/artifacts/chrome-devtools-mcp-server.md +9 -9
  45. package/docs/safety-index/artifacts/cloudflare-server.json +4 -4
  46. package/docs/safety-index/artifacts/cloudflare-server.md +4 -4
  47. package/docs/safety-index/artifacts/context7-server.json +18 -18
  48. package/docs/safety-index/artifacts/context7-server.md +10 -10
  49. package/docs/safety-index/artifacts/cyanheads-git-mcp-server.json +34 -34
  50. package/docs/safety-index/artifacts/cyanheads-git-mcp-server.md +15 -15
  51. package/docs/safety-index/artifacts/everything-server.json +18 -18
  52. package/docs/safety-index/artifacts/everything-server.md +11 -11
  53. package/docs/safety-index/artifacts/executeautomation-playwright-server.json +19 -19
  54. package/docs/safety-index/artifacts/executeautomation-playwright-server.md +11 -11
  55. package/docs/safety-index/artifacts/filesystem-mcp-server.json +19 -19
  56. package/docs/safety-index/artifacts/filesystem-mcp-server.md +10 -10
  57. package/docs/safety-index/artifacts/filesystem-server.json +19 -19
  58. package/docs/safety-index/artifacts/filesystem-server.md +10 -10
  59. package/docs/safety-index/artifacts/github-mcp-server.json +18 -18
  60. package/docs/safety-index/artifacts/github-mcp-server.md +9 -9
  61. package/docs/safety-index/artifacts/google-drive-server.json +4 -4
  62. package/docs/safety-index/artifacts/google-drive-server.md +4 -4
  63. package/docs/safety-index/artifacts/kubernetes-server.json +23 -23
  64. package/docs/safety-index/artifacts/kubernetes-server.md +15 -15
  65. package/docs/safety-index/artifacts/memory-server.json +18 -18
  66. package/docs/safety-index/artifacts/memory-server.md +10 -10
  67. package/docs/safety-index/artifacts/mongodb-server.json +4 -4
  68. package/docs/safety-index/artifacts/mongodb-server.md +4 -4
  69. package/docs/safety-index/artifacts/opentofu-server.json +18 -18
  70. package/docs/safety-index/artifacts/opentofu-server.md +9 -9
  71. package/docs/safety-index/artifacts/playwright-mcp-server.json +18 -18
  72. package/docs/safety-index/artifacts/playwright-mcp-server.md +9 -9
  73. package/docs/safety-index/artifacts/promptopia-server.json +21 -21
  74. package/docs/safety-index/artifacts/promptopia-server.md +11 -11
  75. package/docs/safety-index/artifacts/puppeteer-server.json +18 -18
  76. package/docs/safety-index/artifacts/puppeteer-server.md +9 -9
  77. package/docs/safety-index/artifacts/qdrant-server.json +4 -4
  78. package/docs/safety-index/artifacts/qdrant-server.md +4 -4
  79. package/docs/safety-index/artifacts/ref-tools-server.json +18 -18
  80. package/docs/safety-index/artifacts/ref-tools-server.md +10 -10
  81. package/docs/safety-index/artifacts/sequential-thinking-server.json +18 -18
  82. package/docs/safety-index/artifacts/sequential-thinking-server.md +8 -8
  83. package/docs/safety-index/artifacts/slack-server.json +3 -3
  84. package/docs/safety-index/artifacts/slack-server.md +2 -2
  85. package/docs/safety-index/artifacts/ui5-mcp-server.json +18 -18
  86. package/docs/safety-index/artifacts/ui5-mcp-server.md +9 -9
  87. package/docs/safety-index/artifacts/vercel-ai-server.json +4 -4
  88. package/docs/safety-index/artifacts/vercel-ai-server.md +4 -4
  89. package/package.json +2 -2
  90. package/dist/src/adapters/base.d.ts +0 -14
  91. package/dist/src/adapters/base.js +0 -2
  92. package/dist/src/adapters/base.js.map +0 -1
  93. package/dist/src/checks/semantics.d.ts +0 -2
  94. package/dist/src/checks/semantics.js +0 -48
  95. package/dist/src/checks/semantics.js.map +0 -1
  96. package/dist/src/diff/diff.d.ts +0 -2
  97. package/dist/src/diff/diff.js +0 -81
  98. package/dist/src/diff/diff.js.map +0 -1
  99. package/dist/src/reporters/json.d.ts +0 -2
  100. package/dist/src/reporters/json.js +0 -4
  101. package/dist/src/reporters/json.js.map +0 -1
  102. package/dist/src/runner/runner.d.ts +0 -2
  103. package/dist/src/runner/runner.js +0 -135
  104. package/dist/src/runner/runner.js.map +0 -1
  105. package/dist/src/storage/filesystem.d.ts +0 -6
  106. package/dist/src/storage/filesystem.js +0 -21
  107. package/dist/src/storage/filesystem.js.map +0 -1
@@ -0,0 +1,247 @@
1
+ import { runTarget } from "../index.js";
2
+ import { scanForTargets } from "../discovery.js";
3
+ import { buildEvent, generateSessionId, recordEvent, recordSessionEnd, recordSessionStart } from "../telemetry.js";
4
+ import { maybePrintCloudCta } from "../commercial.js";
5
+ import { ANSI, c, colorStatus, getBinName, isQuiet, LOGO, printCiConversionCta, } from "./helpers.js";
6
+ const DEMO_SERVERS = [
7
+ {
8
+ name: "fetch",
9
+ targetId: "@modelcontextprotocol/server-fetch",
10
+ command: "npx",
11
+ args: ["-y", "@modelcontextprotocol/server-fetch"],
12
+ desc: "Fetch and convert web pages — safe, always available",
13
+ },
14
+ {
15
+ name: "filesystem",
16
+ targetId: "@modelcontextprotocol/server-filesystem",
17
+ command: "npx",
18
+ args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"],
19
+ desc: "Read/write local files — shows capability discovery",
20
+ },
21
+ {
22
+ name: "memory",
23
+ targetId: "@modelcontextprotocol/server-memory",
24
+ command: "npx",
25
+ args: ["-y", "@modelcontextprotocol/server-memory"],
26
+ desc: "Persistent knowledge graph — shows resource handling",
27
+ },
28
+ {
29
+ name: "github",
30
+ targetId: "@modelcontextprotocol/server-github",
31
+ command: "npx",
32
+ args: ["-y", "@modelcontextprotocol/server-github"],
33
+ desc: "GitHub API — needs GITHUB_PERSONAL_ACCESS_TOKEN",
34
+ },
35
+ ];
36
+ function gradeBar(score) {
37
+ const width = 20;
38
+ const filled = Math.round((score / 100) * width);
39
+ const empty = width - filled;
40
+ if (score >= 90)
41
+ return c(ANSI.green, "█".repeat(filled)) + c(ANSI.dim, "░".repeat(empty));
42
+ if (score >= 70)
43
+ return c(ANSI.yellow, "█".repeat(filled)) + c(ANSI.dim, "░".repeat(empty));
44
+ if (score >= 60)
45
+ return c(ANSI.yellow, "█".repeat(filled)) + c(ANSI.dim, "░".repeat(empty));
46
+ return c(ANSI.red, "█".repeat(filled)) + c(ANSI.dim, "░".repeat(empty));
47
+ }
48
+ function gradeColor(grade) {
49
+ if (grade === "A")
50
+ return c(ANSI.green, grade);
51
+ if (grade === "B")
52
+ return c(ANSI.green, grade);
53
+ if (grade === "C")
54
+ return c(ANSI.yellow, grade);
55
+ if (grade === "D")
56
+ return c(ANSI.yellow, grade);
57
+ return c(ANSI.red, grade);
58
+ }
59
+ function dimBar(score) {
60
+ const width = 20;
61
+ const filled = Math.round((score / 100) * width);
62
+ const empty = width - filled;
63
+ return c(ANSI.dim, "▐".repeat(filled)) + c(ANSI.dim, "░".repeat(empty));
64
+ }
65
+ export function registerDemoCommands(program) {
66
+ program
67
+ .command("demo")
68
+ .description("Quick interactive demo — scan your MCP servers and see your safety grade")
69
+ .option("--server <name>", `Demo with a built-in server: ${DEMO_SERVERS.map(s => s.name).join(", ")}`)
70
+ .option("--deep", "Run full tool invocation and security checks (takes longer)", false)
71
+ .option("--no-color", "Disable colored output")
72
+ .action(async (options) => {
73
+ const sessionId = generateSessionId();
74
+ recordSessionStart(sessionId);
75
+ const t0 = Date.now();
76
+ const bin = getBinName();
77
+ if (!isQuiet()) {
78
+ process.stdout.write(LOGO + "\n");
79
+ }
80
+ process.stdout.write(c(ANSI.bold, " MCP Observatory — Interactive Demo\n"));
81
+ process.stdout.write(` ${c(ANSI.dim, "Scan your MCP servers. Get a safety grade. Ship with confidence.")}\n\n`);
82
+ // ── Step 1: Select target ──────────────────────────────────────────
83
+ process.stdout.write(` ${c(ANSI.dim, "⟳")} Discovering your MCP servers...`);
84
+ const targets = await scanForTargets();
85
+ let targetConfig;
86
+ let targetSource;
87
+ if (options.server) {
88
+ const serverName = options.server.toLowerCase();
89
+ const demo = DEMO_SERVERS.find(s => s.name === serverName);
90
+ if (!demo) {
91
+ process.stdout.write(`\r ${c(ANSI.red, "✗")} Unknown demo server "${options.server}".\n`);
92
+ process.stdout.write(` ${c(ANSI.dim, `Available: ${DEMO_SERVERS.map(s => s.name).join(", ")}`)}\n`);
93
+ process.exitCode = 1;
94
+ recordSessionEnd(sessionId);
95
+ return;
96
+ }
97
+ targetConfig = {
98
+ targetId: demo.targetId,
99
+ adapter: "local-process",
100
+ command: demo.command,
101
+ args: demo.args,
102
+ timeoutMs: 15_000,
103
+ };
104
+ targetSource = `built-in demo (${demo.desc})`;
105
+ process.stdout.write(`\r ${c(ANSI.green, "✓")} Using ${c(ANSI.bold, demo.name)} ${c(ANSI.dim, `— ${demo.desc}`)}\n`);
106
+ }
107
+ else if (targets.length > 0) {
108
+ process.stdout.write(`\r ${c(ANSI.green, "✓")} Found ${targets.length} server${targets.length > 1 ? "s" : ""}\n`);
109
+ for (const t of targets.slice(0, 5)) {
110
+ process.stdout.write(` ${c(ANSI.cyan, "●")} ${c(ANSI.bold, t.config.targetId)} ${c(ANSI.dim, `← ${t.source}`)}\n`);
111
+ }
112
+ if (targets.length > 5) {
113
+ process.stdout.write(` ${c(ANSI.dim, `... and ${targets.length - 5} more`)}\n`);
114
+ }
115
+ targetConfig = targets[0].config;
116
+ targetSource = targets[0].source;
117
+ process.stdout.write(`\n ${c(ANSI.dim, "Scanning first server...")}\n`);
118
+ }
119
+ else {
120
+ const demo = DEMO_SERVERS[0];
121
+ targetConfig = {
122
+ targetId: demo.targetId,
123
+ adapter: "local-process",
124
+ command: demo.command,
125
+ args: demo.args,
126
+ timeoutMs: 15_000,
127
+ };
128
+ targetSource = `built-in demo (${demo.desc})`;
129
+ process.stdout.write(`\r ${c(ANSI.yellow, "!")} No MCP servers configured.\n`);
130
+ process.stdout.write(` ${c(ANSI.dim, "Running built-in demo with")} ${c(ANSI.bold, demo.targetId)}\n`);
131
+ process.stdout.write(` ${c(ANSI.dim, `Tip: ${bin} suggest → discover servers for your stack`)}\n`);
132
+ }
133
+ process.stdout.write("\n");
134
+ // ── Step 2: Run scan ───────────────────────────────────────────────
135
+ process.stdout.write(` ${c(ANSI.dim, "⟳")} Scanning ${c(ANSI.bold, targetConfig.targetId)}...`);
136
+ let artifact;
137
+ try {
138
+ artifact = await runTarget(targetConfig, {
139
+ invokeTools: options.deep,
140
+ securityCheck: options.deep,
141
+ });
142
+ }
143
+ catch (err) {
144
+ process.stdout.write(`\r ${c(ANSI.red, "✗")} Scan failed: ${err instanceof Error ? err.message : String(err)}\n`);
145
+ process.exitCode = 1;
146
+ recordEvent(buildEvent("command_complete", "demo", "cli", {
147
+ fatalError: err instanceof Error ? err.message : String(err),
148
+ stageOverride: "scan",
149
+ executionMs: Date.now() - t0,
150
+ }));
151
+ recordSessionEnd(sessionId);
152
+ return;
153
+ }
154
+ const scanMs = Date.now() - t0;
155
+ if (artifact.fatalError) {
156
+ process.stdout.write(`\r ${c(ANSI.red, "✗")} ${c(ANSI.bold, targetConfig.targetId)} could not be reached\n`);
157
+ process.stdout.write(` ${c(ANSI.dim, artifact.fatalError.split("\n")[0])}\n`);
158
+ process.stdout.write("\n");
159
+ process.stdout.write(` ${c(ANSI.dim, "Try another:")} ${bin} demo --server <name>\n`);
160
+ process.stdout.write(` ${c(ANSI.dim, `Built-in demos: ${DEMO_SERVERS.map(s => s.name).join(", ")}`)}\n\n`);
161
+ process.exitCode = 1;
162
+ recordEvent(buildEvent("command_complete", "demo", "cli", {
163
+ targetServer: targetConfig.targetId,
164
+ fatalError: artifact.fatalError.split("\n")[0],
165
+ executionMs: scanMs,
166
+ }));
167
+ recordSessionEnd(sessionId);
168
+ return;
169
+ }
170
+ const gateIcon = artifact.gate === "pass"
171
+ ? c(ANSI.green, "✓")
172
+ : c(ANSI.red, "✗");
173
+ process.stdout.write(`\r ${gateIcon} Scan complete ${c(ANSI.dim, `(${scanMs}ms)`)}\n\n`);
174
+ // ── Step 3: Summary card ───────────────────────────────────────────
175
+ const toolCount = artifact.checks.find(ch => ch.id === "tools")?.evidence[0]?.itemCount ?? 0;
176
+ const promptCount = artifact.checks.find(ch => ch.id === "prompts")?.evidence[0]?.itemCount ?? 0;
177
+ const resourceCount = artifact.checks.find(ch => ch.id === "resources")?.evidence[0]?.itemCount ?? 0;
178
+ process.stdout.write(` ${c(ANSI.bold, "Server")} ${targetConfig.targetId}\n`);
179
+ process.stdout.write(` ${c(ANSI.dim, "Source")} ${targetSource}\n`);
180
+ process.stdout.write(` ${c(ANSI.dim, "Capabilities")} ${toolCount} tools, ${promptCount} prompts, ${resourceCount} resources\n`);
181
+ // ── Step 4: Health Score ───────────────────────────────────────────
182
+ const hs = artifact.healthScore;
183
+ if (hs) {
184
+ process.stdout.write(`\n ${c(ANSI.bold, "Safety Grade")}\n`);
185
+ process.stdout.write(` ${gradeColor(hs.grade)} ${hs.overall}/100 ${gradeBar(hs.overall)}\n\n`);
186
+ process.stdout.write(` ${c(ANSI.dim, "Dimension Breakdown")}\n`);
187
+ for (const dim of hs.dimensions) {
188
+ const pct = Math.round(dim.weight * 100);
189
+ const label = dim.name.padEnd(22);
190
+ const scoreLabel = String(dim.score).padStart(3);
191
+ process.stdout.write(` ${c(ANSI.bold, label)} ${scoreLabel}/100 ${dimBar(dim.score)} ${c(ANSI.dim, `(${pct}%)`)}\n`);
192
+ }
193
+ }
194
+ // ── Step 5: Check results ──────────────────────────────────────────
195
+ process.stdout.write(`\n ${c(ANSI.bold, "Check Results")}\n`);
196
+ for (const check of artifact.checks) {
197
+ const icon = check.status === "pass" ? c(ANSI.green, "✓") :
198
+ check.status === "fail" ? c(ANSI.red, "✗") :
199
+ c(ANSI.yellow, "○");
200
+ const status = colorStatus(check.status);
201
+ process.stdout.write(` ${icon} ${check.id.padEnd(18)} ${status.padEnd(12)} ${c(ANSI.dim, check.message)}\n`);
202
+ }
203
+ process.stdout.write("\n");
204
+ // ── Step 6: Next steps ─────────────────────────────────────────────
205
+ if (artifact.gate === "pass") {
206
+ process.stdout.write(` ${c(ANSI.green, "✓")} ${c(ANSI.bold, "All checks passed!")}\n\n`);
207
+ process.stdout.write(` ${c(ANSI.bold, "What's next?")}\n`);
208
+ const serverCount = targets.length > 1 ? targets.length : "";
209
+ if (serverCount) {
210
+ process.stdout.write(` ${c(ANSI.cyan, "$")} ${c(ANSI.bold, `${bin} scan`)}${serverCount ? "" : ""} ${c(ANSI.dim, `— scan all ${serverCount} servers`)}\n`);
211
+ }
212
+ process.stdout.write(` ${c(ANSI.cyan, "$")} ${c(ANSI.bold, `${bin} diff`)} <run1> <run2> ${c(ANSI.dim, "- compare before/after")}\n`);
213
+ process.stdout.write(` ${c(ANSI.cyan, "$")} ${c(ANSI.bold, `${bin} badge`)} <server> ${c(ANSI.dim, "- generate a safety badge")}\n`);
214
+ process.stdout.write(` ${c(ANSI.cyan, "$")} ${c(ANSI.bold, `${bin} setup-ci`)} ${c(ANSI.dim, "- add to CI pipeline")}\n`);
215
+ printCiConversionCta({ bin, context: "keep this safety grade visible in CI", target: targetConfig });
216
+ }
217
+ else {
218
+ process.stdout.write(` ${c(ANSI.yellow, "!")} ${c(ANSI.bold, "Some checks need attention")}\n\n`);
219
+ process.stdout.write(` ${c(ANSI.bold, "Quick fixes:")}\n`);
220
+ process.stdout.write(` ${c(ANSI.cyan, "$")} ${c(ANSI.bold, `${bin} enforce`)} ${targetConfig.targetId} ${c(ANSI.dim, "- generate runtime policy")}\n`);
221
+ process.stdout.write(` ${c(ANSI.cyan, "$")} ${c(ANSI.bold, `${bin} audit`)} ${targetConfig.targetId} ${c(ANSI.dim, "- deep security audit")}\n`);
222
+ process.stdout.write(` ${c(ANSI.cyan, "$")} ${c(ANSI.bold, `${bin} test --deep`)} ${targetConfig.targetId} ${c(ANSI.dim, "- full tool invocation")}\n`);
223
+ }
224
+ process.stdout.write("\n");
225
+ // ── Telemetry ──────────────────────────────────────────────────────
226
+ const checkStatuses = {};
227
+ for (const ch of artifact.checks)
228
+ checkStatuses[ch.id] = ch.status;
229
+ recordEvent(buildEvent("command_complete", "demo", "cli", {
230
+ targetIds: [targetConfig.targetId],
231
+ gateResult: artifact.gate,
232
+ healthScore: hs?.overall,
233
+ healthGrade: hs?.grade,
234
+ toolsFound: toolCount,
235
+ promptsFound: promptCount,
236
+ resourcesFound: resourceCount,
237
+ checkStatuses,
238
+ serversScanned: targets.length,
239
+ deepFlag: options.deep,
240
+ executionMs: scanMs,
241
+ stageOverride: "demo",
242
+ }));
243
+ maybePrintCloudCta("general");
244
+ recordSessionEnd(sessionId);
245
+ });
246
+ }
247
+ //# sourceMappingURL=demo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"demo.js","sourceRoot":"","sources":["../../../src/commands/demo.ts"],"names":[],"mappings":"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"}
@@ -15,6 +15,17 @@ export declare function useColor(): boolean;
15
15
  export declare function setQuiet(value: boolean): void;
16
16
  export declare function isQuiet(): boolean;
17
17
  export declare function c(code: string, text: string): string;
18
+ /**
19
+ * Suggests a one-line remediation for a raw error message, so scan/test
20
+ * failures tell the user how to fix the problem, not just state it.
21
+ *
22
+ * Note: connection failures during MCP session startup already get a much
23
+ * richer diagnosis (diagnosis/likely causes/next steps) from
24
+ * `formatConnectionFailureDiagnosis` via `RunArtifact.fatalError` — this
25
+ * covers the lighter-weight cases outside that path (thrown exceptions,
26
+ * config parsing errors) where no such diagnosis exists.
27
+ */
28
+ export declare function suggestFix(message: string): string | undefined;
18
29
  export declare function colorStatus(status: string): string;
19
30
  export declare function readTargetConfig(filePath: string): Promise<TargetConfig>;
20
31
  export declare function targetFromCommand(args: string[]): TargetConfig;
@@ -44,6 +44,32 @@ export function isQuiet() {
44
44
  export function c(code, text) {
45
45
  return useColor() ? `${code}${text}${ANSI.reset}` : text;
46
46
  }
47
+ /**
48
+ * Suggests a one-line remediation for a raw error message, so scan/test
49
+ * failures tell the user how to fix the problem, not just state it.
50
+ *
51
+ * Note: connection failures during MCP session startup already get a much
52
+ * richer diagnosis (diagnosis/likely causes/next steps) from
53
+ * `formatConnectionFailureDiagnosis` via `RunArtifact.fatalError` — this
54
+ * covers the lighter-weight cases outside that path (thrown exceptions,
55
+ * config parsing errors) where no such diagnosis exists.
56
+ */
57
+ export function suggestFix(message) {
58
+ const lower = message.toLowerCase();
59
+ if (lower.includes("timed out") || lower.includes("timeout")) {
60
+ return "Try increasing timeout with --timeout 30000";
61
+ }
62
+ if (lower.includes("econnrefused") || lower.includes("connection refused")) {
63
+ return "Check that the server is running. Try: npx -y <server-package>";
64
+ }
65
+ if (lower.includes("enoent") || lower.includes("spawn")) {
66
+ return "Check that the command is installed and on PATH. Try: npx -y <server-package>";
67
+ }
68
+ if (lower.includes("unexpected token") || lower.includes("invalid config") || lower.includes("is not valid json")) {
69
+ return "Check target JSON format. Run: cat <config-file>";
70
+ }
71
+ return undefined;
72
+ }
47
73
  export function colorStatus(status) {
48
74
  switch (status) {
49
75
  case "pass":
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../../src/commands/helpers.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../../src/commands/helpers.ts"],"names":[],"mappings":"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"}
@@ -20,6 +20,7 @@ export interface InitCiOptions {
20
20
  fix?: boolean;
21
21
  fromLastRun?: boolean;
22
22
  campaign?: string;
23
+ ciProvider?: "github-actions" | "gitlab-ci" | "circleci" | "bitbucket-pipelines" | "azure-pipelines";
23
24
  }
24
25
  export interface InitCiResult {
25
26
  workflowStatus: string;
@@ -1,9 +1,26 @@
1
1
  import { access, mkdir, readFile, writeFile } from "node:fs/promises";
2
2
  import path from "node:path";
3
- import { buildEvent, normalizeCampaign, recordEvent } from "../telemetry.js";
3
+ import { buildEvent, detectCiProvider, normalizeCampaign, recordEvent } from "../telemetry.js";
4
4
  import { defaultRunsDirectory, findLatestSuccessfulRunArtifact, readArtifact } from "../storage.js";
5
5
  import { TOOL_VERSION } from "../version.js";
6
6
  import { quoteShell } from "./helpers.js";
7
+ const CI_FILE_PATHS = {
8
+ "github-actions": ".github/workflows/mcp-observatory.yml",
9
+ "gitlab-ci": ".gitlab-ci.yml",
10
+ "circleci": ".circleci/config.yml",
11
+ "bitbucket-pipelines": "bitbucket-pipelines.yml",
12
+ "azure-pipelines": "azure-pipelines.yml",
13
+ };
14
+ const PROVIDER_LABELS = {
15
+ "github-actions": "GitHub Action",
16
+ "gitlab-ci": "GitLab CI",
17
+ "circleci": "CircleCI",
18
+ "bitbucket-pipelines": "Bitbucket Pipelines",
19
+ "azure-pipelines": "Azure Pipelines",
20
+ };
21
+ function providerLabel(provider) {
22
+ return PROVIDER_LABELS[provider] ?? "CI Workflow";
23
+ }
7
24
  const DEFAULT_WORKFLOW_PATH = ".github/workflows/mcp-observatory.yml";
8
25
  const DEFAULT_BADGE_PATH = "docs/mcp-observatory-badge.md";
9
26
  const DEFAULT_TARGET_CONFIG_PATH = "mcp-observatory.target.json";
@@ -31,7 +48,7 @@ function normalizeSchedule(schedule) {
31
48
  const value = schedule.trim();
32
49
  return value.length > 0 ? value : DEFAULT_WEEKLY_CRON;
33
50
  }
34
- function workflowYaml(options) {
51
+ function githubActionsYaml(options) {
35
52
  const command = options.command?.trim();
36
53
  const target = options.target?.trim();
37
54
  const commentsEnabled = options.commentOnPr === true;
@@ -76,6 +93,129 @@ function workflowYaml(options) {
76
93
  lines.push("");
77
94
  return lines.join("\n");
78
95
  }
96
+ function workflowYaml(options) {
97
+ const provider = options.ciProvider ?? "github-actions";
98
+ switch (provider) {
99
+ case "github-actions": return githubActionsYaml(options);
100
+ case "gitlab-ci": return gitlabCiYaml(options);
101
+ case "circleci": return circleCiYaml(options);
102
+ case "bitbucket-pipelines": return bitbucketYaml(options);
103
+ case "azure-pipelines": return azurePipelinesYaml(options);
104
+ default: return githubActionsYaml(options);
105
+ }
106
+ }
107
+ function gitlabCiYaml(options) {
108
+ const lines = [
109
+ "mcp-observatory:",
110
+ " image: node:22",
111
+ ];
112
+ if (options.schedule) {
113
+ lines.push(" only:", " - schedules");
114
+ }
115
+ else {
116
+ lines.push(" rules:", " - if: $CI_PIPELINE_SOURCE == 'merge_request_event'", " - if: $CI_COMMIT_BRANCH == 'main'");
117
+ }
118
+ lines.push(" script:");
119
+ if (options.command) {
120
+ lines.push(` - npx @kryptosai/mcp-observatory test ${options.command} --deep --security` + (options.sarif !== false ? " --sarif mcp-observatory.sarif" : ""));
121
+ }
122
+ else if (options.all) {
123
+ lines.push(" - npx @kryptosai/mcp-observatory scan --deep --security" + (options.sarif !== false ? " --sarif mcp-observatory.sarif" : ""));
124
+ }
125
+ else {
126
+ lines.push(` - npx @kryptosai/mcp-observatory test --target mcp-observatory.target.json --deep --security`);
127
+ }
128
+ if (options.sarif !== false) {
129
+ lines.push(" artifacts:", " reports:", " sast: mcp-observatory.sarif");
130
+ }
131
+ return lines.join("\n");
132
+ }
133
+ function circleCiYaml(options) {
134
+ const lines = [
135
+ "version: 2.1",
136
+ "",
137
+ "jobs:",
138
+ " mcp-observatory:",
139
+ " docker:",
140
+ " - image: cimg/node:22.0",
141
+ " steps:",
142
+ " - checkout",
143
+ ` - run:`,
144
+ ];
145
+ if (options.command) {
146
+ lines.push(` command: npx @kryptosai/mcp-observatory test ${options.command} --deep --security` + (options.sarif !== false ? " --sarif mcp-observatory.sarif" : ""));
147
+ }
148
+ else if (options.all) {
149
+ lines.push(" command: npx @kryptosai/mcp-observatory scan --deep --security" + (options.sarif !== false ? " --sarif mcp-observatory.sarif" : ""));
150
+ }
151
+ else {
152
+ lines.push(" command: npx @kryptosai/mcp-observatory test --target mcp-observatory.target.json --deep --security");
153
+ }
154
+ if (options.sarif !== false) {
155
+ lines.push(" - store_artifacts:", " path: mcp-observatory.sarif");
156
+ }
157
+ lines.push("", "workflows:", " version: 2", " mcp-observatory-workflow:", " jobs:", " - mcp-observatory" + (options.schedule ? ":\n filters:\n branches:\n only: /scheduled-scan/" : ""));
158
+ return lines.join("\n");
159
+ }
160
+ function bitbucketYaml(options) {
161
+ const lines = [
162
+ "image: node:22",
163
+ "",
164
+ "pipelines:",
165
+ ];
166
+ if (options.schedule) {
167
+ lines.push(" custom:");
168
+ lines.push(" mcp-observatory-scheduled:");
169
+ }
170
+ else {
171
+ lines.push(" pull-requests:");
172
+ lines.push(" '**':");
173
+ }
174
+ lines.push(" - step:");
175
+ lines.push(" name: MCP Observatory Safety Check");
176
+ lines.push(" script:");
177
+ if (options.command) {
178
+ lines.push(` - npx @kryptosai/mcp-observatory test ${options.command} --deep --security` + (options.sarif !== false ? " --sarif mcp-observatory.sarif" : ""));
179
+ }
180
+ else if (options.all) {
181
+ lines.push(" - npx @kryptosai/mcp-observatory scan --deep --security" + (options.sarif !== false ? " --sarif mcp-observatory.sarif" : ""));
182
+ }
183
+ else {
184
+ lines.push(" - npx @kryptosai/mcp-observatory test --target mcp-observatory.target.json --deep --security");
185
+ }
186
+ if (options.sarif !== false) {
187
+ lines.push(" artifacts:", " - mcp-observatory.sarif");
188
+ }
189
+ if (!options.schedule && options.command) {
190
+ lines.push("", " branches:", " main:", " - step:", " name: MCP Observatory Safety Check", " script:", ` - npx @kryptosai/mcp-observatory test ${options.command} --deep --security` + (options.sarif !== false ? " --sarif mcp-observatory.sarif" : ""));
191
+ }
192
+ return lines.join("\n");
193
+ }
194
+ function azurePipelinesYaml(options) {
195
+ const lines = [
196
+ "trigger:",
197
+ " - main",
198
+ "",
199
+ ];
200
+ if (!options.schedule) {
201
+ lines.push("pr:", " - main", "");
202
+ }
203
+ else {
204
+ lines.push("schedules:", " - cron: '0 6 * * *'", " displayName: Daily MCP safety scan", " branches:", " include:", " - main", "");
205
+ }
206
+ lines.push("pool:", " vmImage: ubuntu-latest", "", "steps:", " - task: NodeTool@0", " inputs:", " versionSpec: '22.x'", " displayName: 'Install Node.js'", "", " - script: |");
207
+ if (options.command) {
208
+ lines.push(` npx @kryptosai/mcp-observatory test ${options.command} --deep --security` + (options.sarif !== false ? " --sarif mcp-observatory.sarif" : ""));
209
+ }
210
+ else if (options.all) {
211
+ lines.push(" npx @kryptosai/mcp-observatory scan --deep --security" + (options.sarif !== false ? " --sarif mcp-observatory.sarif" : ""));
212
+ }
213
+ else {
214
+ lines.push(" npx @kryptosai/mcp-observatory test --target mcp-observatory.target.json --deep --security");
215
+ }
216
+ lines.push(" displayName: 'MCP Observatory Safety Check'");
217
+ return lines.join("\n");
218
+ }
79
219
  function badgeMarkdown() {
80
220
  return [
81
221
  "[![MCP Observatory](https://img.shields.io/badge/MCP%20Observatory-enabled-2563eb)](https://github.com/KryptosAI/mcp-observatory)",
@@ -258,18 +398,21 @@ function doctorFixOptions(options, workflow) {
258
398
  };
259
399
  }
260
400
  export async function doctorSetupCi(options = {}) {
261
- const workflowPath = options.workflow ?? DEFAULT_WORKFLOW_PATH;
401
+ const detectedProvider = options.ciProvider ?? detectCiProvider() ?? "github-actions";
402
+ const defaultPath = CI_FILE_PATHS[detectedProvider] ?? DEFAULT_WORKFLOW_PATH;
403
+ const workflowPath = options.workflow ?? defaultPath;
262
404
  const badgePath = options.badgeFile ?? DEFAULT_BADGE_PATH;
263
405
  const targetConfigPath = optionPath(options.targetConfig, DEFAULT_TARGET_CONFIG_PATH);
264
406
  const prBodyPath = optionPath(options.prBody, DEFAULT_PR_BODY_PATH);
265
407
  const issueBodyPath = optionPath(options.issueBody, DEFAULT_ISSUE_BODY_PATH);
266
408
  const scoreBadgePath = optionPath(options.scoreBadge, DEFAULT_SCORE_BADGE_PATH);
409
+ const ciLabel = providerLabel(detectedProvider);
267
410
  const workflow = await readOptional(workflowPath);
268
411
  const checks = [];
269
412
  if (workflow === undefined) {
270
413
  checks.push({
271
414
  id: "workflow",
272
- label: "GitHub Action",
415
+ label: ciLabel,
273
416
  status: "fail",
274
417
  message: `${workflowPath} is missing.`,
275
418
  fix: setupCommand(options),
@@ -278,7 +421,7 @@ export async function doctorSetupCi(options = {}) {
278
421
  else {
279
422
  checks.push({
280
423
  id: "workflow",
281
- label: "GitHub Action",
424
+ label: ciLabel,
282
425
  status: "pass",
283
426
  message: `${workflowPath} exists.`,
284
427
  });
@@ -356,7 +499,9 @@ export async function initCi(options) {
356
499
  if (options.target && shouldWrite(options.targetConfig, options.all)) {
357
500
  throw new Error("Use either --target or --target-config, not both.");
358
501
  }
359
- const workflowPath = options.workflow ?? DEFAULT_WORKFLOW_PATH;
502
+ const detectedProvider = options.ciProvider ?? detectCiProvider() ?? "github-actions";
503
+ const defaultPath = CI_FILE_PATHS[detectedProvider] ?? DEFAULT_WORKFLOW_PATH;
504
+ const workflowPath = options.workflow ?? defaultPath;
360
505
  const badgePath = options.badgeFile ?? DEFAULT_BADGE_PATH;
361
506
  const workflowStatus = await writeFileOnce(workflowPath, workflowYaml(options), options.force === true);
362
507
  const result = {
@@ -410,7 +555,8 @@ function addInitCiOptions(command) {
410
555
  .option("--doctor", "Inspect the current repository's MCP Observatory CI adoption state.", false)
411
556
  .option("--fix", "With --doctor, repair the adoption kit with deep, security, SARIF, and weekly scheduled checks.", false)
412
557
  .option("--from-last-run", "Generate the adoption kit from the latest successful local run artifact.", false)
413
- .option("--campaign <slug>", "Attach a safe campaign/source slug to telemetry for attribution.");
558
+ .option("--campaign <slug>", "Attach a safe campaign/source slug to telemetry for attribution.")
559
+ .option("--identify <email>", "Opt-in: share your email to help us understand who uses Observatory. Never shared, never spammed.");
414
560
  }
415
561
  function initCiAction(commandName) {
416
562
  return async (options) => {
@@ -427,7 +573,8 @@ function initCiAction(commandName) {
427
573
  }
428
574
  process.stdout.write(`\nNext best action:\n ${result.nextCommand}\n`);
429
575
  if (options.fix) {
430
- const workflow = await readOptional(options.workflow ?? DEFAULT_WORKFLOW_PATH);
576
+ const defaultPath = CI_FILE_PATHS[options.ciProvider ?? detectCiProvider() ?? "github-actions"] ?? DEFAULT_WORKFLOW_PATH;
577
+ const workflow = await readOptional(options.workflow ?? defaultPath);
431
578
  const fixed = await initCi(doctorFixOptions(options, workflow));
432
579
  process.stdout.write("\nApplied repair:\n");
433
580
  process.stdout.write(`${fixed.workflowStatus}: ${fixed.workflowPath}\n`);
@@ -447,7 +594,7 @@ function initCiAction(commandName) {
447
594
  process.exitCode = 1;
448
595
  }
449
596
  recordEvent(buildEvent("command_complete", commandName, "cli", {
450
- ciProvider: "github-actions",
597
+ ciProvider: options.ciProvider ?? detectCiProvider() ?? "github-actions",
451
598
  setupCiDoctor: true,
452
599
  setupCiReady: result.ready,
453
600
  setupCiFailCount: result.checks.filter((check) => check.status === "fail").length,
@@ -503,7 +650,7 @@ function initCiAction(commandName) {
503
650
  }
504
651
  process.stdout.write("Next: commit the workflow, open a PR, and paste the generated PR body if present.\n");
505
652
  recordEvent(buildEvent("command_complete", commandName, "cli", {
506
- ciProvider: "github-actions",
653
+ ciProvider: options.ciProvider ?? detectCiProvider() ?? "github-actions",
507
654
  commitStatusSet: !skipped,
508
655
  campaign: options.campaign,
509
656
  }));