@k08200/mcp-probe 1.6.0 → 1.10.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/README.md +120 -507
- package/dist/assertions.d.ts.map +1 -1
- package/dist/assertions.js +93 -0
- package/dist/assertions.js.map +1 -1
- package/dist/checker.d.ts.map +1 -1
- package/dist/checker.js +54 -56
- package/dist/checker.js.map +1 -1
- package/dist/cli.js +52 -10
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +30 -1
- package/dist/config.js.map +1 -1
- package/dist/doctor.d.ts +5 -0
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +258 -31
- package/dist/doctor.js.map +1 -1
- package/dist/exit-code.d.ts +3 -0
- package/dist/exit-code.d.ts.map +1 -0
- package/dist/exit-code.js +8 -0
- package/dist/exit-code.js.map +1 -0
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +1 -118
- package/dist/init.js.map +1 -1
- package/dist/issues.d.ts.map +1 -1
- package/dist/issues.js +33 -14
- package/dist/issues.js.map +1 -1
- package/dist/protocols/mcp-client.d.ts.map +1 -1
- package/dist/protocols/mcp-client.js +36 -17
- package/dist/protocols/mcp-client.js.map +1 -1
- package/dist/reporters/receipt.d.ts +16 -0
- package/dist/reporters/receipt.d.ts.map +1 -0
- package/dist/reporters/receipt.js +21 -0
- package/dist/reporters/receipt.js.map +1 -0
- package/dist/scaffold.d.ts +17 -0
- package/dist/scaffold.d.ts.map +1 -0
- package/dist/scaffold.js +152 -0
- package/dist/scaffold.js.map +1 -0
- package/dist/sidecar.d.ts +6 -0
- package/dist/sidecar.d.ts.map +1 -0
- package/dist/sidecar.js +79 -0
- package/dist/sidecar.js.map +1 -0
- package/dist/types.d.ts +8 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +5 -0
- package/dist/version.js.map +1 -0
- package/examples/fixtures/stdio-mcp-server.js +68 -0
- package/examples/github-actions/fleet.yml +9 -1
- package/examples/github-actions/remote-server.yml +9 -1
- package/examples/github-actions/single-server.yml +9 -1
- package/examples/self-check.config.json +3 -1
- package/examples/self-check.strict.config.json +16 -0
- package/examples/self-check.strict.tools.json +49 -0
- package/package.json +1 -1
- package/schemas/mcp-probe.config.schema.json +15 -0
- package/schemas/mcp-probe.sidecar.schema.json +5 -1
package/README.md
CHANGED
|
@@ -3,275 +3,96 @@
|
|
|
3
3
|
[](https://github.com/k08200/mcp-probe/actions/workflows/ci.yml)
|
|
4
4
|
[](https://www.npmjs.com/package/@k08200/mcp-probe)
|
|
5
5
|
[](LICENSE)
|
|
6
|
-
[](package.json)
|
|
7
6
|
|
|
8
|
-
**CI readiness gate for MCP servers.**
|
|
7
|
+
**CI readiness gate for MCP servers.**
|
|
9
8
|
|
|
10
|
-
|
|
9
|
+
`tools/list` is not enough. An MCP server can start, advertise a clean schema, and still fail every real tool call because auth, scopes, downstream permissions, or environment setup are broken.
|
|
11
10
|
|
|
12
|
-
|
|
11
|
+
`mcp-probe` checks the path an agent actually depends on:
|
|
13
12
|
|
|
14
|
-
|
|
13
|
+
- MCP `initialize` handshake
|
|
14
|
+
- `tools/list` discovery
|
|
15
|
+
- optional real `tools/call` dry-runs
|
|
16
|
+
- sidecar sample inputs for meaningful calls
|
|
17
|
+
- contract assertions for result shape, row limits, stable error codes, and leak checks
|
|
18
|
+
- GitHub Actions summaries and machine-readable JSON output
|
|
19
|
+
- optional JSON receipt artifacts for independent CI evidence
|
|
15
20
|
|
|
16
|
-
|
|
21
|
+
## Looking For Real-World Recipes
|
|
17
22
|
|
|
18
|
-
|
|
19
|
-
npx @k08200/mcp-probe@latest init \
|
|
20
|
-
--target @your-org/your-mcp-server \
|
|
21
|
-
--discover \
|
|
22
|
-
--github-actions
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
Add this workflow to any project that depends on MCP servers:
|
|
26
|
-
|
|
27
|
-
```yaml
|
|
28
|
-
name: MCP Probe
|
|
29
|
-
|
|
30
|
-
on:
|
|
31
|
-
pull_request:
|
|
32
|
-
push:
|
|
33
|
-
branches: [main]
|
|
23
|
+
The core tool is useful only if it reflects real MCP failure modes. If you run MCP servers in agent workflows, recipe contributions are especially useful for:
|
|
34
24
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
25
|
+
| Server | What to validate | Issue |
|
|
26
|
+
|---|---|---|
|
|
27
|
+
| Datadog | OAuth/scopes, logs/metrics read paths, auth handoff failures | [#1](https://github.com/k08200/mcp-probe/issues/1) |
|
|
28
|
+
| Supabase | read-only roles, row limits, tenant/project scope, denied writes | [#2](https://github.com/k08200/mcp-probe/issues/2) |
|
|
29
|
+
| Gmail | OAuth browser handoff, stable auth errors, no private email leaks | [#3](https://github.com/k08200/mcp-probe/issues/3) |
|
|
39
30
|
|
|
40
|
-
|
|
41
|
-
- uses: actions/checkout@v6
|
|
31
|
+
Do not paste secrets. Recipes should use placeholders such as `${DATADOG_MCP_TOKEN}` and read-only sample calls.
|
|
42
32
|
|
|
43
|
-
|
|
44
|
-
run: |
|
|
45
|
-
npx @k08200/mcp-probe @your-org/your-mcp-server \
|
|
46
|
-
--probe-tools \
|
|
47
|
-
--github-summary
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
For teams running several MCP servers, use a config file:
|
|
33
|
+
## Quick Start
|
|
51
34
|
|
|
52
35
|
```bash
|
|
53
|
-
npx @k08200/mcp-probe
|
|
36
|
+
npx @k08200/mcp-probe@latest @modelcontextprotocol/server-memory
|
|
54
37
|
```
|
|
55
38
|
|
|
56
|
-
For
|
|
57
|
-
|
|
58
|
-
```json
|
|
59
|
-
{
|
|
60
|
-
"tools": {
|
|
61
|
-
"logs_query": {
|
|
62
|
-
"input": {
|
|
63
|
-
"query": "service:web status:error",
|
|
64
|
-
"timeframe": "1h"
|
|
65
|
-
},
|
|
66
|
-
"expect": {
|
|
67
|
-
"status": "pass",
|
|
68
|
-
"not_error_code": [401, 403],
|
|
69
|
-
"requiredFields": ["source", "freshness"],
|
|
70
|
-
"maxRows": 100
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
```
|
|
39
|
+
For CI, scaffold a config, sidecar, and workflow:
|
|
76
40
|
|
|
77
41
|
```bash
|
|
78
|
-
npx @k08200/mcp-probe
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
mcp-probe @modelcontextprotocol/server-memory
|
|
83
|
-
────────────────────────────────────────────────────
|
|
84
|
-
✓ Target resolution
|
|
85
|
-
npx --yes @modelcontextprotocol/server-memory
|
|
86
|
-
✓ MCP protocol handshake 1392ms
|
|
87
|
-
memory-server v0.6.3
|
|
88
|
-
✓ Tools discovery 33ms
|
|
89
|
-
Found 9 tools
|
|
90
|
-
✓ Tool schema validation
|
|
91
|
-
All tool schemas are valid
|
|
92
|
-
────────────────────────────────────────────────────
|
|
93
|
-
Server memory-server v0.6.3
|
|
94
|
-
Caps tools
|
|
95
|
-
|
|
96
|
-
Tools
|
|
97
|
-
▸ create_entities Create multiple new entities in the knowledge graph
|
|
98
|
-
▸ create_relations Create multiple new relations between entities
|
|
99
|
-
▸ add_observations Add new observations to existing entities
|
|
100
|
-
▸ delete_entities Delete entities and their associated relations
|
|
101
|
-
▸ read_graph Read the entire knowledge graph
|
|
102
|
-
▸ search_nodes Search for nodes in the knowledge graph
|
|
103
|
-
▸ ...and 3 more
|
|
104
|
-
|
|
105
|
-
✓ PASS 1455ms total
|
|
42
|
+
npx @k08200/mcp-probe@latest init \
|
|
43
|
+
--target @your-org/your-mcp-server \
|
|
44
|
+
--discover \
|
|
45
|
+
--github-actions
|
|
106
46
|
```
|
|
107
47
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
## Install
|
|
111
|
-
|
|
112
|
-
Requires Node.js 20.19 or newer.
|
|
48
|
+
Then run:
|
|
113
49
|
|
|
114
50
|
```bash
|
|
115
|
-
|
|
116
|
-
npx @k08200/mcp-probe <target>
|
|
117
|
-
|
|
118
|
-
# Or install globally
|
|
119
|
-
npm install -g @k08200/mcp-probe
|
|
51
|
+
npx @k08200/mcp-probe@latest --config mcp-probe.config.json --github-summary --fail-on-warn
|
|
120
52
|
```
|
|
121
53
|
|
|
122
|
-
##
|
|
54
|
+
## Commands
|
|
123
55
|
|
|
124
56
|
```bash
|
|
125
|
-
# Check
|
|
57
|
+
# Check one server
|
|
126
58
|
mcp-probe @modelcontextprotocol/server-memory
|
|
127
59
|
|
|
128
|
-
#
|
|
129
|
-
mcp-probe
|
|
130
|
-
|
|
131
|
-
# Discover tool names first and scaffold sidecar entries automatically
|
|
132
|
-
mcp-probe init --target @modelcontextprotocol/server-memory --discover --github-actions
|
|
133
|
-
|
|
134
|
-
# Check whether this project is ready to run mcp-probe in CI
|
|
135
|
-
mcp-probe doctor
|
|
136
|
-
|
|
137
|
-
# JSON output for scripting or internal CI preflight checks
|
|
138
|
-
mcp-probe doctor --config-file mcp-probe.config.json --output json
|
|
139
|
-
|
|
140
|
-
# Scaffold a remote server config with auth from an env var
|
|
141
|
-
mcp-probe init \
|
|
142
|
-
--target https://mcp.example.com/mcp \
|
|
143
|
-
--transport http \
|
|
144
|
-
--header-env MCP_TOKEN \
|
|
145
|
-
--github-actions
|
|
146
|
-
|
|
147
|
-
# Choose custom scaffold paths
|
|
148
|
-
mcp-probe init \
|
|
149
|
-
--target @your-org/your-mcp-server \
|
|
150
|
-
--config-file ci/mcp-probe.config.json \
|
|
151
|
-
--sidecar-file ci/mcp-tools.json
|
|
152
|
-
|
|
153
|
-
# Check a server that requires arguments (e.g. directories to serve)
|
|
154
|
-
mcp-probe @modelcontextprotocol/server-filesystem /tmp /Users/me/projects
|
|
60
|
+
# Check a local server
|
|
61
|
+
mcp-probe ./server.js
|
|
155
62
|
|
|
156
|
-
# Check a
|
|
157
|
-
mcp-probe ./my-server.js
|
|
158
|
-
|
|
159
|
-
# Check a remote Streamable HTTP MCP server
|
|
160
|
-
mcp-probe https://mcp.example.com/mcp
|
|
161
|
-
|
|
162
|
-
# Check a legacy HTTP+SSE MCP server
|
|
163
|
-
mcp-probe https://mcp.example.com/sse --transport sse
|
|
164
|
-
|
|
165
|
-
# Pass headers to remote servers
|
|
63
|
+
# Check a remote Streamable HTTP server
|
|
166
64
|
mcp-probe https://mcp.example.com/mcp --header "Authorization: Bearer $TOKEN"
|
|
167
65
|
|
|
168
|
-
#
|
|
169
|
-
mcp-probe @scope/server --stderr-allow "^Warning:" --stderr-fatal "panic|FATAL"
|
|
170
|
-
|
|
171
|
-
# JSON output for CI / scripting
|
|
172
|
-
mcp-probe @scope/server --output json
|
|
173
|
-
|
|
174
|
-
# Custom timeout (default: 10000ms)
|
|
175
|
-
mcp-probe @scope/server --timeout 30000
|
|
176
|
-
|
|
177
|
-
# Batch-check several servers from a config file
|
|
66
|
+
# Batch-check from config
|
|
178
67
|
mcp-probe --config mcp-probe.config.json
|
|
179
68
|
|
|
180
|
-
#
|
|
181
|
-
mcp-probe --config mcp-probe.config.json --
|
|
69
|
+
# Persist an independent readiness receipt artifact
|
|
70
|
+
mcp-probe --config mcp-probe.config.json --receipt-file mcp-probe.receipt.json
|
|
182
71
|
|
|
183
|
-
#
|
|
184
|
-
mcp-probe --config mcp-probe.config.json --badge-file mcp-probe-badge.json
|
|
185
|
-
|
|
186
|
-
# Call tools with generated minimal inputs
|
|
72
|
+
# Call tools, not just tools/list
|
|
187
73
|
mcp-probe @scope/server --probe-tools
|
|
188
74
|
|
|
189
|
-
#
|
|
75
|
+
# Use meaningful sidecar inputs
|
|
190
76
|
mcp-probe @scope/server --tools-file .mcp-probe.json
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
## What it checks
|
|
194
|
-
|
|
195
|
-
| Check | Description |
|
|
196
|
-
|-------|-------------|
|
|
197
|
-
| **Target resolution** | Can the package be located and spawned? |
|
|
198
|
-
| **MCP protocol handshake** | Does the server respond to `initialize`? Measures connect latency. |
|
|
199
|
-
| **Tools discovery** | Does `tools/list` return results? Measures list latency. |
|
|
200
|
-
| **Tool schema validation** | Are all tool schemas well-formed? |
|
|
201
|
-
| **Resources discovery** | Runs `resources/list` when the server advertises resources. |
|
|
202
|
-
| **Prompts discovery** | Runs `prompts/list` when the server advertises prompts. |
|
|
203
|
-
| **Tool call dry-run** | Optional `tools/call` checks via `--probe-tools` or `--tools-file`. |
|
|
204
|
-
|
|
205
|
-
## Issue codes and remediation hints
|
|
206
|
-
|
|
207
|
-
When a check warns or fails, mcp-probe attaches stable issue metadata:
|
|
208
|
-
|
|
209
|
-
```json
|
|
210
|
-
{
|
|
211
|
-
"name": "Tool call dry-run",
|
|
212
|
-
"status": "warn",
|
|
213
|
-
"message": "1 auth/permission errors (1 sidecar, 0 auto)",
|
|
214
|
-
"issue": {
|
|
215
|
-
"code": "TOOL_CALL_AUTH",
|
|
216
|
-
"hint": "At least one tool call hit auth or permission handling. This often means CI needs tokens or the server needs non-browser auth."
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
```
|
|
220
|
-
|
|
221
|
-
These hints appear in terminal output, JSON output, GitHub Actions summaries, and workflow annotations so PR failures point at the likely fix instead of only showing raw MCP errors.
|
|
222
77
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
| Code | Meaning |
|
|
226
|
-
|------|---------|
|
|
227
|
-
| `TARGET_NOT_FOUND` | The npm package, local file, or executable could not be started. |
|
|
228
|
-
| `HANDSHAKE_TIMEOUT` | The server did not complete MCP `initialize` before the timeout. |
|
|
229
|
-
| `HANDSHAKE_AUTH` | Initialization failed with an auth-like error. |
|
|
230
|
-
| `NO_TOOLS` | The server responded but did not expose tools. |
|
|
231
|
-
| `TOOL_SCHEMA_INVALID` | A discovered tool has an invalid schema. |
|
|
232
|
-
| `TOOL_CALL_AUTH` | A real tool call reached auth or permission handling. |
|
|
233
|
-
| `CONTRACT_ASSERTION_FAILED` | A tool call completed but failed one or more sidecar assertions. |
|
|
234
|
-
| `AUTO_DRY_RUN_INPUT` | Auto-generated schema-minimum input failed; add sidecar inputs. |
|
|
235
|
-
| `TOOL_CALL_FAILED` | A sidecar tool call returned a non-auth error. |
|
|
236
|
-
|
|
237
|
-
## Batch CI gate
|
|
78
|
+
# Preflight local mcp-probe setup
|
|
79
|
+
mcp-probe doctor
|
|
238
80
|
|
|
239
|
-
|
|
81
|
+
# Make warnings fail CI too
|
|
82
|
+
mcp-probe --config mcp-probe.config.json --fail-on-warn
|
|
240
83
|
|
|
241
|
-
|
|
242
|
-
mcp-probe
|
|
84
|
+
# Create missing config/sidecar/workflow files
|
|
85
|
+
mcp-probe doctor --fix --target @scope/server
|
|
243
86
|
```
|
|
244
87
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
| File | Purpose |
|
|
248
|
-
|------|---------|
|
|
249
|
-
| `mcp-probe.config.json` | Batch config with one server and `probeTools: true`. |
|
|
250
|
-
| `.mcp-probe.json` | Sidecar template for real tool-call sample inputs. |
|
|
251
|
-
| `.github/workflows/mcp-probe.yml` | GitHub Actions readiness gate. |
|
|
252
|
-
|
|
253
|
-
Existing files are skipped unless you pass `--force`.
|
|
88
|
+
## Config
|
|
254
89
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
| Schema | File |
|
|
258
|
-
|--------|------|
|
|
259
|
-
| [`mcp-probe.config.schema.json`](schemas/mcp-probe.config.schema.json) | `mcp-probe.config.json` |
|
|
260
|
-
| [`mcp-probe.sidecar.schema.json`](schemas/mcp-probe.sidecar.schema.json) | `.mcp-probe.json` |
|
|
261
|
-
|
|
262
|
-
When `--discover` is enabled, mcp-probe connects to the target server, runs discovery, and pre-populates `.mcp-probe.json` with the discovered tool names and schema-minimum sample inputs. Review those values before using them as a production CI gate.
|
|
263
|
-
|
|
264
|
-
Use `--config` when a project depends on several MCP servers and you want one CI command to validate all of them:
|
|
90
|
+
Use `mcp-probe.config.json` when a repository depends on one or more MCP servers:
|
|
265
91
|
|
|
266
92
|
```json
|
|
267
93
|
{
|
|
268
94
|
"timeoutMs": 10000,
|
|
269
95
|
"servers": [
|
|
270
|
-
{
|
|
271
|
-
"name": "memory",
|
|
272
|
-
"target": "@modelcontextprotocol/server-memory",
|
|
273
|
-
"probeTools": true
|
|
274
|
-
},
|
|
275
96
|
{
|
|
276
97
|
"name": "datadog",
|
|
277
98
|
"target": "https://mcp.example.com/mcp",
|
|
@@ -279,95 +100,30 @@ Use `--config` when a project depends on several MCP servers and you want one CI
|
|
|
279
100
|
"headers": {
|
|
280
101
|
"Authorization": "Bearer ${DATADOG_MCP_TOKEN}"
|
|
281
102
|
},
|
|
282
|
-
"
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
},
|
|
286
|
-
"toolsFile": "./recipes/datadog.tools.json"
|
|
103
|
+
"expectedTools": ["logs_query"],
|
|
104
|
+
"forbiddenTools": ["delete_dashboard", "rotate_api_key"],
|
|
105
|
+
"toolsFile": "./datadog.tools.json"
|
|
287
106
|
}
|
|
288
107
|
]
|
|
289
108
|
}
|
|
290
109
|
```
|
|
291
110
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
```bash
|
|
295
|
-
mcp-probe --config mcp-probe.config.json
|
|
296
|
-
```
|
|
297
|
-
|
|
298
|
-
The process exits with `1` if any configured server fails. Warnings such as auth handoff failures still exit `0`, so CI can flag degraded MCP readiness without blocking deploys unless a server is truly broken.
|
|
299
|
-
|
|
300
|
-
Config fields:
|
|
301
|
-
|
|
302
|
-
| Field | Description |
|
|
303
|
-
|-------|-------------|
|
|
304
|
-
| `timeoutMs` | Optional global timeout in milliseconds. CLI `--timeout` is used when omitted. |
|
|
305
|
-
| `servers[].name` | Human-readable name shown in batch output. |
|
|
306
|
-
| `servers[].target` | npm package, local server path, or remote MCP URL. |
|
|
307
|
-
| `servers[].serverArgs` | Optional arguments passed to the MCP server. |
|
|
308
|
-
| `servers[].transport` | Optional transport override: `stdio`, `http`, or `sse`. URL targets default to `http`; package/path targets default to `stdio`. |
|
|
309
|
-
| `servers[].headers` | Optional HTTP headers for remote MCP servers. `${ENV_VAR}` placeholders are expanded at runtime. |
|
|
310
|
-
| `servers[].stderr.allow` | Optional regex patterns for stderr lines that should be ignored when startup fails. |
|
|
311
|
-
| `servers[].stderr.fatal` | Optional regex patterns for stderr lines that should always be treated as the startup failure reason. |
|
|
312
|
-
| `servers[].probeTools` | Enables dry-run tool calls for that server. |
|
|
313
|
-
| `servers[].toolsFile` | Sidecar input file for meaningful `tools/call` samples. Relative paths resolve from the config file directory. |
|
|
314
|
-
|
|
315
|
-
## Project doctor
|
|
316
|
-
|
|
317
|
-
Use `mcp-probe doctor` before wiring mcp-probe into CI or after changing config files:
|
|
318
|
-
|
|
319
|
-
```bash
|
|
320
|
-
mcp-probe doctor
|
|
321
|
-
```
|
|
111
|
+
Relative local `target` and `toolsFile` paths are resolved from the config file directory.
|
|
322
112
|
|
|
323
|
-
|
|
113
|
+
Use `expectedTools` for tools that must be advertised, `allowedTools` for an exact allow-list, and `forbiddenTools` for dangerous tools that must not appear in low-trust configs.
|
|
114
|
+
When `expectedTools` and a `toolsFile` are both set, every expected tool must also have a sidecar sample input so CI proves the tool is actually dry-run.
|
|
324
115
|
|
|
325
|
-
|
|
326
|
-
|-------|-------------|
|
|
327
|
-
| **Node.js version** | Confirms the current runtime satisfies mcp-probe's required Node.js version. |
|
|
328
|
-
| **Config file** | Validates that `mcp-probe.config.json` exists and can be parsed. |
|
|
329
|
-
| **Sidecar files** | Validates each configured `toolsFile`, resolving relative paths from the config file directory. |
|
|
330
|
-
| **GitHub Actions workflow** | Warns when no workflow mentions `mcp-probe`, or when workflows miss `actions/checkout@v6`, `--config <file>`, or `--github-summary`. |
|
|
331
|
-
|
|
332
|
-
For automation, use JSON output:
|
|
333
|
-
|
|
334
|
-
```bash
|
|
335
|
-
mcp-probe doctor --config-file ci/mcp-probe.config.json --output json
|
|
336
|
-
```
|
|
337
|
-
|
|
338
|
-
## Stderr classification
|
|
339
|
-
|
|
340
|
-
Many MCP servers write harmless warnings to stderr during startup: optional config notices, update checks, deprecation warnings, and similar noise. If the server later fails to initialize, raw stderr can make those warnings look like the root cause.
|
|
341
|
-
|
|
342
|
-
mcp-probe has built-in warning filters and also lets you declare server-specific regexes:
|
|
116
|
+
Run:
|
|
343
117
|
|
|
344
118
|
```bash
|
|
345
|
-
mcp-probe
|
|
346
|
-
--stderr-allow "^Warning:" \
|
|
347
|
-
--stderr-allow "missing optional config" \
|
|
348
|
-
--stderr-fatal "panic|FATAL"
|
|
349
|
-
```
|
|
350
|
-
|
|
351
|
-
For batch checks, put the rules in `mcp-probe.config.json`:
|
|
352
|
-
|
|
353
|
-
```json
|
|
354
|
-
{
|
|
355
|
-
"name": "datadog",
|
|
356
|
-
"target": "https://mcp.example.com/mcp",
|
|
357
|
-
"stderr": {
|
|
358
|
-
"allow": ["^Warning:", "missing optional config"],
|
|
359
|
-
"fatal": ["panic", "FATAL"]
|
|
360
|
-
}
|
|
361
|
-
}
|
|
119
|
+
mcp-probe --config mcp-probe.config.json --github-summary --fail-on-warn
|
|
362
120
|
```
|
|
363
121
|
|
|
364
|
-
|
|
122
|
+
## Sidecar Inputs
|
|
365
123
|
|
|
366
|
-
|
|
124
|
+
Auto-generated tool inputs mostly test schema validation. Production CI should use sidecar inputs that reach real read-only paths.
|
|
367
125
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
By default, mcp-probe generates minimal inputs from each tool schema. That catches broken call paths, but real CI gates should prefer a sidecar file with meaningful sample inputs:
|
|
126
|
+
When a sidecar is provided, mcp-probe calls only the tools listed in that file. Tools that are discovered but not listed are not called.
|
|
371
127
|
|
|
372
128
|
```json
|
|
373
129
|
{
|
|
@@ -377,57 +133,19 @@ By default, mcp-probe generates minimal inputs from each tool schema. That catch
|
|
|
377
133
|
"query": "service:web status:error",
|
|
378
134
|
"timeframe": "1h"
|
|
379
135
|
},
|
|
380
|
-
"expect": {
|
|
381
|
-
"not_error_code": [401, 403]
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
```
|
|
387
|
-
|
|
388
|
-
Save this as `.mcp-probe.json` in your project root and run:
|
|
389
|
-
|
|
390
|
-
```bash
|
|
391
|
-
mcp-probe @your-org/datadog-mcp --probe-tools
|
|
392
|
-
```
|
|
393
|
-
|
|
394
|
-
Or pass an explicit path:
|
|
395
|
-
|
|
396
|
-
```bash
|
|
397
|
-
mcp-probe @your-org/datadog-mcp --tools-file ./ci/mcp-tools.json
|
|
398
|
-
```
|
|
399
|
-
|
|
400
|
-
Sidecar inputs are used first; generated minimal inputs are fallback only. Auth and permission failures such as 401/403 are surfaced as warnings so CI can distinguish "OAuth handoff needed" from transport or runtime failure.
|
|
401
|
-
|
|
402
|
-
## Tool call contract assertions
|
|
403
|
-
|
|
404
|
-
For production MCP servers, especially database-backed servers, a successful `tools/call` is still not enough. Agents depend on a contract: read-only roles, scoped data, stable error codes, safe limits, and no leaked internals.
|
|
405
|
-
|
|
406
|
-
Add assertions to `.mcp-probe.json` to validate that contract:
|
|
407
|
-
|
|
408
|
-
```json
|
|
409
|
-
{
|
|
410
|
-
"tools": {
|
|
411
|
-
"execute_sql": {
|
|
412
|
-
"input": {
|
|
413
|
-
"project_id": "YOUR_PROJECT_ID",
|
|
414
|
-
"query": "select 1 as health_check"
|
|
415
|
-
},
|
|
416
136
|
"expect": {
|
|
417
137
|
"status": "pass",
|
|
418
|
-
"
|
|
419
|
-
"
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
"errorCode": "WRITE_NOT_ALLOWED",
|
|
430
|
-
"notContains": ["DATABASE_URL", "password", "stack"]
|
|
138
|
+
"not_error_code": [401, 403],
|
|
139
|
+
"requiredFields": ["source", "freshness"],
|
|
140
|
+
"maxRows": 100,
|
|
141
|
+
"jsonSchema": {
|
|
142
|
+
"type": "object",
|
|
143
|
+
"required": ["source", "freshness"],
|
|
144
|
+
"properties": {
|
|
145
|
+
"source": { "type": "string" },
|
|
146
|
+
"freshness": { "type": "string" }
|
|
147
|
+
}
|
|
148
|
+
}
|
|
431
149
|
}
|
|
432
150
|
}
|
|
433
151
|
}
|
|
@@ -437,55 +155,43 @@ Add assertions to `.mcp-probe.json` to validate that contract:
|
|
|
437
155
|
Supported assertions:
|
|
438
156
|
|
|
439
157
|
| Assertion | Purpose |
|
|
440
|
-
|
|
441
|
-
| `status` | Expected call status: `pass`, `fail`, or `warn`.
|
|
442
|
-
| `requiredFields` |
|
|
443
|
-
| `maxRows` | Maximum allowed row count
|
|
158
|
+
|---|---|
|
|
159
|
+
| `status` | Expected call status: `pass`, `fail`, or `warn`. |
|
|
160
|
+
| `requiredFields` | Fields that must appear somewhere in the result payload. |
|
|
161
|
+
| `maxRows` | Maximum allowed row count from metadata or row arrays. |
|
|
444
162
|
| `errorCode` | Stable error code expected in an error response. |
|
|
445
|
-
| `contains` | Text snippets that must appear
|
|
446
|
-
| `notContains` | Text snippets that must not appear
|
|
447
|
-
| `not_error_code` | HTTP/status codes
|
|
163
|
+
| `contains` | Text snippets that must appear. |
|
|
164
|
+
| `notContains` | Text snippets that must not appear, useful for leak checks. |
|
|
165
|
+
| `not_error_code` | HTTP/status codes treated as warnings, usually auth handoff codes. |
|
|
166
|
+
| `jsonSchema` | JSON Schema subset for validating the observed tool result shape. |
|
|
448
167
|
|
|
449
|
-
|
|
168
|
+
## Doctor
|
|
450
169
|
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
Use `--badge-file` to write a [shields.io endpoint](https://shields.io/badges/endpoint-badge) JSON file:
|
|
170
|
+
`doctor` checks whether the repository is ready to run mcp-probe in CI:
|
|
454
171
|
|
|
455
172
|
```bash
|
|
456
|
-
mcp-probe
|
|
173
|
+
mcp-probe doctor
|
|
457
174
|
```
|
|
458
175
|
|
|
459
|
-
|
|
176
|
+
It validates:
|
|
460
177
|
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
}
|
|
468
|
-
```
|
|
178
|
+
- Node.js version
|
|
179
|
+
- config file shape
|
|
180
|
+
- sidecar file shape
|
|
181
|
+
- `expectedTools` sidecar sample coverage
|
|
182
|
+
- GitHub Actions workflow presence, strict CI flags, receipt generation, and artifact upload
|
|
183
|
+
- whether mcp-probe is actually executed from a workflow `run:` step
|
|
469
184
|
|
|
470
|
-
|
|
185
|
+
`doctor --fix` creates missing files. It does **not** rewrite existing workflows unless `--force` is explicitly passed.
|
|
186
|
+
When a config already declares `expectedTools`, missing sidecar files are scaffolded with those tool names instead of a generic placeholder.
|
|
471
187
|
|
|
472
|
-
```
|
|
473
|
-
|
|
188
|
+
```bash
|
|
189
|
+
mcp-probe doctor --fix --target @your-org/your-mcp-server
|
|
474
190
|
```
|
|
475
191
|
|
|
476
|
-
##
|
|
477
|
-
|
|
478
|
-
| Code | Meaning |
|
|
479
|
-
|------|---------|
|
|
480
|
-
| `0` | All checks passed (or warnings only) |
|
|
481
|
-
| `1` | One or more checks failed |
|
|
482
|
-
|
|
483
|
-
## CI integration
|
|
484
|
-
|
|
485
|
-
Single server workflow:
|
|
192
|
+
## GitHub Actions
|
|
486
193
|
|
|
487
194
|
```yaml
|
|
488
|
-
# .github/workflows/mcp-probe.yml
|
|
489
195
|
name: MCP Probe
|
|
490
196
|
|
|
491
197
|
on:
|
|
@@ -496,145 +202,52 @@ on:
|
|
|
496
202
|
jobs:
|
|
497
203
|
mcp-probe:
|
|
498
204
|
runs-on: ubuntu-latest
|
|
499
|
-
timeout-minutes: 5
|
|
500
|
-
|
|
501
|
-
steps:
|
|
502
|
-
- uses: actions/checkout@v6
|
|
503
|
-
|
|
504
|
-
- name: Validate MCP server
|
|
505
|
-
run: |
|
|
506
|
-
npx @k08200/mcp-probe @your-org/your-mcp-server \
|
|
507
|
-
--probe-tools \
|
|
508
|
-
--github-summary \
|
|
509
|
-
--badge-file mcp-probe-badge.json
|
|
510
|
-
```
|
|
511
|
-
|
|
512
|
-
Fleet workflow:
|
|
513
|
-
|
|
514
|
-
```yaml
|
|
515
|
-
# .github/workflows/mcp-fleet.yml
|
|
516
|
-
name: MCP Fleet Probe
|
|
517
|
-
|
|
518
|
-
on:
|
|
519
|
-
pull_request:
|
|
520
|
-
push:
|
|
521
|
-
branches: [main]
|
|
522
|
-
schedule:
|
|
523
|
-
- cron: "0 * * * *"
|
|
524
|
-
|
|
525
|
-
jobs:
|
|
526
|
-
mcp-probe:
|
|
527
|
-
runs-on: ubuntu-latest
|
|
528
|
-
timeout-minutes: 10
|
|
529
|
-
|
|
530
205
|
steps:
|
|
531
206
|
- uses: actions/checkout@v6
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
207
|
+
- uses: actions/setup-node@v6
|
|
208
|
+
with:
|
|
209
|
+
node-version: 20
|
|
210
|
+
- run: |
|
|
211
|
+
npx @k08200/mcp-probe@latest \
|
|
536
212
|
--config mcp-probe.config.json \
|
|
537
213
|
--github-summary \
|
|
538
|
-
--
|
|
214
|
+
--fail-on-warn \
|
|
215
|
+
--receipt-file mcp-probe.receipt.json
|
|
216
|
+
- uses: actions/upload-artifact@v4
|
|
217
|
+
with:
|
|
218
|
+
name: mcp-probe-receipt
|
|
219
|
+
path: mcp-probe.receipt.json
|
|
539
220
|
```
|
|
540
221
|
|
|
541
|
-
|
|
222
|
+
## Receipt Artifacts
|
|
542
223
|
|
|
543
|
-
|
|
224
|
+
`--receipt-file` writes a redacted JSON artifact containing the observed handshake, tool catalog, dry-run calls, contract assertions, and final status.
|
|
544
225
|
|
|
545
|
-
|
|
546
|
-
|---------|----------|
|
|
547
|
-
| [`single-server.yml`](examples/github-actions/single-server.yml) | Validate one stdio MCP package. |
|
|
548
|
-
| [`fleet.yml`](examples/github-actions/fleet.yml) | Validate several MCP servers from `mcp-probe.config.json` on PRs and hourly schedules. |
|
|
549
|
-
| [`remote-server.yml`](examples/github-actions/remote-server.yml) | Validate a remote Streamable HTTP MCP server with auth headers. |
|
|
550
|
-
|
|
551
|
-
mcp-probe also dogfoods itself in CI with [`examples/self-check.config.json`](examples/self-check.config.json), which validates batch mode, sidecar inputs, GitHub summaries, and badge output against a local fixture MCP server.
|
|
552
|
-
|
|
553
|
-
It also includes [`examples/contract-failure.tools.json`](examples/contract-failure.tools.json), an intentionally broken sidecar used by CI to prove contract failures surface as `CONTRACT_ASSERTION_FAILED`. That fixture checks the negative path: missing metadata, row-limit violations, and denied writes that must fail safely.
|
|
554
|
-
|
|
555
|
-
## Recipes
|
|
556
|
-
|
|
557
|
-
Production MCP checks work best with sidecar inputs that exercise real call paths instead of generated empty values. Copy-ready starting points live in [`examples/recipes`](examples/recipes):
|
|
558
|
-
|
|
559
|
-
| Recipe | Focus |
|
|
560
|
-
|--------|-------|
|
|
561
|
-
| [`datadog.tools.json`](examples/recipes/datadog.tools.json) | Logs/metrics queries that reveal auth handoff and downstream API failures. |
|
|
562
|
-
| [`supabase.tools.json`](examples/recipes/supabase.tools.json) | Project visibility and a harmless `select 1` SQL path. |
|
|
563
|
-
| [`gmail.tools.json`](examples/recipes/gmail.tools.json) | OAuth/token handoff and read-only mailbox access. |
|
|
564
|
-
|
|
565
|
-
Tool names vary by MCP server implementation. Run your server once with `--output json`, inspect the discovered tool names and schemas, then adjust the recipe file to match.
|
|
566
|
-
|
|
567
|
-
## JSON output
|
|
226
|
+
Use it when CI needs durable evidence of what actually happened, not just terminal output:
|
|
568
227
|
|
|
569
228
|
```bash
|
|
570
|
-
mcp-probe
|
|
229
|
+
mcp-probe --config mcp-probe.config.json --receipt-file mcp-probe.receipt.json
|
|
571
230
|
```
|
|
572
231
|
|
|
573
|
-
|
|
574
|
-
{
|
|
575
|
-
"target": "@your-org/datadog-mcp",
|
|
576
|
-
"timestamp": "2026-05-17T12:00:00.000Z",
|
|
577
|
-
"overallStatus": "warn",
|
|
578
|
-
"checks": [
|
|
579
|
-
{ "name": "Target resolution", "status": "pass", "message": "npx --yes @your-org/datadog-mcp" },
|
|
580
|
-
{ "name": "MCP protocol handshake", "status": "pass", "message": "datadog-mcp v1.0.0", "latencyMs": 1392 },
|
|
581
|
-
{ "name": "Tools discovery", "status": "pass", "message": "Found 12 tools", "latencyMs": 33 },
|
|
582
|
-
{ "name": "Tool schema validation", "status": "pass", "message": "All tool schemas are valid" },
|
|
583
|
-
{
|
|
584
|
-
"name": "Tool call dry-run",
|
|
585
|
-
"status": "warn",
|
|
586
|
-
"message": "1 auth/permission errors (1 sidecar, 0 auto)",
|
|
587
|
-
"issue": {
|
|
588
|
-
"code": "TOOL_CALL_AUTH",
|
|
589
|
-
"hint": "At least one tool call hit auth or permission handling. This often means CI needs tokens or the server needs non-browser auth."
|
|
590
|
-
}
|
|
591
|
-
}
|
|
592
|
-
],
|
|
593
|
-
"serverInfo": { "name": "datadog-mcp", "version": "1.0.0", "capabilities": ["tools"] },
|
|
594
|
-
"tools": [{ "name": "logs_query", "description": "Query Datadog logs" }],
|
|
595
|
-
"toolCallResults": [
|
|
596
|
-
{
|
|
597
|
-
"tool": "logs_query",
|
|
598
|
-
"status": "warn",
|
|
599
|
-
"latencyMs": 41,
|
|
600
|
-
"source": "sidecar",
|
|
601
|
-
"error": "401 Unauthorized",
|
|
602
|
-
"issue": {
|
|
603
|
-
"code": "TOOL_CALL_AUTH",
|
|
604
|
-
"hint": "The server registered this tool, but the call path hit auth or permission handling. Check OAuth/browser handoff, service tokens, and CI secrets."
|
|
605
|
-
}
|
|
606
|
-
}
|
|
607
|
-
],
|
|
608
|
-
"totalLatencyMs": 1455
|
|
609
|
-
}
|
|
610
|
-
```
|
|
611
|
-
|
|
612
|
-
## Status values
|
|
613
|
-
|
|
614
|
-
| Status | Icon | Meaning |
|
|
615
|
-
|--------|------|---------|
|
|
616
|
-
| `pass` | ✓ | Check succeeded |
|
|
617
|
-
| `warn` | ⚠ | Non-fatal issue (e.g. no tools registered) |
|
|
618
|
-
| `fail` | ✗ | Check failed — exits with code 1 |
|
|
232
|
+
## Exit Codes
|
|
619
233
|
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
- [x] Batch checking from a config file (`mcp-probe --config mcp-probe.config.json`)
|
|
625
|
-
- [x] GitHub Actions summary and annotations
|
|
626
|
-
- [x] Badge generation (`mcp-probe --badge-file mcp-probe-badge.json`)
|
|
627
|
-
- [x] Structured stderr classification rules
|
|
628
|
-
- [x] Server-specific recipe examples for Datadog, Supabase, and Gmail MCP servers
|
|
629
|
-
|
|
630
|
-
## Contributing
|
|
234
|
+
| Code | Meaning |
|
|
235
|
+
|---|---|
|
|
236
|
+
| `0` | Passed, or warnings only unless `--fail-on-warn` is set |
|
|
237
|
+
| `1` | One or more checks failed |
|
|
631
238
|
|
|
632
|
-
|
|
239
|
+
Warnings do not fail CI by default. They are intended for degraded states such as OAuth handoff or permission issues that should be visible but may not block every deploy.
|
|
240
|
+
Use `--fail-on-warn` for production readiness gates where auth handoff, permission warnings, or incomplete receipts should block the workflow.
|
|
633
241
|
|
|
634
|
-
##
|
|
242
|
+
## Development
|
|
635
243
|
|
|
636
|
-
|
|
244
|
+
```bash
|
|
245
|
+
npm install
|
|
246
|
+
npm run typecheck
|
|
247
|
+
npm test
|
|
248
|
+
npm run build
|
|
249
|
+
```
|
|
637
250
|
|
|
638
251
|
## License
|
|
639
252
|
|
|
640
|
-
|
|
253
|
+
MIT
|