@k08200/mcp-probe 1.6.0 → 1.8.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 +86 -517
- 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 +42 -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 +251 -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/scaffold.d.ts +17 -0
- package/dist/scaffold.d.ts.map +1 -0
- package/dist/scaffold.js +145 -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 +76 -0
- package/dist/sidecar.js.map +1 -0
- package/dist/types.d.ts +7 -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 +1 -0
- package/examples/github-actions/remote-server.yml +1 -0
- package/examples/github-actions/single-server.yml +1 -0
- package/examples/self-check.config.json +3 -1
- package/examples/self-check.strict.config.json +16 -0
- package/examples/self-check.strict.tools.json +29 -0
- package/package.json +1 -1
- package/schemas/mcp-probe.config.schema.json +15 -0
- package/schemas/mcp-probe.sidecar.schema.json +1 -1
package/README.md
CHANGED
|
@@ -3,275 +3,80 @@
|
|
|
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
|
|
15
19
|
|
|
16
|
-
|
|
20
|
+
## Quick Start
|
|
17
21
|
|
|
18
22
|
```bash
|
|
19
|
-
npx @k08200/mcp-probe@latest
|
|
20
|
-
--target @your-org/your-mcp-server \
|
|
21
|
-
--discover \
|
|
22
|
-
--github-actions
|
|
23
|
+
npx @k08200/mcp-probe@latest @modelcontextprotocol/server-memory
|
|
23
24
|
```
|
|
24
25
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
```yaml
|
|
28
|
-
name: MCP Probe
|
|
29
|
-
|
|
30
|
-
on:
|
|
31
|
-
pull_request:
|
|
32
|
-
push:
|
|
33
|
-
branches: [main]
|
|
34
|
-
|
|
35
|
-
jobs:
|
|
36
|
-
mcp-probe:
|
|
37
|
-
runs-on: ubuntu-latest
|
|
38
|
-
timeout-minutes: 5
|
|
39
|
-
|
|
40
|
-
steps:
|
|
41
|
-
- uses: actions/checkout@v6
|
|
42
|
-
|
|
43
|
-
- name: Validate MCP server
|
|
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:
|
|
26
|
+
For CI, scaffold a config, sidecar, and workflow:
|
|
51
27
|
|
|
52
28
|
```bash
|
|
53
|
-
npx @k08200/mcp-probe
|
|
29
|
+
npx @k08200/mcp-probe@latest init \
|
|
30
|
+
--target @your-org/your-mcp-server \
|
|
31
|
+
--discover \
|
|
32
|
+
--github-actions
|
|
54
33
|
```
|
|
55
34
|
|
|
56
|
-
|
|
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
|
-
```
|
|
35
|
+
Then run:
|
|
76
36
|
|
|
77
37
|
```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
|
|
38
|
+
npx @k08200/mcp-probe@latest --config mcp-probe.config.json --github-summary --fail-on-warn
|
|
106
39
|
```
|
|
107
40
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
## Install
|
|
111
|
-
|
|
112
|
-
Requires Node.js 20.19 or newer.
|
|
41
|
+
## Commands
|
|
113
42
|
|
|
114
43
|
```bash
|
|
115
|
-
#
|
|
116
|
-
npx @k08200/mcp-probe <target>
|
|
117
|
-
|
|
118
|
-
# Or install globally
|
|
119
|
-
npm install -g @k08200/mcp-probe
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
## Usage
|
|
123
|
-
|
|
124
|
-
```bash
|
|
125
|
-
# Check an npm package
|
|
44
|
+
# Check one server
|
|
126
45
|
mcp-probe @modelcontextprotocol/server-memory
|
|
127
46
|
|
|
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
|
|
155
|
-
|
|
156
|
-
# Check a local server file
|
|
157
|
-
mcp-probe ./my-server.js
|
|
47
|
+
# Check a local server
|
|
48
|
+
mcp-probe ./server.js
|
|
158
49
|
|
|
159
|
-
# Check a remote Streamable HTTP
|
|
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
|
|
50
|
+
# Check a remote Streamable HTTP server
|
|
166
51
|
mcp-probe https://mcp.example.com/mcp --header "Authorization: Bearer $TOKEN"
|
|
167
52
|
|
|
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
|
|
53
|
+
# Batch-check from config
|
|
178
54
|
mcp-probe --config mcp-probe.config.json
|
|
179
55
|
|
|
180
|
-
#
|
|
181
|
-
mcp-probe --config mcp-probe.config.json --github-summary
|
|
182
|
-
|
|
183
|
-
# Write shields.io endpoint JSON for a status badge
|
|
184
|
-
mcp-probe --config mcp-probe.config.json --badge-file mcp-probe-badge.json
|
|
185
|
-
|
|
186
|
-
# Call tools with generated minimal inputs
|
|
56
|
+
# Call tools, not just tools/list
|
|
187
57
|
mcp-probe @scope/server --probe-tools
|
|
188
58
|
|
|
189
|
-
#
|
|
59
|
+
# Use meaningful sidecar inputs
|
|
190
60
|
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
61
|
|
|
205
|
-
|
|
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
|
-
|
|
223
|
-
Common issue codes:
|
|
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
|
|
62
|
+
# Preflight local mcp-probe setup
|
|
63
|
+
mcp-probe doctor
|
|
238
64
|
|
|
239
|
-
|
|
65
|
+
# Make warnings fail CI too
|
|
66
|
+
mcp-probe --config mcp-probe.config.json --fail-on-warn
|
|
240
67
|
|
|
241
|
-
|
|
242
|
-
mcp-probe
|
|
68
|
+
# Create missing config/sidecar/workflow files
|
|
69
|
+
mcp-probe doctor --fix --target @scope/server
|
|
243
70
|
```
|
|
244
71
|
|
|
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`.
|
|
254
|
-
|
|
255
|
-
Generated config and sidecar files include JSON Schema references:
|
|
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.
|
|
72
|
+
## Config
|
|
263
73
|
|
|
264
|
-
Use
|
|
74
|
+
Use `mcp-probe.config.json` when a repository depends on one or more MCP servers:
|
|
265
75
|
|
|
266
76
|
```json
|
|
267
77
|
{
|
|
268
78
|
"timeoutMs": 10000,
|
|
269
79
|
"servers": [
|
|
270
|
-
{
|
|
271
|
-
"name": "memory",
|
|
272
|
-
"target": "@modelcontextprotocol/server-memory",
|
|
273
|
-
"probeTools": true
|
|
274
|
-
},
|
|
275
80
|
{
|
|
276
81
|
"name": "datadog",
|
|
277
82
|
"target": "https://mcp.example.com/mcp",
|
|
@@ -279,95 +84,30 @@ Use `--config` when a project depends on several MCP servers and you want one CI
|
|
|
279
84
|
"headers": {
|
|
280
85
|
"Authorization": "Bearer ${DATADOG_MCP_TOKEN}"
|
|
281
86
|
},
|
|
282
|
-
"
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
},
|
|
286
|
-
"toolsFile": "./recipes/datadog.tools.json"
|
|
87
|
+
"expectedTools": ["logs_query"],
|
|
88
|
+
"forbiddenTools": ["delete_dashboard", "rotate_api_key"],
|
|
89
|
+
"toolsFile": "./datadog.tools.json"
|
|
287
90
|
}
|
|
288
91
|
]
|
|
289
92
|
}
|
|
290
93
|
```
|
|
291
94
|
|
|
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
|
-
```
|
|
322
|
-
|
|
323
|
-
It checks:
|
|
95
|
+
Relative local `target` and `toolsFile` paths are resolved from the config file directory.
|
|
324
96
|
|
|
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`. |
|
|
97
|
+
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.
|
|
98
|
+
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.
|
|
331
99
|
|
|
332
|
-
|
|
100
|
+
Run:
|
|
333
101
|
|
|
334
102
|
```bash
|
|
335
|
-
mcp-probe
|
|
103
|
+
mcp-probe --config mcp-probe.config.json --github-summary --fail-on-warn
|
|
336
104
|
```
|
|
337
105
|
|
|
338
|
-
##
|
|
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:
|
|
106
|
+
## Sidecar Inputs
|
|
343
107
|
|
|
344
|
-
|
|
345
|
-
mcp-probe @scope/server \
|
|
346
|
-
--stderr-allow "^Warning:" \
|
|
347
|
-
--stderr-allow "missing optional config" \
|
|
348
|
-
--stderr-fatal "panic|FATAL"
|
|
349
|
-
```
|
|
108
|
+
Auto-generated tool inputs mostly test schema validation. Production CI should use sidecar inputs that reach real read-only paths.
|
|
350
109
|
|
|
351
|
-
|
|
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
|
-
}
|
|
362
|
-
```
|
|
363
|
-
|
|
364
|
-
`fatal` patterns win over `allow` patterns. If every stderr line is allowed noise, mcp-probe reports the actual connection/init error instead of the warning text.
|
|
365
|
-
|
|
366
|
-
## Tool call dry-runs
|
|
367
|
-
|
|
368
|
-
Discovery proves that a server starts and registers tools. It does **not** prove that the tools actually work in an agent loop. Use `--probe-tools` to call every discovered tool.
|
|
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:
|
|
110
|
+
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
111
|
|
|
372
112
|
```json
|
|
373
113
|
{
|
|
@@ -377,58 +117,12 @@ By default, mcp-probe generates minimal inputs from each tool schema. That catch
|
|
|
377
117
|
"query": "service:web status:error",
|
|
378
118
|
"timeframe": "1h"
|
|
379
119
|
},
|
|
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
120
|
"expect": {
|
|
417
121
|
"status": "pass",
|
|
418
|
-
"
|
|
122
|
+
"not_error_code": [401, 403],
|
|
123
|
+
"requiredFields": ["source", "freshness"],
|
|
419
124
|
"maxRows": 100
|
|
420
125
|
}
|
|
421
|
-
},
|
|
422
|
-
"execute_sql_write_denied": {
|
|
423
|
-
"input": {
|
|
424
|
-
"project_id": "YOUR_PROJECT_ID",
|
|
425
|
-
"query": "delete from users where id = 1"
|
|
426
|
-
},
|
|
427
|
-
"expect": {
|
|
428
|
-
"status": "fail",
|
|
429
|
-
"errorCode": "WRITE_NOT_ALLOWED",
|
|
430
|
-
"notContains": ["DATABASE_URL", "password", "stack"]
|
|
431
|
-
}
|
|
432
126
|
}
|
|
433
127
|
}
|
|
434
128
|
}
|
|
@@ -437,55 +131,42 @@ Add assertions to `.mcp-probe.json` to validate that contract:
|
|
|
437
131
|
Supported assertions:
|
|
438
132
|
|
|
439
133
|
| Assertion | Purpose |
|
|
440
|
-
|
|
441
|
-
| `status` | Expected call status: `pass`, `fail`, or `warn`.
|
|
442
|
-
| `requiredFields` |
|
|
443
|
-
| `maxRows` | Maximum allowed row count
|
|
134
|
+
|---|---|
|
|
135
|
+
| `status` | Expected call status: `pass`, `fail`, or `warn`. |
|
|
136
|
+
| `requiredFields` | Fields that must appear somewhere in the result payload. |
|
|
137
|
+
| `maxRows` | Maximum allowed row count from metadata or row arrays. |
|
|
444
138
|
| `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
|
|
448
|
-
|
|
449
|
-
If an assertion fails, mcp-probe returns `CONTRACT_ASSERTION_FAILED` and includes per-assertion details in JSON and GitHub Actions summaries.
|
|
139
|
+
| `contains` | Text snippets that must appear. |
|
|
140
|
+
| `notContains` | Text snippets that must not appear, useful for leak checks. |
|
|
141
|
+
| `not_error_code` | HTTP/status codes treated as warnings, usually auth handoff codes. |
|
|
450
142
|
|
|
451
|
-
##
|
|
143
|
+
## Doctor
|
|
452
144
|
|
|
453
|
-
|
|
145
|
+
`doctor` checks whether the repository is ready to run mcp-probe in CI:
|
|
454
146
|
|
|
455
147
|
```bash
|
|
456
|
-
mcp-probe
|
|
148
|
+
mcp-probe doctor
|
|
457
149
|
```
|
|
458
150
|
|
|
459
|
-
|
|
151
|
+
It validates:
|
|
460
152
|
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
}
|
|
468
|
-
```
|
|
153
|
+
- Node.js version
|
|
154
|
+
- config file shape
|
|
155
|
+
- sidecar file shape
|
|
156
|
+
- `expectedTools` sidecar sample coverage
|
|
157
|
+
- GitHub Actions workflow presence and recommended flags (`--github-summary`, `--fail-on-warn`)
|
|
158
|
+
- whether mcp-probe is actually executed from a workflow `run:` step
|
|
469
159
|
|
|
470
|
-
|
|
160
|
+
`doctor --fix` creates missing files. It does **not** rewrite existing workflows unless `--force` is explicitly passed.
|
|
161
|
+
When a config already declares `expectedTools`, missing sidecar files are scaffolded with those tool names instead of a generic placeholder.
|
|
471
162
|
|
|
472
|
-
```
|
|
473
|
-
|
|
163
|
+
```bash
|
|
164
|
+
mcp-probe doctor --fix --target @your-org/your-mcp-server
|
|
474
165
|
```
|
|
475
166
|
|
|
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:
|
|
167
|
+
## GitHub Actions
|
|
486
168
|
|
|
487
169
|
```yaml
|
|
488
|
-
# .github/workflows/mcp-probe.yml
|
|
489
170
|
name: MCP Probe
|
|
490
171
|
|
|
491
172
|
on:
|
|
@@ -496,145 +177,33 @@ on:
|
|
|
496
177
|
jobs:
|
|
497
178
|
mcp-probe:
|
|
498
179
|
runs-on: ubuntu-latest
|
|
499
|
-
timeout-minutes: 5
|
|
500
|
-
|
|
501
180
|
steps:
|
|
502
181
|
- uses: actions/checkout@v6
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
--probe-tools \
|
|
508
|
-
--github-summary \
|
|
509
|
-
--badge-file mcp-probe-badge.json
|
|
182
|
+
- uses: actions/setup-node@v6
|
|
183
|
+
with:
|
|
184
|
+
node-version: 20
|
|
185
|
+
- run: npx @k08200/mcp-probe@latest --config mcp-probe.config.json --github-summary --fail-on-warn
|
|
510
186
|
```
|
|
511
187
|
|
|
512
|
-
|
|
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
|
-
steps:
|
|
531
|
-
- uses: actions/checkout@v6
|
|
532
|
-
|
|
533
|
-
- name: Validate MCP fleet
|
|
534
|
-
run: |
|
|
535
|
-
npx @k08200/mcp-probe \
|
|
536
|
-
--config mcp-probe.config.json \
|
|
537
|
-
--github-summary \
|
|
538
|
-
--badge-file mcp-probe-badge.json
|
|
539
|
-
```
|
|
540
|
-
|
|
541
|
-
When `--github-summary` is enabled in GitHub Actions, mcp-probe appends a Markdown report to `$GITHUB_STEP_SUMMARY` and emits workflow annotations for failed checks, warnings, and tool-call dry-run errors. This makes PR failures point directly at the broken MCP server or tool call instead of burying the signal in raw logs.
|
|
542
|
-
|
|
543
|
-
Copy-ready examples live in [`examples/github-actions`](examples/github-actions):
|
|
188
|
+
## Exit Codes
|
|
544
189
|
|
|
545
|
-
|
|
|
546
|
-
|
|
547
|
-
|
|
|
548
|
-
|
|
|
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. |
|
|
190
|
+
| Code | Meaning |
|
|
191
|
+
|---|---|
|
|
192
|
+
| `0` | Passed, or warnings only unless `--fail-on-warn` is set |
|
|
193
|
+
| `1` | One or more checks failed |
|
|
564
194
|
|
|
565
|
-
|
|
195
|
+
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.
|
|
196
|
+
Use `--fail-on-warn` for production readiness gates where auth handoff, permission warnings, or incomplete receipts should block the workflow.
|
|
566
197
|
|
|
567
|
-
##
|
|
198
|
+
## Development
|
|
568
199
|
|
|
569
200
|
```bash
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
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
|
-
}
|
|
201
|
+
npm install
|
|
202
|
+
npm run typecheck
|
|
203
|
+
npm test
|
|
204
|
+
npm run build
|
|
610
205
|
```
|
|
611
206
|
|
|
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 |
|
|
619
|
-
|
|
620
|
-
## Roadmap
|
|
621
|
-
|
|
622
|
-
- [x] Self-check batch workflow for mcp-probe itself
|
|
623
|
-
- [x] HTTP/SSE transport support
|
|
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
|
|
631
|
-
|
|
632
|
-
Issues and PRs are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
633
|
-
|
|
634
|
-
## Changelog
|
|
635
|
-
|
|
636
|
-
See [CHANGELOG.md](CHANGELOG.md).
|
|
637
|
-
|
|
638
207
|
## License
|
|
639
208
|
|
|
640
|
-
|
|
209
|
+
MIT
|