@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
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 KryptosAI
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,228 @@
1
+ # MCP Observatory
2
+
3
+ [![CI](https://github.com/KryptosAI/mcp-observatory/actions/workflows/ci.yml/badge.svg)](https://github.com/KryptosAI/mcp-observatory/actions/workflows/ci.yml)
4
+ [![Real Server Matrix](https://github.com/KryptosAI/mcp-observatory/actions/workflows/real-server-matrix.yml/badge.svg)](https://github.com/KryptosAI/mcp-observatory/actions/workflows/real-server-matrix.yml)
5
+ [![Latest Release](https://img.shields.io/github/v/release/KryptosAI/mcp-observatory?display_name=tag)](https://github.com/KryptosAI/mcp-observatory/releases)
6
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](./LICENSE)
7
+ [![Node >= 20](https://img.shields.io/badge/node-%3E%3D20-339933)](./package.json)
8
+
9
+ Regression evidence for Node/local-process stdio MCP targets.
10
+
11
+ Current status: GitHub-release-installable, tested against 7 real servers, and still at zero external adoption proof until that changes. The public package identity is `@kryptosai/mcp-observatory`; npm publishing is wired into the release flow but needs credentials before it becomes a live install path.
12
+
13
+ > Maintainer note, March 19, 2026: this repo exists because real MCP servers drift in ways conformance does not explain. Some servers pass cleanly with very different capability shapes. Others time out or close early when treated as plain stdio targets. Both outcomes are useful evidence.
14
+
15
+ ## Install
16
+
17
+ ```bash
18
+ # npm (when published)
19
+ npx @kryptosai/mcp-observatory
20
+
21
+ # or from GitHub release tarball
22
+ npx --yes https://github.com/KryptosAI/mcp-observatory/releases/download/v0.3.0/kryptosai-mcp-observatory-0.3.0.tgz
23
+ ```
24
+
25
+ Running with no arguments auto-discovers your MCP servers and checks them all.
26
+
27
+ Create one tiny target config in any directory:
28
+
29
+ ```json
30
+ {
31
+ "targetId": "filesystem-cli-proof",
32
+ "adapter": "local-process",
33
+ "command": "npx",
34
+ "args": ["-y", "@modelcontextprotocol/server-filesystem", "."],
35
+ "timeoutMs": 15000,
36
+ "metadata": {
37
+ "package": "@modelcontextprotocol/server-filesystem",
38
+ "purpose": "standalone-cli-proof"
39
+ }
40
+ }
41
+ ```
42
+
43
+ Run it:
44
+
45
+ ```bash
46
+ npx --yes https://github.com/KryptosAI/mcp-observatory/releases/download/v0.2.0/kryptosai-mcp-observatory-0.2.0.tgz run --target ./filesystem-target.json
47
+ ```
48
+
49
+ ## Known-Good Matrix
50
+
51
+ Passing matrix refreshed on 2026-03-19:
52
+
53
+ | Target | Package | Tools | Prompts | Resources | Why it matters |
54
+ | --- | --- | --- | --- | --- | --- |
55
+ | [filesystem-server.json](./examples/targets/filesystem-server.json) | `@modelcontextprotocol/server-filesystem` | pass | unsupported | unsupported | baseline proof that unsupported is not failure |
56
+ | [everything-server.json](./examples/targets/everything-server.json) | `@modelcontextprotocol/server-everything` | pass | pass | pass | broad official reference target |
57
+ | [ref-tools-server.json](./examples/targets/ref-tools-server.json) | `ref-tools-mcp` | pass | pass | unsupported | third-party prompts-capable proof |
58
+ | [context7-server.json](./examples/targets/context7-server.json) | `@upstash/context7-mcp` | pass | unsupported | unsupported | zero-config third-party tools proof |
59
+ | [puppeteer-server.json](./examples/targets/puppeteer-server.json) | `puppeteer-mcp-server` | pass | unsupported | pass | browser-oriented resources case with an optional-endpoint caveat |
60
+ | [promptopia-server.json](./examples/targets/promptopia-server.json) | `promptopia-mcp` | pass | pass | unsupported | second third-party prompts-capable server |
61
+ | [opentofu-server.json](./examples/targets/opentofu-server.json) | `@opentofu/opentofu-mcp-server` | pass | unsupported | pass | second third-party resources-capable server |
62
+
63
+ To refresh the matrix locally:
64
+
65
+ ```bash
66
+ npm run integration:real
67
+ ```
68
+
69
+ ## Working Surface
70
+
71
+ - `run`: execute checks against one target and persist a run artifact
72
+ - `diff`: compare two runs and classify regressions, recoveries, and schema drift
73
+ - `report`: turn a saved run artifact into readable terminal, JSON, or Markdown output
74
+ - `scan`: auto-discover MCP servers from local config files and check them all (default command)
75
+ - `check`: run a single capability check (tools, prompts, resources, or tools-invoke)
76
+
77
+ ## Scan
78
+
79
+ Auto-discover MCP server configs from Claude Code, Claude Desktop, and project-level config files, then run checks against every discovered server. This is the default command — running `mcp-observatory` with no arguments runs scan:
80
+
81
+ ```bash
82
+ mcp-observatory
83
+ mcp-observatory scan
84
+ mcp-observatory scan --config ~/.claude.json
85
+ mcp-observatory scan --invoke-tools
86
+ ```
87
+
88
+ Scanned locations (in order):
89
+ - `~/.claude.json` (Claude Code)
90
+ - `~/Library/Application Support/Claude/claude_desktop_config.json` (Claude Desktop, macOS)
91
+ - `%APPDATA%/Claude/claude_desktop_config.json` (Claude Desktop, Windows)
92
+ - `.claude.json` (current directory)
93
+ - `.mcp.json` (current directory)
94
+
95
+ ## Check
96
+
97
+ Run a single capability check for faster iteration:
98
+
99
+ ```bash
100
+ mcp-observatory check tools --target ./my-server.json
101
+ mcp-observatory check prompts --target ./my-server.json
102
+ mcp-observatory check resources --target ./my-server.json
103
+ mcp-observatory check tools-invoke --target ./my-server.json
104
+ ```
105
+
106
+ ## Tool Invocation
107
+
108
+ Go beyond listing — actually call tools and verify they execute. Only safe tools are invoked: those with no required parameters or with `readOnlyHint` annotation. Arguments are auto-generated from the tool's JSON Schema.
109
+
110
+ ```bash
111
+ mcp-observatory scan --invoke-tools
112
+ mcp-observatory run --target ./my-server.json --invoke-tools
113
+ mcp-observatory check tools-invoke --target ./my-server.json
114
+ ```
115
+
116
+ ## Schema Drift
117
+
118
+ When diffing two runs, schema changes are detected automatically. Added/removed required fields, property changes, and type changes are surfaced alongside status regressions:
119
+
120
+ ```bash
121
+ mcp-observatory diff --base run-a.json --head run-b.json
122
+ ```
123
+
124
+ Example output:
125
+ ```
126
+ Schema Drift:
127
+ - search (tools): added required field 'limit', changed 'query' type from 'number' to 'string'
128
+ - old-tool (tools): removed
129
+ ```
130
+
131
+ ## Watch
132
+
133
+ Re-run checks on an interval and output only when something changes:
134
+
135
+ ```bash
136
+ mcp-observatory run --target ./my-server.json --watch
137
+ mcp-observatory run --target ./my-server.json --watch --interval 60
138
+ ```
139
+
140
+ Press Ctrl+C to stop.
141
+
142
+ ## HTTP / SSE Targets
143
+
144
+ In addition to local-process stdio, you can check remote MCP servers over HTTP (Streamable HTTP and SSE):
145
+
146
+ ```json
147
+ {
148
+ "targetId": "my-remote-server",
149
+ "adapter": "http",
150
+ "url": "http://localhost:3000/mcp",
151
+ "authToken": "optional-bearer-token",
152
+ "timeoutMs": 15000
153
+ }
154
+ ```
155
+
156
+ ```bash
157
+ mcp-observatory run --target ./remote-target.json
158
+ mcp-observatory run --target ./remote-target.json --invoke-tools
159
+ ```
160
+
161
+ ## HTML Reports
162
+
163
+ Generate a self-contained HTML report from any run or diff artifact:
164
+
165
+ ```bash
166
+ mcp-observatory report --run ./run-artifact.json --format html --output report.html
167
+ mcp-observatory diff --base run-a.json --head run-b.json --format html --output diff.html
168
+ ```
169
+
170
+ Open the file in any browser — no server required, shareable via Slack/email/GitHub comments.
171
+
172
+ ## Do Not Use This If...
173
+
174
+ - you need deep semantic correctness validation
175
+ - you need every MCP package on npm to work out of the box
176
+
177
+ If those are the requirements, this repo is the wrong tool.
178
+
179
+ ## Repo-Local Validation
180
+
181
+ If you do want the repo-local path, use the fixture flow:
182
+
183
+ ```bash
184
+ npm install
185
+ npm run cli -- run --target tests/fixtures/sample-target-config.json
186
+ npm run cli -- diff --base tests/fixtures/sample-run-a.json --head tests/fixtures/sample-run-b.json
187
+ npm run cli -- report --run tests/fixtures/sample-run-b.json --format markdown --output examples/results/sample-report.md
188
+ ```
189
+
190
+ This path exists to validate the repo itself. It is not the only way to use the tool.
191
+
192
+ ## Artifact Contract
193
+
194
+ Every artifact is versioned and intentionally boring:
195
+
196
+ - `artifactType`: `run` or `diff`
197
+ - `schemaVersion`: currently `1.0.0`
198
+ - `gate`: `pass` or `fail`
199
+
200
+ Compatibility rules:
201
+
202
+ - additive changes stay within `1.x`
203
+ - breaking artifact changes require a major schema bump
204
+
205
+ Published schemas:
206
+
207
+ - [schemas/run-artifact.schema.json](./schemas/run-artifact.schema.json)
208
+ - [schemas/diff-artifact.schema.json](./schemas/diff-artifact.schema.json)
209
+
210
+ Validate checked-in artifacts locally:
211
+
212
+ ```bash
213
+ npm run validate:artifacts
214
+ ```
215
+
216
+ ## Contributing
217
+
218
+ See [CONTRIBUTING.md](./CONTRIBUTING.md) for the contribution bar and the kinds of work likely to be declined.
219
+
220
+ The fastest way to contribute something credible is to add evidence:
221
+
222
+ - a real passing target with a distinct capability shape
223
+ - a clearer report surface
224
+ - a cleaner startup diagnosis
225
+
226
+ ## Known Issues
227
+
228
+ See [docs/known-issues.md](./docs/known-issues.md) for the difference between `unsupported` and `failed`, plus the current list of packages that do not behave like drop-in stdio targets under the local-process harness.
@@ -0,0 +1,5 @@
1
+ import type { HttpTargetConfig } from "../types.js";
2
+ import type { AdapterSession } from "./local-process.js";
3
+ export declare class HttpAdapter {
4
+ connect(target: HttpTargetConfig): Promise<AdapterSession>;
5
+ }
@@ -0,0 +1,54 @@
1
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
2
+ import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
3
+ import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
4
+ import { formatConnectionFailureDiagnosis } from "../utils/failure-diagnosis.js";
5
+ import { TOOL_VERSION } from "../version.js";
6
+ export class HttpAdapter {
7
+ async connect(target) {
8
+ const headers = { ...(target.headers ?? {}) };
9
+ if (target.authToken) {
10
+ headers["Authorization"] = `Bearer ${target.authToken}`;
11
+ }
12
+ const client = new Client({ name: "mcp-observatory", version: TOOL_VERSION }, { capabilities: {} });
13
+ const stderrLines = [];
14
+ const url = new URL(target.url);
15
+ const timeoutMs = target.timeoutMs ?? 15_000;
16
+ // Try streamable-http first, fall back to SSE
17
+ let connected = false;
18
+ try {
19
+ const transport = new StreamableHTTPClientTransport(url, { requestInit: { headers } });
20
+ await client.connect(transport, { timeout: timeoutMs });
21
+ connected = true;
22
+ }
23
+ catch {
24
+ stderrLines.push("Streamable HTTP failed, falling back to SSE.");
25
+ }
26
+ if (!connected) {
27
+ try {
28
+ const transport = new SSEClientTransport(url, { requestInit: { headers } });
29
+ await client.connect(transport, { timeout: timeoutMs });
30
+ connected = true;
31
+ }
32
+ catch (error) {
33
+ const rawMessage = error instanceof Error ? error.message : String(error);
34
+ await client.close().catch(() => undefined);
35
+ const msg = formatConnectionFailureDiagnosis(target, rawMessage, stderrLines);
36
+ const err = new Error(msg);
37
+ err.name = "AdapterConnectError";
38
+ throw err;
39
+ }
40
+ }
41
+ const serverVersion = client.getServerVersion();
42
+ return {
43
+ client,
44
+ serverCapabilities: client.getServerCapabilities(),
45
+ serverName: serverVersion?.name,
46
+ serverVersion: serverVersion?.version,
47
+ stderrLines,
48
+ close: async () => {
49
+ await client.close();
50
+ },
51
+ };
52
+ }
53
+ }
54
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../../src/adapters/http.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
2
+ import type { ServerCapabilities } from "@modelcontextprotocol/sdk/types.js";
3
+ import type { LocalProcessTargetConfig, TargetConfig } from "../types.js";
4
+ export interface AdapterSession {
5
+ client: Client;
6
+ serverCapabilities?: ServerCapabilities;
7
+ serverName?: string;
8
+ serverVersion?: string;
9
+ stderrLines: string[];
10
+ close(): Promise<void>;
11
+ }
12
+ export declare class AdapterConnectError extends Error {
13
+ readonly rawMessage: string;
14
+ readonly stderrLines: string[];
15
+ constructor(target: TargetConfig, rawMessage: string, stderrLines: string[]);
16
+ }
17
+ export declare class LocalProcessAdapter {
18
+ connect(target: LocalProcessTargetConfig): Promise<AdapterSession>;
19
+ }
@@ -0,0 +1,63 @@
1
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
2
+ import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
3
+ import { formatConnectionFailureDiagnosis } from "../utils/failure-diagnosis.js";
4
+ import { TOOL_VERSION } from "../version.js";
5
+ export class AdapterConnectError extends Error {
6
+ rawMessage;
7
+ stderrLines;
8
+ constructor(target, rawMessage, stderrLines) {
9
+ super(formatConnectionFailureDiagnosis(target, rawMessage, stderrLines));
10
+ this.name = "AdapterConnectError";
11
+ this.rawMessage = rawMessage;
12
+ this.stderrLines = stderrLines;
13
+ }
14
+ }
15
+ export class LocalProcessAdapter {
16
+ async connect(target) {
17
+ const transport = new StdioClientTransport({
18
+ command: target.command,
19
+ args: target.args,
20
+ cwd: target.cwd,
21
+ env: target.env,
22
+ stderr: "pipe"
23
+ });
24
+ const stderrLines = [];
25
+ transport.stderr?.on("data", (chunk) => {
26
+ const text = typeof chunk === "string" ? chunk : chunk.toString("utf8");
27
+ for (const line of text.split(/\r?\n/)) {
28
+ const trimmed = line.trim();
29
+ if (trimmed.length > 0) {
30
+ stderrLines.push(trimmed);
31
+ }
32
+ }
33
+ });
34
+ const client = new Client({
35
+ name: "mcp-observatory",
36
+ version: TOOL_VERSION
37
+ }, {
38
+ capabilities: {}
39
+ });
40
+ try {
41
+ await client.connect(transport, {
42
+ timeout: target.timeoutMs ?? 10_000
43
+ });
44
+ }
45
+ catch (error) {
46
+ const rawMessage = error instanceof Error ? error.message : String(error);
47
+ await client.close().catch(() => undefined);
48
+ throw new AdapterConnectError(target, rawMessage, stderrLines);
49
+ }
50
+ const serverVersion = client.getServerVersion();
51
+ return {
52
+ client,
53
+ serverCapabilities: client.getServerCapabilities(),
54
+ serverName: serverVersion?.name,
55
+ serverVersion: serverVersion?.version,
56
+ stderrLines,
57
+ close: async () => {
58
+ await client.close();
59
+ }
60
+ };
61
+ }
62
+ }
63
+ //# sourceMappingURL=local-process.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-process.js","sourceRoot":"","sources":["../../../src/adapters/local-process.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAIjF,OAAO,EAAE,gCAAgC,EAAE,MAAM,+BAA+B,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAW7C,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IACnC,UAAU,CAAS;IACnB,WAAW,CAAW;IAE/B,YAAY,MAAoB,EAAE,UAAkB,EAAE,WAAqB;QACzE,KAAK,CAAC,gCAAgC,CAAC,MAAM,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC,CAAC;QACzE,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;QAClC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;IACjC,CAAC;CACF;AAED,MAAM,OAAO,mBAAmB;IAC9B,KAAK,CAAC,OAAO,CAAC,MAAgC;QAC5C,MAAM,SAAS,GAAG,IAAI,oBAAoB,CAAC;YACzC,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,GAAG,EAAE,MAAM,CAAC,GAAG;YACf,GAAG,EAAE,MAAM,CAAC,GAAG;YACf,MAAM,EAAE,MAAM;SACf,CAAC,CAAC;QAEH,MAAM,WAAW,GAAa,EAAE,CAAC;QACjC,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,KAAsB,EAAE,EAAE;YACtD,MAAM,IAAI,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YACxE,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;gBACvC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;gBAC5B,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACvB,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBAC5B,CAAC;YACH,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,IAAI,MAAM,CACvB;YACE,IAAI,EAAE,iBAAiB;YACvB,OAAO,EAAE,YAAY;SACtB,EACD;YACE,YAAY,EAAE,EAAE;SACjB,CACF,CAAC;QAEF,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE;gBAC9B,OAAO,EAAE,MAAM,CAAC,SAAS,IAAI,MAAM;aACpC,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,UAAU,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC1E,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;YAC5C,MAAM,IAAI,mBAAmB,CAAC,MAAM,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;QACjE,CAAC;QAED,MAAM,aAAa,GAAG,MAAM,CAAC,gBAAgB,EAAE,CAAC;QAEhD,OAAO;YACL,MAAM;YACN,kBAAkB,EAAE,MAAM,CAAC,qBAAqB,EAAE;YAClD,UAAU,EAAE,aAAa,EAAE,IAAI;YAC/B,aAAa,EAAE,aAAa,EAAE,OAAO;YACrC,WAAW;YACX,KAAK,EAAE,KAAK,IAAI,EAAE;gBAChB,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;YACvB,CAAC;SACF,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,28 @@
1
+ import type { Client } from "@modelcontextprotocol/sdk/client/index.js";
2
+ import type { ServerCapabilities } from "@modelcontextprotocol/sdk/types.js";
3
+ import type { CheckId, CheckResult, CheckStatus, EvidenceSummary, TargetConfig } from "../types.js";
4
+ export interface CheckContext {
5
+ client: Client;
6
+ serverCapabilities?: ServerCapabilities;
7
+ target: TargetConfig;
8
+ timeoutMs: number;
9
+ stderrLines: string[];
10
+ }
11
+ export interface CapabilityObservation {
12
+ capability: "tools" | "prompts" | "resources";
13
+ advertised: boolean;
14
+ responded: boolean;
15
+ minimalShapePresent: boolean;
16
+ endpoint: string;
17
+ itemCount?: number;
18
+ identifiers?: string[];
19
+ diagnostics: string[];
20
+ }
21
+ export interface ObservedCheck {
22
+ result: CheckResult;
23
+ observation?: CapabilityObservation;
24
+ }
25
+ export declare function makeCheckResult(id: CheckId, status: CheckStatus, durationMs: number, message: string, evidence: EvidenceSummary[]): CheckResult;
26
+ export declare function baseEvidence(observation: CapabilityObservation, stderrLines: string[]): EvidenceSummary;
27
+ export declare function isCapabilityAdvertised(capabilities: ServerCapabilities | undefined, capability: keyof Pick<ServerCapabilities, "tools" | "prompts" | "resources">): boolean;
28
+ export declare function summarizeObservation(observation: CapabilityObservation): string;
@@ -0,0 +1,42 @@
1
+ export function makeCheckResult(id, status, durationMs, message, evidence) {
2
+ return {
3
+ id,
4
+ capability: id,
5
+ status,
6
+ durationMs,
7
+ message,
8
+ evidence
9
+ };
10
+ }
11
+ export function baseEvidence(observation, stderrLines) {
12
+ return {
13
+ endpoint: observation.endpoint,
14
+ advertised: observation.advertised,
15
+ responded: observation.responded,
16
+ minimalShapePresent: observation.minimalShapePresent,
17
+ itemCount: observation.itemCount,
18
+ identifiers: observation.identifiers,
19
+ diagnostics: stderrLines.length > 0
20
+ ? [...observation.diagnostics, ...stderrLines.slice(-5)]
21
+ : observation.diagnostics
22
+ };
23
+ }
24
+ export function isCapabilityAdvertised(capabilities, capability) {
25
+ return capabilities?.[capability] !== undefined;
26
+ }
27
+ export function summarizeObservation(observation) {
28
+ if (!observation.advertised) {
29
+ return "Capability is not advertised by the target.";
30
+ }
31
+ if (!observation.responded) {
32
+ return "Advertised capability did not respond successfully.";
33
+ }
34
+ if (!observation.minimalShapePresent) {
35
+ return "Endpoint responded, but the minimal expected shape was incomplete.";
36
+ }
37
+ const countSuffix = observation.itemCount !== undefined
38
+ ? ` (${observation.itemCount} item${observation.itemCount === 1 ? "" : "s"})`
39
+ : "";
40
+ return `Advertised capability responded with the minimal expected shape${countSuffix}.`;
41
+ }
42
+ //# sourceMappingURL=base.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.js","sourceRoot":"","sources":["../../../src/checks/base.ts"],"names":[],"mappings":"AA6BA,MAAM,UAAU,eAAe,CAC7B,EAAW,EACX,MAAmB,EACnB,UAAkB,EAClB,OAAe,EACf,QAA2B;IAE3B,OAAO;QACL,EAAE;QACF,UAAU,EAAE,EAAE;QACd,MAAM;QACN,UAAU;QACV,OAAO;QACP,QAAQ;KACT,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,YAAY,CAC1B,WAAkC,EAClC,WAAqB;IAErB,OAAO;QACL,QAAQ,EAAE,WAAW,CAAC,QAAQ;QAC9B,UAAU,EAAE,WAAW,CAAC,UAAU;QAClC,SAAS,EAAE,WAAW,CAAC,SAAS;QAChC,mBAAmB,EAAE,WAAW,CAAC,mBAAmB;QACpD,SAAS,EAAE,WAAW,CAAC,SAAS;QAChC,WAAW,EAAE,WAAW,CAAC,WAAW;QACpC,WAAW,EACT,WAAW,CAAC,MAAM,GAAG,CAAC;YACpB,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,WAAW,EAAE,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YACxD,CAAC,CAAC,WAAW,CAAC,WAAW;KAC9B,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,YAA4C,EAC5C,UAA6E;IAE7E,OAAO,YAAY,EAAE,CAAC,UAAU,CAAC,KAAK,SAAS,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,WAAkC;IACrE,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,CAAC;QAC5B,OAAO,6CAA6C,CAAC;IACvD,CAAC;IACD,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,CAAC;QAC3B,OAAO,qDAAqD,CAAC;IAC/D,CAAC;IACD,IAAI,CAAC,WAAW,CAAC,mBAAmB,EAAE,CAAC;QACrC,OAAO,oEAAoE,CAAC;IAC9E,CAAC;IACD,MAAM,WAAW,GACf,WAAW,CAAC,SAAS,KAAK,SAAS;QACjC,CAAC,CAAC,KAAK,WAAW,CAAC,SAAS,QAAQ,WAAW,CAAC,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG;QAC7E,CAAC,CAAC,EAAE,CAAC;IACT,OAAO,kEAAkE,WAAW,GAAG,CAAC;AAC1F,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { type CheckContext, type ObservedCheck } from "./base.js";
2
+ export interface ListCheckConfig<TItem> {
3
+ /** Capability name: "tools" or "prompts" */
4
+ capability: "tools" | "prompts";
5
+ /** The endpoint name used in evidence, e.g. "tools/list" */
6
+ endpoint: string;
7
+ /** Calls the appropriate list method on the MCP client */
8
+ listItems: (context: CheckContext) => Promise<TItem[]>;
9
+ /** Validates that a single item has the minimal expected shape */
10
+ hasMinimalShape: (item: TItem) => boolean;
11
+ /** Extracts the display name/identifier from an item */
12
+ getItemName: (item: TItem) => string;
13
+ /** Optionally extracts the schema/definition object for drift detection */
14
+ getItemSchema?: (item: TItem) => object | undefined;
15
+ }
16
+ export declare function runListCheck<TItem>(config: ListCheckConfig<TItem>, context: CheckContext): Promise<ObservedCheck>;
@@ -0,0 +1,78 @@
1
+ import { performance } from "node:perf_hooks";
2
+ import { baseEvidence, isCapabilityAdvertised, makeCheckResult, summarizeObservation } from "./base.js";
3
+ export async function runListCheck(config, context) {
4
+ const startedAt = performance.now();
5
+ const advertised = isCapabilityAdvertised(context.serverCapabilities, config.capability);
6
+ if (!advertised) {
7
+ return {
8
+ observation: {
9
+ capability: config.capability,
10
+ advertised: false,
11
+ responded: false,
12
+ minimalShapePresent: false,
13
+ endpoint: config.endpoint,
14
+ diagnostics: []
15
+ },
16
+ result: makeCheckResult(config.capability, "unsupported", performance.now() - startedAt, `${capitalize(config.capability)} are not advertised by the target.`, [
17
+ {
18
+ endpoint: config.endpoint,
19
+ advertised: false,
20
+ responded: false,
21
+ minimalShapePresent: false,
22
+ diagnostics: []
23
+ }
24
+ ])
25
+ };
26
+ }
27
+ try {
28
+ const items = await config.listItems(context);
29
+ const identifiers = items.map(config.getItemName);
30
+ const minimalShapePresent = items.every(config.hasMinimalShape);
31
+ const observation = {
32
+ capability: config.capability,
33
+ advertised: true,
34
+ responded: true,
35
+ minimalShapePresent,
36
+ endpoint: config.endpoint,
37
+ itemCount: items.length,
38
+ identifiers,
39
+ diagnostics: []
40
+ };
41
+ const evidence = baseEvidence(observation, context.stderrLines);
42
+ if (config.getItemSchema) {
43
+ const schemas = {};
44
+ for (const item of items) {
45
+ const schema = config.getItemSchema(item);
46
+ if (schema !== undefined) {
47
+ schemas[config.getItemName(item)] = schema;
48
+ }
49
+ }
50
+ if (Object.keys(schemas).length > 0) {
51
+ evidence.schemas = schemas;
52
+ }
53
+ }
54
+ return {
55
+ observation,
56
+ result: makeCheckResult(config.capability, minimalShapePresent ? "pass" : "partial", performance.now() - startedAt, summarizeObservation(observation), [evidence])
57
+ };
58
+ }
59
+ catch (error) {
60
+ const message = error instanceof Error ? error.message : String(error);
61
+ const observation = {
62
+ capability: config.capability,
63
+ advertised: true,
64
+ responded: false,
65
+ minimalShapePresent: false,
66
+ endpoint: config.endpoint,
67
+ diagnostics: [message]
68
+ };
69
+ return {
70
+ observation,
71
+ result: makeCheckResult(config.capability, "fail", performance.now() - startedAt, `Advertised capability failed during ${config.endpoint}: ${message}`, [baseEvidence(observation, context.stderrLines)])
72
+ };
73
+ }
74
+ }
75
+ function capitalize(s) {
76
+ return s.charAt(0).toUpperCase() + s.slice(1);
77
+ }
78
+ //# sourceMappingURL=list-check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-check.js","sourceRoot":"","sources":["../../../src/checks/list-check.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE9C,OAAO,EACL,YAAY,EACZ,sBAAsB,EACtB,eAAe,EACf,oBAAoB,EAIrB,MAAM,WAAW,CAAC;AAiBnB,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,MAA8B,EAC9B,OAAqB;IAErB,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;IACpC,MAAM,UAAU,GAAG,sBAAsB,CAAC,OAAO,CAAC,kBAAkB,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;IAEzF,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO;YACL,WAAW,EAAE;gBACX,UAAU,EAAE,MAAM,CAAC,UAAU;gBAC7B,UAAU,EAAE,KAAK;gBACjB,SAAS,EAAE,KAAK;gBAChB,mBAAmB,EAAE,KAAK;gBAC1B,QAAQ,EAAE,MAAM,CAAC,QAAQ;gBACzB,WAAW,EAAE,EAAE;aAChB;YACD,MAAM,EAAE,eAAe,CACrB,MAAM,CAAC,UAAU,EACjB,aAAa,EACb,WAAW,CAAC,GAAG,EAAE,GAAG,SAAS,EAC7B,GAAG,UAAU,CAAC,MAAM,CAAC,UAAU,CAAC,oCAAoC,EACpE;gBACE;oBACE,QAAQ,EAAE,MAAM,CAAC,QAAQ;oBACzB,UAAU,EAAE,KAAK;oBACjB,SAAS,EAAE,KAAK;oBAChB,mBAAmB,EAAE,KAAK;oBAC1B,WAAW,EAAE,EAAE;iBAChB;aACF,CACF;SACF,CAAC;IACJ,CAAC;IAED,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAC9C,MAAM,WAAW,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAClD,MAAM,mBAAmB,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;QAChE,MAAM,WAAW,GAA0B;YACzC,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,UAAU,EAAE,IAAI;YAChB,SAAS,EAAE,IAAI;YACf,mBAAmB;YACnB,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,SAAS,EAAE,KAAK,CAAC,MAAM;YACvB,WAAW;YACX,WAAW,EAAE,EAAE;SAChB,CAAC;QAEF,MAAM,QAAQ,GAAG,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;QAChE,IAAI,MAAM,CAAC,aAAa,EAAE,CAAC;YACzB,MAAM,OAAO,GAA2B,EAAE,CAAC;YAC3C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,MAAM,MAAM,GAAG,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;gBAC1C,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;oBACzB,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC;gBAC7C,CAAC;YACH,CAAC;YACD,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACpC,QAAQ,CAAC,OAAO,GAAG,OAAO,CAAC;YAC7B,CAAC;QACH,CAAC;QAED,OAAO;YACL,WAAW;YACX,MAAM,EAAE,eAAe,CACrB,MAAM,CAAC,UAAU,EACjB,mBAAmB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,EACxC,WAAW,CAAC,GAAG,EAAE,GAAG,SAAS,EAC7B,oBAAoB,CAAC,WAAW,CAAC,EACjC,CAAC,QAAQ,CAAC,CACX;SACF,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,MAAM,WAAW,GAA0B;YACzC,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,UAAU,EAAE,IAAI;YAChB,SAAS,EAAE,KAAK;YAChB,mBAAmB,EAAE,KAAK;YAC1B,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,WAAW,EAAE,CAAC,OAAO,CAAC;SACvB,CAAC;QACF,OAAO;YACL,WAAW;YACX,MAAM,EAAE,eAAe,CACrB,MAAM,CAAC,UAAU,EACjB,MAAM,EACN,WAAW,CAAC,GAAG,EAAE,GAAG,SAAS,EAC7B,uCAAuC,MAAM,CAAC,QAAQ,KAAK,OAAO,EAAE,EACpE,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC,CACjD;SACF,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CAAC,CAAS;IAC3B,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAChD,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { CheckContext, ObservedCheck } from "./base.js";
2
+ export declare function runPromptsCheck(context: CheckContext): Promise<ObservedCheck>;
@@ -0,0 +1,11 @@
1
+ import { runListCheck } from "./list-check.js";
2
+ export async function runPromptsCheck(context) {
3
+ return runListCheck({
4
+ capability: "prompts",
5
+ endpoint: "prompts/list",
6
+ listItems: async (ctx) => (await ctx.client.listPrompts(undefined, { timeout: ctx.timeoutMs })).prompts,
7
+ hasMinimalShape: (prompt) => typeof prompt.name === "string" && prompt.name.trim().length > 0,
8
+ getItemName: (prompt) => prompt.name,
9
+ }, context);
10
+ }
11
+ //# sourceMappingURL=prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../../src/checks/prompts.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,OAAqB;IACzD,OAAO,YAAY,CAAS;QAC1B,UAAU,EAAE,SAAS;QACrB,QAAQ,EAAE,cAAc;QACxB,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,SAAS,EAAE,EAAE,OAAO,EAAE,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,OAAO;QACvG,eAAe,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC;QAC7F,WAAW,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI;KACrC,EAAE,OAAO,CAAC,CAAC;AACd,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { type CheckContext, type ObservedCheck } from "./base.js";
2
+ export declare function runResourcesCheck(context: CheckContext): Promise<ObservedCheck>;