# MCP Tester
The Swiss Army knife for testing MCP servers. Validate protocol conformance, test tools, generate scenarios, and diagnose connection issues — all from a single binary.
```
$ mcp-tester test http://localhost:3000
MCP Server Test Report
══════════════════════════════════════════════════════
Server: my-server v1.0.0 | Protocol: 2025-11-25
Core
✓ Initialize Server responded with valid capabilities
✓ Protocol Version Protocol version: 2025-11-25
✓ Server Info my-server v1.0.0
✓ Capabilities tools, resources, prompts
Tools
✓ List Found 5 tools
✓ Schema All 5 tool schemas valid
Resources
✓ List Found 2 resources
Summary: 7 passed, 0 failed, 0 warnings in 1.23s
```
## Install
### Option 1: Cargo (recommended for Rust developers)
```bash
# Standalone binary
cargo install mcp-tester
# Or as part of the full PMCP toolkit
cargo install cargo-pmcp
```
### Option 2: Shell script (no Rust required)
Linux and macOS — downloads the pre-built binary for your platform:
```bash
curl -fsSL https://raw.githubusercontent.com/paiml/rust-mcp-sdk/main/install/install.sh | sh
```
Windows PowerShell:
```powershell
irm https://raw.githubusercontent.com/paiml/rust-mcp-sdk/main/install/install.ps1 | iex
```
Pre-built binaries are available for Linux x86_64/ARM64, macOS Intel/Apple Silicon, and Windows x86_64.
### Option 3: Via MCP (use from any MCP client)
The PMCP server at `https://pmcp-server.us-east.true-mcp.com/mcp` exposes testing tools you can call directly from Claude Desktop, ChatGPT, or any MCP client — no local install needed.
## Quick Start: Check
The fastest way to validate an MCP server — one command, pass/fail answer:
```bash
# Test a local server
mcp-tester quick http://localhost:3000
# Test a remote server
mcp-tester quick https://my-server.example.com/mcp
# Test with OAuth
mcp-tester quick https://api.example.com/mcp \
--oauth-issuer "https://auth.example.com" \
--oauth-client-id "my-client-id"
# Via cargo-pmcp (auto-discovers server in your workspace)
cargo pmcp test check http://localhost:3000
```
## Protocol Conformance
Validate any MCP server against the protocol spec (2025-11-25). Tests 5 domains: Core, Tools, Resources, Prompts, Tasks. Each domain reports independently — a server with no resources still passes.
```bash
# Full conformance check
mcp-tester conformance http://localhost:3000
# Strict mode (warnings → failures)
mcp-tester conformance http://localhost:3000 --strict
# Test specific domains only
mcp-tester conformance http://localhost:3000 --domain core,tools
# Via cargo-pmcp
cargo pmcp test conformance http://localhost:3000
```
Output includes a per-domain CI summary line:
```
Conformance: Core=PASS Tools=PASS Resources=SKIP Prompts=PASS Tasks=SKIP
```
## App Validation
Validate MCP App metadata on a running server. Cross-references tools that declare `ui.resourceUri` against the resources they reference, validates MIME types, and (in strict modes) statically inspects the widget HTML for required protocol handler wiring.
```bash
# Default (permissive) — one summary Warning per widget
mcp-tester apps http://localhost:3000
# ChatGPT compatibility mode (no-op for widget HTML inspection)
mcp-tester apps http://localhost:3000 --mode chatgpt
# Claude Desktop / Claude.ai pre-deploy gate (strict static widget inspection)
mcp-tester apps http://localhost:3000 --mode claude-desktop
```
`--mode claude-desktop` statically inspects each widget HTML body for the `@modelcontextprotocol/ext-apps` import and the four required protocol handlers (`onteardown`, `ontoolinput`, `ontoolcancelled`, `onerror`) before `connect()`. This catches the silent-fail class where Claude Desktop tears down the MCP connection after a missing handler — see [src/server/mcp_apps/GUIDE.md#handlers-before-connect](https://github.com/paiml/rust-mcp-sdk/blob/main/src/server/mcp_apps/GUIDE.md#handlers-before-connect).
### Source-scan mode: `--widgets-dir <path>`
Two scan surfaces are supported:
| Scan mode | When to use | What it scans |
|-----------|-------------|---------------|
| **Bundle scan** (default) | CI against a deployed server | Each widget HTML body fetched via `resources/read` |
| **Source scan** (`--widgets-dir <path>`) | Local pre-deploy validation | `<path>/*.html` source files on disk |
**Why both:** Bundle scan validates what the server actually serves to clients (the post-Vite-singlefile bytes). Source scan is faster and higher-confidence pre-deploy because source files have unmangled identifiers and intact import statements — minifiers cannot defeat patterns that match against the unminified `import { App } from '@modelcontextprotocol/ext-apps'`.
The validator's regex set is minification-resistant in both modes (see [Plan 78-06 — gap closure for cost-coach minified-bundle false positives](../../.planning/phases/78-cargo-pmcp-test-apps-mode-claude-desktop-detect-missing-mcp-/78-06-PLAN.md)). The four SDK-presence signals — `[ext-apps]` log prefix, `ui/initialize` method literal, `ui/notifications/tool-result` method literal, and the legacy `@modelcontextprotocol/ext-apps` import literal — survive Vite singlefile minification because they are protocol-level strings the SDK exposes by name.
Example:
```bash
# Source-scan local widget files (pre-deploy)
cargo pmcp test apps --mode claude-desktop --widgets-dir ./widget "http://informational"
# Bundle-scan against a deployed server (CI)
cargo pmcp test apps --mode claude-desktop https://my-server.example.com/mcp
```
Same validator, same verdict shape, two ingestion paths.
## Generate Test Scenarios
Auto-generate test scenarios from your server's capabilities. The generator discovers all tools, analyzes their JSON schemas, and creates YAML scenario files with smart placeholder values:
```bash
# Generate from a running server
mcp-tester generate-scenario http://localhost:3000 -o tests/my-server.yaml \
--all-tools --with-resources --with-prompts
# Via cargo-pmcp
cargo pmcp test generate --server my-server --port 3000
```
This produces editable YAML like:
```yaml
name: my-server Test Scenario
timeout: 60
steps:
- name: Test tool search
operation:
type: tool_call
tool: search
arguments:
query: "TODO: query" # ← fill in real test data
assertions:
- type: success
- type: exists
path: results
```
## Run Test Scenarios
Execute generated or hand-written scenarios against your server:
```bash
# Run a single scenario
mcp-tester scenario http://localhost:3000 tests/my-server.yaml --detailed
# Run all scenarios in a directory
cargo pmcp test run --server my-server --scenarios tests/
```
## All Commands
| Command | Description |
|---------|-------------|
| `test` | Full test suite — protocol, tools, resources, prompts |
| `quick` | Fast connectivity and protocol check |
| `conformance` | MCP protocol conformance validation (19 scenarios across 5 domains) |
| `tools` | Discover tools and validate schemas |
| `resources` | Test resource discovery and reading |
| `prompts` | Validate prompt templates and arguments |
| `apps` | Validate MCP App metadata (standard, ChatGPT, Claude Desktop modes) |
| `generate-scenario` | Auto-generate test scenarios from server capabilities |
| `scenario` | Run YAML/JSON test scenarios |
| `diagnose` | Layer-by-layer connection diagnostics |
| `compare` | Compare two servers side-by-side |
| `health` | Health check endpoint |
## Key Features
- **Multi-transport**: HTTP, HTTPS, WebSocket, stdio — auto-detected or forced with `--transport`
- **OAuth 2.0**: Interactive browser-based PKCE flow with token caching (`--oauth-*` flags)
- **Schema validation**: Warns about missing properties, empty schemas, incomplete metadata
- **MCP App validation**: Checks `_meta`, `ui.resourceUri`, resource cross-refs, ChatGPT keys
- **CI/CD ready**: `--format json` for machine-readable output, deterministic exit codes
- **Multiple output formats**: `pretty` (default), `json`, `minimal`, `verbose`
## CI/CD Integration
```yaml
# GitHub Actions
- name: Test MCP Server
run: |
curl -fsSL https://raw.githubusercontent.com/paiml/rust-mcp-sdk/main/install/install.sh | sh
mcp-tester test ${{ env.SERVER_URL }} --format json > results.json
```
```bash
# Any CI — exit code tells you pass/fail
mcp-tester test "$SERVER_URL" --format minimal
```
## Documentation
- [Scenario Format Reference](SCENARIO_FORMAT.md) — YAML/JSON scenario structure, operations, and assertions
- [cargo-pmcp README](../../cargo-pmcp/README.md) — Full PMCP toolkit including test, preview, and deploy commands
- [PMCP SDK](../../README.md) — The Rust MCP SDK that powers mcp-tester
## License
MIT — See [LICENSE](../../LICENSE) in the repository root.