@kryptosai/mcp-observatory 0.3.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 (80) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +228 -0
  3. package/dist/src/adapters/http.d.ts +5 -0
  4. package/dist/src/adapters/http.js +54 -0
  5. package/dist/src/adapters/http.js.map +1 -0
  6. package/dist/src/adapters/local-process.d.ts +19 -0
  7. package/dist/src/adapters/local-process.js +63 -0
  8. package/dist/src/adapters/local-process.js.map +1 -0
  9. package/dist/src/checks/base.d.ts +28 -0
  10. package/dist/src/checks/base.js +42 -0
  11. package/dist/src/checks/base.js.map +1 -0
  12. package/dist/src/checks/list-check.d.ts +16 -0
  13. package/dist/src/checks/list-check.js +78 -0
  14. package/dist/src/checks/list-check.js.map +1 -0
  15. package/dist/src/checks/prompts.d.ts +2 -0
  16. package/dist/src/checks/prompts.js +11 -0
  17. package/dist/src/checks/prompts.js.map +1 -0
  18. package/dist/src/checks/resources.d.ts +2 -0
  19. package/dist/src/checks/resources.js +163 -0
  20. package/dist/src/checks/resources.js.map +1 -0
  21. package/dist/src/checks/tools-invoke.d.ts +2 -0
  22. package/dist/src/checks/tools-invoke.js +107 -0
  23. package/dist/src/checks/tools-invoke.js.map +1 -0
  24. package/dist/src/checks/tools.d.ts +2 -0
  25. package/dist/src/checks/tools.js +12 -0
  26. package/dist/src/checks/tools.js.map +1 -0
  27. package/dist/src/cli.d.ts +2 -0
  28. package/dist/src/cli.js +266 -0
  29. package/dist/src/cli.js.map +1 -0
  30. package/dist/src/diff.d.ts +2 -0
  31. package/dist/src/diff.js +98 -0
  32. package/dist/src/diff.js.map +1 -0
  33. package/dist/src/discovery.d.ts +7 -0
  34. package/dist/src/discovery.js +116 -0
  35. package/dist/src/discovery.js.map +1 -0
  36. package/dist/src/index.d.ts +9 -0
  37. package/dist/src/index.js +10 -0
  38. package/dist/src/index.js.map +1 -0
  39. package/dist/src/reporters/common.d.ts +7 -0
  40. package/dist/src/reporters/common.js +63 -0
  41. package/dist/src/reporters/common.js.map +1 -0
  42. package/dist/src/reporters/html.d.ts +2 -0
  43. package/dist/src/reporters/html.js +228 -0
  44. package/dist/src/reporters/html.js.map +1 -0
  45. package/dist/src/reporters/markdown.d.ts +2 -0
  46. package/dist/src/reporters/markdown.js +231 -0
  47. package/dist/src/reporters/markdown.js.map +1 -0
  48. package/dist/src/reporters/terminal.d.ts +2 -0
  49. package/dist/src/reporters/terminal.js +110 -0
  50. package/dist/src/reporters/terminal.js.map +1 -0
  51. package/dist/src/runner.d.ts +5 -0
  52. package/dist/src/runner.js +138 -0
  53. package/dist/src/runner.js.map +1 -0
  54. package/dist/src/schema-diff.d.ts +6 -0
  55. package/dist/src/schema-diff.js +73 -0
  56. package/dist/src/schema-diff.js.map +1 -0
  57. package/dist/src/storage.d.ts +6 -0
  58. package/dist/src/storage.js +32 -0
  59. package/dist/src/storage.js.map +1 -0
  60. package/dist/src/types.d.ts +120 -0
  61. package/dist/src/types.js +5 -0
  62. package/dist/src/types.js.map +1 -0
  63. package/dist/src/utils/failure-diagnosis.d.ts +2 -0
  64. package/dist/src/utils/failure-diagnosis.js +90 -0
  65. package/dist/src/utils/failure-diagnosis.js.map +1 -0
  66. package/dist/src/utils/ids.d.ts +2 -0
  67. package/dist/src/utils/ids.js +13 -0
  68. package/dist/src/utils/ids.js.map +1 -0
  69. package/dist/src/utils/schema-stub.d.ts +14 -0
  70. package/dist/src/utils/schema-stub.js +61 -0
  71. package/dist/src/utils/schema-stub.js.map +1 -0
  72. package/dist/src/validate.d.ts +4 -0
  73. package/dist/src/validate.js +97 -0
  74. package/dist/src/validate.js.map +1 -0
  75. package/dist/src/version.d.ts +1 -0
  76. package/dist/src/version.js +21 -0
  77. package/dist/src/version.js.map +1 -0
  78. package/package.json +76 -0
  79. package/schemas/diff-artifact.schema.json +132 -0
  80. package/schemas/run-artifact.schema.json +245 -0
@@ -0,0 +1,163 @@
1
+ import { performance } from "node:perf_hooks";
2
+ import { baseEvidence, isCapabilityAdvertised, makeCheckResult } from "./base.js";
3
+ function hasMinimalResourceShape(resource) {
4
+ return typeof resource.uri === "string" && resource.uri.trim().length > 0;
5
+ }
6
+ function hasMinimalTemplateShape(template) {
7
+ return (typeof template.uriTemplate === "string" &&
8
+ template.uriTemplate.trim().length > 0);
9
+ }
10
+ function isOptionalEndpointFailure(message) {
11
+ const lower = message.toLowerCase();
12
+ return (lower.includes("method not found") ||
13
+ lower.includes("not implemented") ||
14
+ lower.includes("not supported"));
15
+ }
16
+ export async function runResourcesCheck(context) {
17
+ const startedAt = performance.now();
18
+ const advertised = isCapabilityAdvertised(context.serverCapabilities, "resources");
19
+ if (!advertised) {
20
+ return {
21
+ observation: {
22
+ capability: "resources",
23
+ advertised: false,
24
+ responded: false,
25
+ minimalShapePresent: false,
26
+ endpoint: "resources/list | resources/templates/list",
27
+ diagnostics: []
28
+ },
29
+ result: makeCheckResult("resources", "unsupported", performance.now() - startedAt, "Resources are not advertised by the target.", [
30
+ {
31
+ endpoint: "resources/list | resources/templates/list",
32
+ advertised: false,
33
+ responded: false,
34
+ minimalShapePresent: false,
35
+ diagnostics: []
36
+ }
37
+ ])
38
+ };
39
+ }
40
+ const diagnostics = [];
41
+ const identifiers = [];
42
+ const endpointEvidence = [];
43
+ let itemCount = 0;
44
+ let respondedEndpoints = 0;
45
+ let hardEndpointFailures = 0;
46
+ let shapeProblems = 0;
47
+ try {
48
+ const listResources = await context.client.listResources(undefined, {
49
+ timeout: context.timeoutMs
50
+ });
51
+ itemCount += listResources.resources.length;
52
+ identifiers.push(...listResources.resources.map((resource) => resource.uri));
53
+ respondedEndpoints += 1;
54
+ const minimalShapePresent = listResources.resources.every(hasMinimalResourceShape);
55
+ if (!minimalShapePresent) {
56
+ shapeProblems += 1;
57
+ }
58
+ endpointEvidence.push(baseEvidence({
59
+ capability: "resources",
60
+ advertised: true,
61
+ responded: true,
62
+ minimalShapePresent,
63
+ endpoint: "resources/list",
64
+ itemCount: listResources.resources.length,
65
+ identifiers: listResources.resources.map((resource) => resource.uri),
66
+ diagnostics: []
67
+ }, context.stderrLines));
68
+ }
69
+ catch (error) {
70
+ const message = error instanceof Error ? error.message : String(error);
71
+ diagnostics.push(`resources/list: ${message}`);
72
+ if (!isOptionalEndpointFailure(message)) {
73
+ hardEndpointFailures += 1;
74
+ }
75
+ endpointEvidence.push(baseEvidence({
76
+ capability: "resources",
77
+ advertised: true,
78
+ responded: false,
79
+ minimalShapePresent: false,
80
+ endpoint: "resources/list",
81
+ diagnostics: [message]
82
+ }, context.stderrLines));
83
+ }
84
+ try {
85
+ const listTemplates = await context.client.listResourceTemplates(undefined, {
86
+ timeout: context.timeoutMs
87
+ });
88
+ itemCount += listTemplates.resourceTemplates.length;
89
+ const templateIdentifiers = listTemplates.resourceTemplates.map((template) => template.uriTemplate);
90
+ identifiers.push(...templateIdentifiers);
91
+ respondedEndpoints += 1;
92
+ const minimalShapePresent = listTemplates.resourceTemplates.every(hasMinimalTemplateShape);
93
+ if (!minimalShapePresent) {
94
+ shapeProblems += 1;
95
+ }
96
+ endpointEvidence.push(baseEvidence({
97
+ capability: "resources",
98
+ advertised: true,
99
+ responded: true,
100
+ minimalShapePresent,
101
+ endpoint: "resources/templates/list",
102
+ itemCount: listTemplates.resourceTemplates.length,
103
+ identifiers: templateIdentifiers,
104
+ diagnostics: []
105
+ }, context.stderrLines));
106
+ }
107
+ catch (error) {
108
+ const message = error instanceof Error ? error.message : String(error);
109
+ diagnostics.push(`resources/templates/list: ${message}`);
110
+ if (!isOptionalEndpointFailure(message)) {
111
+ hardEndpointFailures += 1;
112
+ }
113
+ endpointEvidence.push(baseEvidence({
114
+ capability: "resources",
115
+ advertised: true,
116
+ responded: false,
117
+ minimalShapePresent: false,
118
+ endpoint: "resources/templates/list",
119
+ diagnostics: [message]
120
+ }, context.stderrLines));
121
+ }
122
+ const responded = respondedEndpoints > 0;
123
+ const minimalShapePresent = responded && shapeProblems === 0;
124
+ const observation = {
125
+ capability: "resources",
126
+ advertised: true,
127
+ responded,
128
+ minimalShapePresent,
129
+ endpoint: "resources/list | resources/templates/list",
130
+ itemCount,
131
+ identifiers,
132
+ diagnostics
133
+ };
134
+ const status = !responded
135
+ ? "fail"
136
+ : hardEndpointFailures > 0 || shapeProblems > 0
137
+ ? "partial"
138
+ : "pass";
139
+ let message = "Advertised capability responded with the minimal expected shape.";
140
+ if (!responded) {
141
+ message = "Advertised capability did not respond successfully.";
142
+ }
143
+ else if (hardEndpointFailures > 0) {
144
+ message =
145
+ "Advertised capability responded, but at least one resource endpoint failed unexpectedly.";
146
+ }
147
+ else if (shapeProblems > 0) {
148
+ message =
149
+ "Advertised capability responded, but at least one resource endpoint missed the minimal expected shape.";
150
+ }
151
+ else if (diagnostics.length > 0) {
152
+ message =
153
+ "Advertised capability responded with the minimal expected shape, but one optional resource endpoint appears unsupported.";
154
+ }
155
+ else if (itemCount !== undefined) {
156
+ message = `Advertised capability responded with the minimal expected shape (${itemCount} items).`;
157
+ }
158
+ return {
159
+ observation,
160
+ result: makeCheckResult("resources", status, performance.now() - startedAt, message, endpointEvidence)
161
+ };
162
+ }
163
+ //# sourceMappingURL=resources.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resources.js","sourceRoot":"","sources":["../../../src/checks/resources.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { type CheckContext, type ObservedCheck } from "./base.js";
2
+ export declare function runToolsInvokeCheck(context: CheckContext): Promise<ObservedCheck>;
@@ -0,0 +1,107 @@
1
+ import { performance } from "node:perf_hooks";
2
+ import { isSafeToInvoke, stubFromSchema } from "../utils/schema-stub.js";
3
+ import { isCapabilityAdvertised, makeCheckResult } from "./base.js";
4
+ export async function runToolsInvokeCheck(context) {
5
+ const startedAt = performance.now();
6
+ const advertised = isCapabilityAdvertised(context.serverCapabilities, "tools");
7
+ if (!advertised) {
8
+ return {
9
+ result: makeCheckResult("tools-invoke", "unsupported", performance.now() - startedAt, "Tools are not advertised by the target.", [{
10
+ endpoint: "tools/call",
11
+ advertised: false,
12
+ responded: false,
13
+ minimalShapePresent: false,
14
+ diagnostics: []
15
+ }])
16
+ };
17
+ }
18
+ let tools;
19
+ try {
20
+ const resp = await context.client.listTools(undefined, { timeout: context.timeoutMs });
21
+ tools = resp.tools;
22
+ }
23
+ catch (error) {
24
+ const msg = error instanceof Error ? error.message : String(error);
25
+ return {
26
+ result: makeCheckResult("tools-invoke", "fail", performance.now() - startedAt, `Failed to list tools before invocation: ${msg}`, [{
27
+ endpoint: "tools/list",
28
+ advertised: true,
29
+ responded: false,
30
+ minimalShapePresent: false,
31
+ diagnostics: [msg]
32
+ }])
33
+ };
34
+ }
35
+ const safeTools = tools.filter((t) => isSafeToInvoke({
36
+ inputSchema: t.inputSchema,
37
+ annotations: t.annotations,
38
+ }));
39
+ if (safeTools.length === 0) {
40
+ return {
41
+ result: makeCheckResult("tools-invoke", "pass", performance.now() - startedAt, `${tools.length} tool(s) found but none are safe to invoke (all have required parameters). Listing check covers these.`, [{
42
+ endpoint: "tools/call",
43
+ advertised: true,
44
+ responded: true,
45
+ minimalShapePresent: true,
46
+ itemCount: 0,
47
+ identifiers: [],
48
+ diagnostics: []
49
+ }])
50
+ };
51
+ }
52
+ const results = [];
53
+ for (const tool of safeTools) {
54
+ const args = stubFromSchema(tool.inputSchema);
55
+ try {
56
+ const response = await context.client.callTool({ name: tool.name, arguments: args }, undefined, { timeout: context.timeoutMs });
57
+ const isError = response.isError === true;
58
+ results.push({
59
+ name: tool.name,
60
+ invoked: true,
61
+ responded: true,
62
+ isError,
63
+ error: isError ? String(response.content) : undefined,
64
+ });
65
+ }
66
+ catch (error) {
67
+ const msg = error instanceof Error ? error.message : String(error);
68
+ results.push({
69
+ name: tool.name,
70
+ invoked: true,
71
+ responded: false,
72
+ isError: true,
73
+ error: msg,
74
+ });
75
+ }
76
+ }
77
+ const passed = results.filter((r) => r.responded && !r.isError);
78
+ const failed = results.filter((r) => !r.responded || r.isError);
79
+ const diagnostics = failed.map((r) => `${r.name}: ${r.error ?? "no response"}`);
80
+ let status;
81
+ if (failed.length === 0) {
82
+ status = "pass";
83
+ }
84
+ else if (passed.length > 0) {
85
+ status = "partial";
86
+ }
87
+ else {
88
+ status = "fail";
89
+ }
90
+ const message = `Invoked ${results.length}/${safeTools.length} safe tool(s): ` +
91
+ `${passed.length} passed, ${failed.length} failed` +
92
+ (tools.length > safeTools.length
93
+ ? ` (${tools.length - safeTools.length} skipped — have required params)`
94
+ : "");
95
+ return {
96
+ result: makeCheckResult("tools-invoke", status, performance.now() - startedAt, message, [{
97
+ endpoint: "tools/call",
98
+ advertised: true,
99
+ responded: failed.length === 0,
100
+ minimalShapePresent: true,
101
+ itemCount: results.length,
102
+ identifiers: results.map((r) => r.name),
103
+ diagnostics,
104
+ }])
105
+ };
106
+ }
107
+ //# sourceMappingURL=tools-invoke.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools-invoke.js","sourceRoot":"","sources":["../../../src/checks/tools-invoke.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { CheckContext, ObservedCheck } from "./base.js";
2
+ export declare function runToolsCheck(context: CheckContext): Promise<ObservedCheck>;
@@ -0,0 +1,12 @@
1
+ import { runListCheck } from "./list-check.js";
2
+ export async function runToolsCheck(context) {
3
+ return runListCheck({
4
+ capability: "tools",
5
+ endpoint: "tools/list",
6
+ listItems: async (ctx) => (await ctx.client.listTools(undefined, { timeout: ctx.timeoutMs })).tools,
7
+ hasMinimalShape: (tool) => typeof tool.name === "string" && tool.name.trim().length > 0,
8
+ getItemName: (tool) => tool.name,
9
+ getItemSchema: (tool) => tool.inputSchema,
10
+ }, context);
11
+ }
12
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../../../src/checks/tools.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,OAAqB;IACvD,OAAO,YAAY,CAAO;QACxB,UAAU,EAAE,OAAO;QACnB,QAAQ,EAAE,YAAY;QACtB,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,OAAO,EAAE,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,KAAK;QACnG,eAAe,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC;QACvF,WAAW,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI;QAChC,aAAa,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,WAAiC;KAChE,EAAE,OAAO,CAAC,CAAC;AACd,CAAC"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,266 @@
1
+ #!/usr/bin/env node
2
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
3
+ import path from "node:path";
4
+ import { Command } from "commander";
5
+ import { scanForTargets } from "./discovery.js";
6
+ import { diffArtifacts, readArtifact, renderHtml, renderMarkdown, renderTerminal, runTarget, writeRunArtifact } from "./index.js";
7
+ import { defaultRunsDirectory } from "./storage.js";
8
+ import { validateTargetConfig } from "./validate.js";
9
+ import { TOOL_VERSION } from "./version.js";
10
+ async function readTargetConfig(filePath) {
11
+ const content = await readFile(filePath, "utf8");
12
+ return validateTargetConfig(JSON.parse(content));
13
+ }
14
+ function useColor() {
15
+ return !process.env["NO_COLOR"] && !process.argv.includes("--no-color");
16
+ }
17
+ const ANSI = {
18
+ red: "\x1b[31m",
19
+ green: "\x1b[32m",
20
+ yellow: "\x1b[33m",
21
+ dim: "\x1b[2m",
22
+ bold: "\x1b[1m",
23
+ reset: "\x1b[0m",
24
+ };
25
+ function c(code, text) {
26
+ return useColor() ? `${code}${text}${ANSI.reset}` : text;
27
+ }
28
+ async function main() {
29
+ const program = new Command();
30
+ program
31
+ .name("mcp-observatory")
32
+ .description("Regression intelligence for MCP targets: detect, diff, and explain interoperability drift over time.")
33
+ .version(TOOL_VERSION);
34
+ program
35
+ .command("run")
36
+ .requiredOption("--target <config>", "Path to a target config JSON file.")
37
+ .option("--out-dir <directory>", "Directory for persisted run artifacts.", defaultRunsDirectory(process.cwd()))
38
+ .option("--watch", "Re-run checks on an interval and diff against the previous run.", false)
39
+ .option("--interval <seconds>", "Interval in seconds for watch mode.", "30")
40
+ .option("--invoke-tools", "Invoke safe tools (no required params) to verify they execute.", false)
41
+ .option("--no-color", "Disable colored output.")
42
+ .action(async (options) => {
43
+ const target = await readTargetConfig(options.target);
44
+ if (options.watch) {
45
+ await runWatchMode(target, options.outDir, parseInt(options.interval, 10) || 30);
46
+ return;
47
+ }
48
+ const artifact = await runTarget(target, { invokeTools: options.invokeTools });
49
+ const outPath = await writeRunArtifact(artifact, options.outDir);
50
+ const summary = renderTerminal(artifact);
51
+ process.stdout.write(`${summary}\nArtifact: ${outPath}\n`);
52
+ });
53
+ program
54
+ .command("diff")
55
+ .requiredOption("--base <artifact>", "Base run artifact JSON.")
56
+ .requiredOption("--head <artifact>", "Head run artifact JSON.")
57
+ .option("--format <format>", "terminal, json, markdown, or html", "terminal")
58
+ .option("--output <file>", "Optional output file path (useful for html format).")
59
+ .option("--no-color", "Disable colored output.")
60
+ .option("--fail-on-regression", "Exit with code 1 when regressions are present.", false)
61
+ .action(async (options) => {
62
+ const baseArtifact = await readArtifact(options.base);
63
+ const headArtifact = await readArtifact(options.head);
64
+ if (baseArtifact.artifactType !== "run" || headArtifact.artifactType !== "run") {
65
+ throw new Error("The diff command only accepts run artifacts.");
66
+ }
67
+ const artifact = diffArtifacts(baseArtifact, headArtifact);
68
+ const output = options.format === "json"
69
+ ? JSON.stringify(artifact, null, 2)
70
+ : options.format === "markdown"
71
+ ? renderMarkdown(artifact)
72
+ : options.format === "html"
73
+ ? renderHtml(artifact)
74
+ : renderTerminal(artifact);
75
+ if (options.output !== undefined) {
76
+ await mkdir(path.dirname(options.output), { recursive: true });
77
+ await writeFile(options.output, output + "\n", "utf8");
78
+ process.stdout.write(`Wrote ${options.format} report to ${options.output}\n`);
79
+ }
80
+ else {
81
+ process.stdout.write(`${output}\n`);
82
+ }
83
+ if (options.failOnRegression && artifact.gate === "fail") {
84
+ process.exitCode = 1;
85
+ }
86
+ });
87
+ program
88
+ .command("report")
89
+ .requiredOption("--run <artifact>", "Run artifact JSON.")
90
+ .option("--format <format>", "terminal, markdown, json, or html", "terminal")
91
+ .option("--output <file>", "Optional output file path (useful for html format).")
92
+ .option("--no-color", "Disable colored output.")
93
+ .action(async (options) => {
94
+ const artifact = await readArtifact(options.run);
95
+ if (artifact.artifactType !== "run") {
96
+ throw new Error("The report command only accepts run artifacts.");
97
+ }
98
+ const output = options.format === "json"
99
+ ? JSON.stringify(artifact, null, 2)
100
+ : options.format === "markdown"
101
+ ? renderMarkdown(artifact)
102
+ : options.format === "html"
103
+ ? renderHtml(artifact)
104
+ : renderTerminal(artifact);
105
+ if (options.output !== undefined) {
106
+ await mkdir(path.dirname(options.output), { recursive: true });
107
+ await writeFile(options.output, output + "\n", "utf8");
108
+ process.stdout.write(`Wrote ${options.format} report to ${options.output}\n`);
109
+ return;
110
+ }
111
+ process.stdout.write(`${output}\n`);
112
+ });
113
+ program
114
+ .command("scan")
115
+ .description("Auto-discover MCP server configs and run checks against each discovered server.")
116
+ .option("--config <path>", "Path to a specific MCP config file.")
117
+ .option("--invoke-tools", "Invoke safe tools (no required params) to verify they execute.", false)
118
+ .option("--no-color", "Disable colored output.")
119
+ .action(async (options) => {
120
+ const targets = await scanForTargets(options.config);
121
+ if (targets.length === 0) {
122
+ process.stdout.write("No MCP server configs found.\n");
123
+ return;
124
+ }
125
+ process.stdout.write(c(ANSI.bold, `Discovered ${targets.length} MCP server(s):\n`));
126
+ for (const t of targets) {
127
+ process.stdout.write(` ${t.config.targetId} (from ${t.source})\n`);
128
+ }
129
+ process.stdout.write("\n");
130
+ const results = [];
131
+ for (const t of targets) {
132
+ process.stdout.write(`Running checks for ${c(ANSI.bold, t.config.targetId)}...\n`);
133
+ try {
134
+ const artifact = await runTarget(t.config, { invokeTools: options.invokeTools });
135
+ const toolsStatus = artifact.checks.find((ch) => ch.id === "tools")?.status ?? "skipped";
136
+ const promptsStatus = artifact.checks.find((ch) => ch.id === "prompts")?.status ?? "skipped";
137
+ const resourcesStatus = artifact.checks.find((ch) => ch.id === "resources")?.status ?? "skipped";
138
+ const invokeStatus = artifact.checks.find((ch) => ch.id === "tools-invoke")?.status;
139
+ results.push({
140
+ targetId: t.config.targetId,
141
+ gate: artifact.gate,
142
+ tools: toolsStatus,
143
+ prompts: promptsStatus,
144
+ resources: resourcesStatus,
145
+ invoke: invokeStatus,
146
+ });
147
+ }
148
+ catch (error) {
149
+ const msg = error instanceof Error ? error.message : String(error);
150
+ results.push({
151
+ targetId: t.config.targetId,
152
+ gate: "fail",
153
+ tools: "skipped",
154
+ prompts: "skipped",
155
+ resources: "skipped",
156
+ });
157
+ process.stderr.write(` Error: ${msg}\n`);
158
+ }
159
+ }
160
+ const showInvoke = options.invokeTools;
161
+ process.stdout.write("\n" + c(ANSI.bold, "Scan Results:\n"));
162
+ let header = `${"Target".padEnd(30)} ${"Gate".padEnd(6)} ${"Tools".padEnd(14)} ${"Prompts".padEnd(14)} ${"Resources".padEnd(14)}`;
163
+ let separator = `${"─".repeat(30)} ${"─".repeat(6)} ${"─".repeat(14)} ${"─".repeat(14)} ${"─".repeat(14)}`;
164
+ if (showInvoke) {
165
+ header += ` ${"Invoke".padEnd(14)}`;
166
+ separator += ` ${"─".repeat(14)}`;
167
+ }
168
+ process.stdout.write(`${header}\n${separator}\n`);
169
+ for (const r of results) {
170
+ const gateStr = r.gate === "pass" ? c(ANSI.green, "pass") : c(ANSI.red, "fail");
171
+ const pad = useColor() ? 9 : 0;
172
+ let line = `${r.targetId.padEnd(30)} ${gateStr.padEnd(6 + pad)} ${colorStatus(r.tools).padEnd(14 + pad)} ${colorStatus(r.prompts).padEnd(14 + pad)} ${colorStatus(r.resources).padEnd(14 + pad)}`;
173
+ if (showInvoke) {
174
+ line += ` ${colorStatus(r.invoke ?? "skipped")}`;
175
+ }
176
+ process.stdout.write(`${line}\n`);
177
+ }
178
+ });
179
+ program
180
+ .command("check")
181
+ .description("Run a single capability check against a target.")
182
+ .argument("<capability>", "Capability to check: tools, prompts, resources, or tools-invoke.")
183
+ .requiredOption("--target <config>", "Path to a target config JSON file.")
184
+ .option("--no-color", "Disable colored output.")
185
+ .action(async (capability, options) => {
186
+ const validCapabilities = ["tools", "prompts", "resources", "tools-invoke"];
187
+ if (!validCapabilities.includes(capability)) {
188
+ throw new Error(`Invalid capability '${capability}'. Must be one of: ${validCapabilities.join(", ")}`);
189
+ }
190
+ const target = await readTargetConfig(options.target);
191
+ const invokeTools = capability === "tools-invoke";
192
+ const artifact = await runTarget(target, { invokeTools });
193
+ const check = artifact.checks.find((ch) => ch.id === capability);
194
+ if (!check) {
195
+ throw new Error(`Check '${capability}' was not found in the run results.`);
196
+ }
197
+ const statusStr = colorStatus(check.status);
198
+ process.stdout.write(`${c(ANSI.bold, capability)}: ${statusStr}\n`);
199
+ process.stdout.write(`${check.message}\n`);
200
+ if (check.evidence.length > 0) {
201
+ for (const ev of check.evidence) {
202
+ if (ev.identifiers && ev.identifiers.length > 0) {
203
+ process.stdout.write(`Items: ${ev.identifiers.join(", ")}\n`);
204
+ }
205
+ if (ev.diagnostics && ev.diagnostics.length > 0) {
206
+ process.stdout.write(`Diagnostics: ${ev.diagnostics.join("; ")}\n`);
207
+ }
208
+ }
209
+ }
210
+ });
211
+ // Default to scan when invoked with no arguments
212
+ if (process.argv.length === 2) {
213
+ process.argv.push("scan");
214
+ }
215
+ await program.parseAsync(process.argv);
216
+ }
217
+ function colorStatus(status) {
218
+ switch (status) {
219
+ case "pass":
220
+ return c(ANSI.green, status);
221
+ case "fail":
222
+ return c(ANSI.red, status);
223
+ case "partial":
224
+ case "flaky":
225
+ return c(ANSI.yellow, status);
226
+ case "unsupported":
227
+ case "skipped":
228
+ return c(ANSI.dim, status);
229
+ default:
230
+ return status;
231
+ }
232
+ }
233
+ async function runWatchMode(target, outDir, intervalSeconds) {
234
+ const { diffArtifacts: diff } = await import("./diff.js");
235
+ process.stdout.write(`Watch mode: checking every ${intervalSeconds}s. Press Ctrl+C to stop.\n\n`);
236
+ let previousArtifact = await runTarget(target);
237
+ await writeRunArtifact(previousArtifact, outDir);
238
+ process.stdout.write(`${renderTerminal(previousArtifact)}\n\n`);
239
+ const loop = async () => {
240
+ await new Promise((resolve) => setTimeout(resolve, intervalSeconds * 1000));
241
+ const currentArtifact = await runTarget(target);
242
+ const diffResult = diff(previousArtifact, currentArtifact);
243
+ if (diffResult.summary.regressions > 0 || diffResult.summary.recoveries > 0 || diffResult.summary.added > 0 || diffResult.summary.removed > 0) {
244
+ const outPath = await writeRunArtifact(currentArtifact, outDir);
245
+ process.stdout.write(`\n--- Change detected at ${currentArtifact.createdAt} ---\n`);
246
+ process.stdout.write(`${renderTerminal(diffResult)}\n`);
247
+ process.stdout.write(`Artifact: ${outPath}\n\n`);
248
+ }
249
+ previousArtifact = currentArtifact;
250
+ void loop();
251
+ };
252
+ void loop();
253
+ // Keep the process alive until Ctrl+C
254
+ await new Promise((resolve) => {
255
+ process.on("SIGINT", () => {
256
+ process.stdout.write("\nWatch mode stopped.\n");
257
+ resolve();
258
+ });
259
+ });
260
+ }
261
+ void main().catch((error) => {
262
+ const message = error instanceof Error ? error.message : String(error);
263
+ process.stderr.write(`${message}\n`);
264
+ process.exitCode = 1;
265
+ });
266
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { DiffArtifact, RunArtifact } from "./types.js";
2
+ export declare function diffArtifacts(base: RunArtifact, head: RunArtifact): DiffArtifact;