@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.
- package/LICENSE +21 -0
- package/README.md +228 -0
- package/dist/src/adapters/http.d.ts +5 -0
- package/dist/src/adapters/http.js +54 -0
- package/dist/src/adapters/http.js.map +1 -0
- package/dist/src/adapters/local-process.d.ts +19 -0
- package/dist/src/adapters/local-process.js +63 -0
- package/dist/src/adapters/local-process.js.map +1 -0
- package/dist/src/checks/base.d.ts +28 -0
- package/dist/src/checks/base.js +42 -0
- package/dist/src/checks/base.js.map +1 -0
- package/dist/src/checks/list-check.d.ts +16 -0
- package/dist/src/checks/list-check.js +78 -0
- package/dist/src/checks/list-check.js.map +1 -0
- package/dist/src/checks/prompts.d.ts +2 -0
- package/dist/src/checks/prompts.js +11 -0
- package/dist/src/checks/prompts.js.map +1 -0
- package/dist/src/checks/resources.d.ts +2 -0
- package/dist/src/checks/resources.js +163 -0
- package/dist/src/checks/resources.js.map +1 -0
- package/dist/src/checks/tools-invoke.d.ts +2 -0
- package/dist/src/checks/tools-invoke.js +107 -0
- package/dist/src/checks/tools-invoke.js.map +1 -0
- package/dist/src/checks/tools.d.ts +2 -0
- package/dist/src/checks/tools.js +12 -0
- package/dist/src/checks/tools.js.map +1 -0
- package/dist/src/cli.d.ts +2 -0
- package/dist/src/cli.js +266 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/diff.d.ts +2 -0
- package/dist/src/diff.js +98 -0
- package/dist/src/diff.js.map +1 -0
- package/dist/src/discovery.d.ts +7 -0
- package/dist/src/discovery.js +116 -0
- package/dist/src/discovery.js.map +1 -0
- package/dist/src/index.d.ts +9 -0
- package/dist/src/index.js +10 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/reporters/common.d.ts +7 -0
- package/dist/src/reporters/common.js +63 -0
- package/dist/src/reporters/common.js.map +1 -0
- package/dist/src/reporters/html.d.ts +2 -0
- package/dist/src/reporters/html.js +228 -0
- package/dist/src/reporters/html.js.map +1 -0
- package/dist/src/reporters/markdown.d.ts +2 -0
- package/dist/src/reporters/markdown.js +231 -0
- package/dist/src/reporters/markdown.js.map +1 -0
- package/dist/src/reporters/terminal.d.ts +2 -0
- package/dist/src/reporters/terminal.js +110 -0
- package/dist/src/reporters/terminal.js.map +1 -0
- package/dist/src/runner.d.ts +5 -0
- package/dist/src/runner.js +138 -0
- package/dist/src/runner.js.map +1 -0
- package/dist/src/schema-diff.d.ts +6 -0
- package/dist/src/schema-diff.js +73 -0
- package/dist/src/schema-diff.js.map +1 -0
- package/dist/src/storage.d.ts +6 -0
- package/dist/src/storage.js +32 -0
- package/dist/src/storage.js.map +1 -0
- package/dist/src/types.d.ts +120 -0
- package/dist/src/types.js +5 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/utils/failure-diagnosis.d.ts +2 -0
- package/dist/src/utils/failure-diagnosis.js +90 -0
- package/dist/src/utils/failure-diagnosis.js.map +1 -0
- package/dist/src/utils/ids.d.ts +2 -0
- package/dist/src/utils/ids.js +13 -0
- package/dist/src/utils/ids.js.map +1 -0
- package/dist/src/utils/schema-stub.d.ts +14 -0
- package/dist/src/utils/schema-stub.js +61 -0
- package/dist/src/utils/schema-stub.js.map +1 -0
- package/dist/src/validate.d.ts +4 -0
- package/dist/src/validate.js +97 -0
- package/dist/src/validate.js.map +1 -0
- package/dist/src/version.d.ts +1 -0
- package/dist/src/version.js +21 -0
- package/dist/src/version.js.map +1 -0
- package/package.json +76 -0
- package/schemas/diff-artifact.schema.json +132 -0
- 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
|
+
[](https://github.com/KryptosAI/mcp-observatory/actions/workflows/ci.yml)
|
|
4
|
+
[](https://github.com/KryptosAI/mcp-observatory/actions/workflows/real-server-matrix.yml)
|
|
5
|
+
[](https://github.com/KryptosAI/mcp-observatory/releases)
|
|
6
|
+
[](./LICENSE)
|
|
7
|
+
[](./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,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":"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"}
|
|
@@ -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"}
|