← Field Notes · August 14, 2026 · 8 min read · AIOProductOS Team

MCP Inspector: How to Test an MCP Server You Did Not Write

MCP Inspector shows a server's tool surface with no model in the way. An ordered procedure for evaluating a server you did not write, ending in a verdict.

Someone hands you an MCP server. A vendor's remote endpoint, or an open-source one they found on a directory, and the ask is whether the team can point it at the company workspace. You have an afternoon.

Most of page one for this query is written for the person who wrote the server: a test pyramid, unit tests around your own tool handlers, fixtures, a CI story. Good advice, and none of it available to you, because you do not own the code and are not going to read all of it. What you need is an evaluation: a short ordered sequence that ends in a verdict.

How do you test an MCP server you did not write?

You evaluate its surface rather than its code. Enumerate every tool, sort them into reads and writes, connect against a workspace you can throw away, call one tool correctly and one deliberately wrong, and check what trace the calls left behind. Six checks, in that order, ending in a yes or a no.

How to test an MCP server you did not write: six ordered checks and what a pass looks like at each step

The procedure, in order

Each row produces a verdict about one thing. Run them in sequence, because a failure early makes everything below it untestable.

#What you checkHow you check itA pass looks like
1The tool surfaceConnect in a scratch client profile and list the tools. Count them, then read every name and descriptionEach name is distinguishable from every other one, and each description says when to call it, not just what it does
2Reads versus writesSort the list into read, write, and destructive by name and input schema. Write the three counts downThe read set alone covers the job you actually wanted. Nothing is ambiguous enough that you had to guess which pile it belongs in
3Blast radiusPoint it at a seeded demo account or a throwaway workspace, never at production, for the whole evaluationThe workspace is one you would delete without asking anyone's permission
4A successful callAsk one real question in your own words, the way a colleague would phrase itTyped records with ids, units and currency, not a paragraph of prose the model has to re-parse
5A failed callCall with a malformed id, an empty filter, and one request you should not be entitled toThree distinct, legible errors. No stack trace, no other tenant's rows, no silent empty success
6The trailAfter the calls, go looking for the record of them: a server-side log, an audit view, or an identity toolSomeone other than the person who made the calls can reconstruct who called what

1. Enumerate before you connect anything real

The first artifact is a list, and you write it down. Connect the server in a scratch client profile, ask for the tool list, and read it end to end. This is the one step where a dedicated inspector beats a chat client, because it shows you the raw surface without a model standing between you and it.

MCP Inspector is the usual choice here, and it is the official one. npx @modelcontextprotocol/inspector connects to the server the way a client would and gives you every tool, resource and prompt it exposes, a form for calling each one by hand, and the raw JSON-RPC traffic underneath. Nothing is choosing tools on your behalf, which is exactly the property you want while you are still deciding whether to trust the thing.

Two things fall out immediately. The count tells you what you are adding to every future conversation, and the names tell you whether a model will pick correctly under pressure. Names like search and query sitting next to each other are a retrieval failure waiting to happen. Descriptions that explain the endpoint rather than the situation ("returns account objects") will get called at the wrong moment.

Count the tools yourself rather than trusting a number in a README or a vendor benchmark. The list comes from the protocol; the README comes from marketing.

2. Sort reads from writes, on paper

Take the list and split it into three piles: reads, writes, and anything that deletes or is irreversible. Do this by hand, from the names and the input schemas, before you connect to anything you care about.

The pile sizes are the finding. If the read set alone does the job you were asked to enable, you have just discovered that the write half is optional, and optional access is access you decline in week one. If a tool is ambiguous enough that you cannot place it, that ambiguity is the model's problem too, and it is a mark against the surface.

This is also the point where a server's honesty is cheapest to check. A server that claims a read-only mode should have a read-only tool list to show for it, not a promise in the docs.

3. Run it against something you can throw away

Everything from here on is live calling, so it happens somewhere disposable. A vendor's own seeded demo workspace is ideal, because it is populated enough for the answers to be meaningful and belongs to nobody. Failing that, a scratch project you created this morning.

The rule is blunt: for the whole evaluation, the data on the other end is data you would delete without asking. Whether the server eventually deserves production data is the trust decision, and that has its own procedure. This step exists so the evaluation itself is free.

Worked example, since ours is built to be checked this way. Run npx -y @aioproductoscom/mcp@latest with no PRODUCTOS_TOKEN set, and the stdio server starts in demo mode against a fully seeded showcase workspace with a read-only subset of the tools. No account, no credentials, no signup. What you should get back is a tool list from the protocol itself and typed records from the first call, and what you should not get back is a successful write, because those tools are not on a tokenless surface.

4. Ask one real question, then read the shape of the answer

Now make one call, phrased the way a teammate would phrase it rather than the way the schema is written. What you are grading is not whether it answered. It is what came back.

Structured records with ids let you make a second call. Units and currency let a model do arithmetic without inventing a denomination. An explicit empty result ("no accounts matched, 0 of 412 scanned") stops the model from filling the silence with a plausible explanation. Prose does none of that, and a server that answers in prose will quietly degrade every conversation it is attached to.

Watch the size too. A tool that dumps several thousand rows into the context window has spent the budget the model needed for reasoning. If the description does not mention pagination, assume there is none.

5. Break it on purpose

This is the step nobody runs, and it is the one that separates a careful server from a careless one. Make three calls you expect to fail: a malformed or non-existent id, a filter that matches nothing, and something you should not be entitled to.

You are looking for three different errors, each of which tells you something. A not-found should say not found, not return an empty list that reads as a legitimate zero. A permission denial should say denied rather than returning someone else's rows. And none of the three should hand back a stack trace, a raw database error, or a fragment of another tenant's data, because a model will happily read all of that back to whoever is in the conversation.

A server that returns the same vague failure for all three has told you it does not distinguish between them internally either. If the calls do not go through at all, that is a connection problem rather than a quality one, and the five-layer diagnosis is a different job from this one.

6. Ask what it left behind

Last check, and the one that gets asked after an incident rather than before one: go looking for the record of the calls you just made.

For a hosted server, that means a server-side log or an audit view, and the question is whether an administrator who was not in the conversation can reconstruct who called what. If the server exposes an identity or whoami tool, call it, because "which account was that" is often the whole answer. For a local server running as a subprocess on one laptop, the honest finding is usually that there is no trail that outlives the process, which is a real property of that architecture rather than a bug, and it is covered in what a local server costs at team scale.

Write the answer down either way. "Nowhere" is a legitimate result; it just means this server does not get production data.

When this procedure is overkill

Three cases where running all six checks is the wrong use of an afternoon.

The server is local-only and touches nothing shared. A filesystem server, a browser driver, a device on your desk. There is no tenancy to isolate and no audit trail to demand, because the blast radius is one laptop that is already logged into everything. Read the source or pin the version, and skip the rest.

You wrote it. Then page one is right and this post is not for you. Unit-test the handlers, add fixtures, wire it into CI. The reason the procedure above exists is precisely that none of those options are on the table for code you did not write.

You are comparing five servers rather than approving one. Full evaluation is too slow at that width. Run steps 1 and 2 on all of them, which is cheap, and only take the shortlist through the live calls. Surveying what is out there first is a different task, and the roundup is the faster start.

The procedure is deliberately mechanical because the alternative is a vibe. Enumerate, sort, sandbox, call, break, trace, decide. If you want to run it against a production surface where every tool is documented before you connect, ours is listed tool by tool, on flat tiers with no per-seat metering.

Frequently asked questions

What is MCP Inspector?

MCP Inspector is the official developer tool for the Model Context Protocol, run with npx @modelcontextprotocol/inspector. It connects to a server the way a client would and gives you a browser UI listing that server's tools, resources and prompts, a form for calling each one by hand, and a view of the raw JSON-RPC traffic underneath. For evaluating a server someone else wrote, its value is that it shows you the entire surface and every response shape with no AI model in the loop deciding what to call.

How do I know if an MCP server is working?

Working means three things in sequence, and most people check only the first. The client lists its tools; a read call returns typed records rather than a sentence; and a deliberately bad call returns a legible error instead of an empty success. A server that lists tools and then answers everything with prose is connected, not working. If the tool list never appears at all, that is a connection fault rather than a quality one, and it is diagnosed differently.

How do you test MCP tools?

Call each one directly, before letting a model choose for you. Sort the surface into reads and writes, run only the reads against a workspace you can throw away, and pass each tool one valid input, one malformed id, and one request you should not have permission for. What you are grading is the return shape: typed records carrying ids and units on success, and distinct, non-leaking errors on failure. Only after that do you hand the same questions to a model in plain language.

Don't take our word for it

Reading this with an AI assistant? Let it check us.

AIOProductOS is an MCP server, so an assistant can connect to it directly - with no account, no card and no signup. It starts against a fully seeded showcase workspace, read-only, and there is nothing to cancel afterwards.

$ npx -y @aioproductoscom/mcp@latest

Then ask it the kind of question this post is about - "which paying customers asked for the feature we're building, and did shipping it move their usage?" - against a real joined record instead of a blog post. When you want it pointed at your own data, start here.

Keep reading

See the join on your own stack.

One record per customer - revenue, feedback, work, and code. Flat plans from $199/mo, every module included - a 14-day onboarding runway on your own data, then a 30-day money-back guarantee.