Deploy and review
Run the final test matrix
Test discovery and representative success, validation, absence, security, and transport cases across local and remote servers.
Unit tests can check that the search filter works. They can’t check that a real client, over a real transport, gets what the contract promises. For that we need contract tests: calls made through the protocol, with recorded arguments and results.
We’ve been collecting rows in TESTING.md since the first Inspector session. Let’s complete them.
The matrix
Add this table and fill in every row:
| Area | Test | Expected |
|---|---|---|
| Discovery | List tools, resources, prompts | 2 tools, 1 resource, 1 prompt |
| Search | Query deploy | One matching note |
| Validation | Empty query | Rejected before handler |
| Lookup | Unknown ID | Clear error result |
| Resource | Read notes://catalog | Valid JSON catalog |
| Prompt | Render topic deploy | One review message |
| Boundary | Request hidden/local data | No capability exposes it |
| Transport | Repeat locally and remotely | Equivalent capability results |
| Protocol | Record negotiated revision | Expected modern or legacy era |
| Output | Compare text and structured data | Same successful payload |
| Injection | Read hostile practice note | Returned only as note data |
| HTTP path | Request a different route | 404 |
| Authorization | Missing, invalid, wrong-scope token | 401, 401, 403 |
The Boundary row is the odd one: try to get something the server shouldn’t have, like a file path or an environment variable. No capability exposes it, so every attempt should fail.
Be honest about the authorization row
The last row only applies when the endpoint is protected. For a public practice-data deployment, write “not implemented: public demo”. A matrix that pretends is worse than none, because people trust it.
Run it three times
Run the table against stdio, then local HTTP, then the deployed endpoint. Record exact arguments and results. “Works” is not a result. {"results":[{"id":"deploy-checklist",...}]} is.
After any transport change, rerun the negative rows too. The success path can keep passing while the error path is broken. Drop .min(1) from a schema by accident and search still works, but an empty query now reaches the handler.
Write down the conditions
Record these next to the table, or the results can’t be reproduced:
- SDK and Inspector versions
- negotiated protocol revision
- commit or deployment version
- date and endpoint
- whether authorization was enabled
Screenshots are optional. The saved arguments and results are the evidence, and they diff cleanly when something changes.
Try this on your own server: pick the three rows most likely to fail and run only those, today.
Lesson completed