From testing
Use when the user mentions mcporter, says "test an MCP server", "smoke-test these tools", "automate MCP testing", "call a tool from the shell", "list MCP tools", "exercise the gateway tools", or asks for a script that hits MCP endpoints. Covers using mcporter to discover, inspect, and call MCP servers from the shell, and to write repeatable regression or smoke-test scripts. Not for designing new MCP servers, writing server-side handlers, or generic API testing unrelated to MCP.
How this skill is triggered — by the user, by Claude, or both
Slash command
/testing:mcporterThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
- Argument: $ARGUMENTS
pwdcommand -v mcporter >/dev/null && mcporter --version 2>/dev/null || echo "not installed (npm i -g mcporter)"mcporter list --json 2>/dev/null | jq -r '.servers[] | "\(.status)\t\(.name)"' 2>/dev/null | head -20 || echo "none / mcporter unavailable"mcporter is a shell client for the Model Context Protocol. Use it to list servers, inspect tool schemas, call tools, and drive scripted regression tests over the wire — without writing a TypeScript client.
Auto-loads servers from ./config/mcporter.json plus editor imports (Cursor, Claude Code, Codex, etc.), so most named servers in the user's environment already work without setup.
mcporter list # all configured servers (status only)
mcporter list <server> --schema # tool docs for one server
mcporter list <server> --schema --all-parameters --json
mcporter call <server>.<tool> k=v ... # invoke a tool
mcporter call <server>.<tool> --args '{"k":"v"}' # JSON payload
mcporter call <server>.<tool> --output json # machine-readable
mcporter auth <server> # OAuth handshake only (no listing)
mcporter config doctor # validate all configs
Selectors are server.tool. The argument is server or a full https://host/mcp URL.
mcporter call overloads on the second segment:
mcporter call <server>.<tool> k=v # tool call
mcporter call <server>.<resource-uri> # resource read (URI contains ://)
mcporter call <server> --tool <prompt-name> ... # prompt fetch
If the schema isn't obvious, run mcporter list <server> --schema --all-parameters first — guessing arg names against the wrong shape is the #1 wasted call.
| Form | When |
|---|---|
key=value / key:value | Flat scalar args, fast for shell use |
--args '{...}' | Nested objects, arrays, anything with quoting pain |
'server.tool(key: "value", n: 1)' | Function-call syntax when you want it self-documenting in a script |
--output text\|markdown\|json\|raw controls formatting; always use json for scripts.
mcporter list --http-url https://host/mcp --schema
mcporter call --stdio 'bun run ./server.ts' my_tool arg=1
mcporter list https://host/mcp # bare URL = HTTP
mcporter call --stdio 'node srv.js' --env API_KEY=$KEY tool arg=1
Persist a working ad-hoc definition with --persist ./config/mcporter.json --yes.
When the user wants a sharable, schema-validated wrapper rather than a shell script, prefer mcporter generate-cli:
mcporter generate-cli --server <name> --compile ./bin/<name>-cli
mcporter generate-cli --command 'npx -y @org/server' --name my-cli --compile ./bin/my-cli
The generated CLI bundles the tool schemas at build time, so every call is type-checked locally before it leaves the process. Inspect a generated binary with mcporter inspect-cli ./bin/my-cli.
The goal: prove each tool returns the right thing for a known input — and catch breakage before sending the call when possible. Keep the script readable.
The template at scripts/smoke.sh (in this skill folder) does three things mcporter doesn't:
inputSchema once and rejects any case whose args are missing a required key. Catches typos locally, no network call.MCP error -32xxx), and tool-level isError: true envelopes as failures (each tagged differently in the report).mcporter call --output json, which currently emits Node util.inspect format (not parseable JSON) on most servers.Each row in CASES=():
"label|args|assertion"
| Field | Meaning |
|---|---|
label | Tool name (search) or resource URI (ui://server/status) |
args | Appended to mcporter call. key=value flat, --args '{...}' nested, empty for resources |
assertion | One of the five forms below |
| Assertion form | What it checks |
|---|---|
| (empty) | Liveness — call must succeed, no error envelope |
contains: TEXT | Response text must include TEXT |
regex: PATTERN | Bash ERE matched against response text |
jq: FILTER | Response text parsed as JSON, jq -e FILTER must be truthy |
error: KIND | Expects an error envelope; passes if .kind == KIND or message contains KIND |
./smoke.sh --list-tools <server> # one tool name per line — pipe to grep
./smoke.sh --init <server> # print skeleton CASES=() from the schema
# required args are pre-filled with TODO
Typical flow: ./smoke.sh --init lab > cases.sh.fragment, paste the relevant tools into smoke.sh, replace each TODO with a real value plus an assertion, run.
| Var | Effect |
|---|---|
TIMEOUT_MS=8000 | Per-call timeout (default 15000) |
VERBOSE=1 | Dump raw response on any failure |
NO_PREFLIGHT=1 | Skip schema preflight (e.g. to test the server's own validation) |
--output json?mcporter call --output json currently emits Node util.inspect output (unquoted keys, single quotes, string concatenation with +) — verified against multiple servers. jq cannot parse it. The script uses --output text for assertions and --output raw only to inspect the envelope for isError and the error kind. If a tool's response is a JSON string, the jq: assertion form parses that string with jq.
set -e traps to knowIf you copy snippets out of smoke.sh, two patterns will bite you under set -e:
((counter++)) returns the old value of counter — when it was 0, exit code is 1 and the script dies. Use ((++counter)) or counter=$((counter+1)).[[ test ]] && command returns the failed test's exit when the test is false — fine inside if/while/|| lists, fatal as a standalone statement. Use if [[ test ]]; then command; fi.Same loop — URI is the label, args is empty:
"ui://server/status||contains: ok"
"file://docs/readme.md||regex: ^# "
| Symptom | Likely cause | Fix |
|---|---|---|
Unknown MCP server 'X' | Name typo or import not picked up | mcporter list to see actual names; mcporter config list --verbose for sources |
Tool call hangs ~30s then tools unavailable | Stdio binary missing (ENOENT) | Build / install the server binary; check the transport field in --json |
SSE error: Non-200 status code | HTTP server down or auth expired | mcporter auth <server> --reset or check the URL |
| Args rejected with cryptic schema error | Flat k=v against a nested schema | Switch to --args '{...}' |
OAuth timeout | Browser flow didn't complete in time | --oauth-timeout 180000 and rerun mcporter auth |
mcporter list --json | jq '.servers[] | {name, status}' # health snapshot
mcporter list <s> --schema --json | jq '.tools[].name' # tool names only
mcporter call <s>.<t> --args "$(cat payload.json)" --output json | jq .
mcporter generate-cli --server <s> --compile ./bin/<s> # ship a binary
key=value on the command line — use --env KEY=$VAR for stdio servers, env-injection for HTTP.mcporter call + a shell loop will do.--output json for machine-parseable output in scripts — it emits Node util.inspect format, not valid JSON. Use --output text for assertions and --output raw for envelope inspection../config/mcporter.json with personal tokens; use editor-imports or --env.references/cli-commands.md — full flag tables for every subcommand (list, call, auth, generate-cli, emit-ts, config, daemon). Load when you need exact flag semantics beyond the quick reference above.references/configuration.md — mcporter.json format, config resolution order, allowedTools/blockedTools, OAuth cache, and all environment variables.references/tips-gotchas.md — real footguns in rough order of frequency: --help coverage gaps, function-call quoting, generate-cli input exclusivity, Bun requirement for --compile, daemon limitations, and string-field coercion.references/typescript-api.md — callOnce(), createRuntime(), createServerProxy() API surface and when to use each. Load when the user wants a TypeScript client rather than a shell script.scripts/smoke.sh — the test harness template. Copy and populate CASES=() for a new server.npx claudepluginhub jmagar/dendrite --plugin testingGuides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.