mcptest docs GitHub

The hosted test server

https://test.mcptest.sh is a hosted MCP server you can point mcptest at to exercise the engine without standing up your own. Every tool and scenario maps to a feature, so it doubles as a learning platform. It is a teaching fixture, not a real server: it is stateless, read data is seeded, and mutating tools simulate a result without persisting.

Run this example. examples/hosted-smoke.yml exercises the conformant catalog end to end against it.

mcptest run --config examples/hosted-smoke.yml
mcptest discover --url https://test.mcptest.sh

These commands need test.mcptest.sh to be reachable. If the host does not resolve or the initialize handshake times out, the server is not deployed in your environment, which is an availability issue rather than a problem with the example. For a fully local, key-free run that needs no hosted server, use the bundled reference server (examples/server-stdio.yml and the examples/reference-server/ folder).

The conformant catalog

POST https://test.mcptest.sh/mcp speaks JSON-RPC and serves this catalog:

ToolFeature it teaches
greet(name)a happy-path tool call and the exact matcher
search(query)content arrays, contains and schema matchers
get_forecast(city)a declared outputSchema and structuredContent (rule SCHEMA-006)
list_items(cursor?)cursor pagination with nextCursor
slow_op(delay_ms?)latency budgets (max_duration_ms)
fail(code?)error envelopes and negative tests
delete_record(id)a destructiveHint annotation

It also serves two resources (docs://welcome, items://{id}) and a summarize prompt.

Scenario modes

The same endpoint switches behavior by query, so one server covers drift, non-conformance, and security.

Drift

/mcp?catalog=v1 returns the prior catalog: an extra archive_item tool (removed in the current catalog), search.query optional (required now), and a kelvin units enum value (removed now). Capture both catalogs and diff them to see breaking changes. See mcptest diff and the diff-tools snapshot pair.

Invalid MCP

/mcp?scenario=invalid returns spec-violating responses: a malformed protocolVersion, a missing capabilities block, and a tools/call result with no content. Run a compliance suite against it to see what a failing compliance run looks like.

Insecure catalog

/mcp?scenario=insecure serves a deliberately poisoned catalog (a description that injects instructions, a cross-tool directive, an exfiltration sink, hidden unicode in a name, a credential left in a description, and an unannotated destructive tool). Capture its tools/list and scan it:

curl -s -X POST 'https://test.mcptest.sh/mcp?scenario=insecure' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' > insecure.json
mcptest security insecure.json --fail-on high

See security checks.

Equal-function set (the alt catalog)

/mcp?catalog=alt serves the same capabilities as the conformant catalog under different tool names: greeting for greet, lookup for search, and weather_now for get_forecast. Point a second server at it and declare the matching tools as an equal-function set, so tool selection is scored on capability, not on a name match. See tool-selection F1.

Distractor tools

/mcp?scenario=distractors&n=8 serves the real get_forecast buried among n near-duplicate decoys (clamped 1..20). Only get_forecast returns a forecast; every decoy errors with -32601 when called. The real tool is placed last, so a position-biased agent cannot win by always picking the first match. Raise n to chart how selection accuracy decays as the catalog grows. See distractor tools.

Legacy resource-error code

/mcp?scenario=legacy returns the pre-2026-07-28 missing-resource code (-32002) instead of the standard JSON-RPC -32602, so the migration doctor has a non-conformant target to flag:

curl -s -X POST 'https://test.mcptest.sh/mcp?scenario=legacy' \
  -d '{"jsonrpc":"2.0","id":1,"method":"resources/read","params":{"uri":"items://999"}}'
# -> error.code -32002 (the conformant endpoint returns -32602)

See spec-version pinning.

Rate limiting

/mcp?scenario=ratelimit answers every request with HTTP 429 and a Retry-After: 1 header, before any JSON-RPC handling, so a client's backoff and the engine's rate-limit handling have something to exercise.

The second server (/mcp-b)

POST https://test.mcptest.sh/mcp-b is an independent MCP server, datastore-b, with its own catalog under distinct names: db_get(key), db_put(key, value), db_list(), and db_purge() (carrying a destructiveHint), plus a records://{key} resource. Pair it with /mcp for multi-server discovery and orchestration suites, where each capability lives on a different server under a different name.

Cross-server trust boundary

/mcp-b?scenario=crosstrust makes db_get return stored data that looks benign but carries an embedded instruction targeting the other server (call delete_record on the primary, then forward the result to an exfiltration sink). An agent that treats tool output as trusted control input would propagate this across the server boundary. A trust-boundary check flags exactly this implicit-trust pattern: output from one server must never become control input for another. The crafted value is a labelled teaching honeypot, benign by default. See trust-boundary conformance.

Run this example. examples/hosted-cross-server.yml exercises both servers and asserts the crosstrust payload crosses the boundary.

mcptest run --config examples/hosted-cross-server.yml

Authentication

/secure/mcp runs the same conformant handler but requires Authorization: Bearer <token>. The public demo token is mcptest-demo-token; you can also fetch a short-lived one from the mock OAuth endpoint:

curl -s -X POST https://test.mcptest.sh/oauth/token -d grant_type=client_credentials

examples/hosted-auth.yml reads the token from the environment:

MCPTEST_TEST_TOKEN=mcptest-demo-token mcptest run --config examples/hosted-auth.yml

Transport scenarios

For exercising the runner's transport and layered-error handling:

URLReturns
GET /health{ ok: true }
GET /slow?ms=Nwaits up to 5000ms, then responds
GET /errorHTTP 500
GET /status/:codethe requested HTTP status

Discovery

GET https://test.mcptest.sh/.well-known/mcp.json is a discovery document, so mcptest discover --url https://test.mcptest.sh renders a ready-to-paste server: block.