Test an MCP server before you point an agent at it
An MCP server can look fine in your own code and still fail the first time a real client connects. The URL redirects, the path is wrong, the reply is a web page, or the tool list is technically valid and practically unusable because nothing in it explains what a tool is for. None of that shows up until something tries to use it.
This is a guide to what a client does when it connects, the ways that goes wrong, and how to write a tool list an agent can choose from.
What a client does on connect
Over the Streamable HTTP transport, a client does the same short sequence every time.
initialize. The client POSTs a JSON-RPC message with the protocol revision it wants and some information about itself. The server answers with the revision it will use, its name and version, the capabilities it supports, and optionally instructions for the model.notifications/initialized. The client tells the server it is ready. This is a notification, so there is no reply beyond an acknowledgement.tools/list. The client asks for the tools, and followsnextCursorif the list is paged.- Optionally
resources/listandprompts/list, if the server said it supports those.
If the server issues a session ID in a response header, the client sends it on every later request. If it does not, the server is stateless and each request stands alone. Stateless suits serverless hosting. Stateful servers need to be told when a session ends, which clients do with an HTTP DELETE.
The MCP Endpoint Inspector performs exactly this sequence against a public URL and shows you the result. It never calls a tool, only reads. When the inspector can read your server, a real client probably can.
The ways it fails
Most connection problems fall into a few buckets, and each has a distinct message.
The URL redirects. A request to http:// becomes a 301 or 308 to https://, or a missing trailing slash becomes a redirect. A redirect on a POST is handled inconsistently by clients, and some turn it into a GET, which then fails. Configure the final URL, not the one that redirects. This is a very common cause of "it works in my browser, not in my client".
HTTP 404. Nothing is served at that path. MCP servers are often mounted at /mcp, and the root of the site is usually a web page instead.
HTTP 405. The URL does not accept a POST. Either the path is wrong, or the server speaks the older HTTP plus SSE transport, where the client opens a stream first. Servers on that older transport need a different client setup than the Streamable HTTP one.
A web page instead of JSON-RPC. The server returned 200 with HTML, often a login page, a landing page, or a framework error page. The content type is the quick tell. The inspector reports the type and the first characters of the body so you can see what came back.
401 or 403. The server requires authentication. The inspector sends no credentials by design, so it reports this rather than looking inside. That is the correct outcome for a protected server. Test those from your own client, which can complete the login.
A JSON-RPC error on initialize. The server understood the request and refused it, often because it does not support the protocol revision the client asked for. The error message names it.
Unreachable. DNS fails, the host is down, or the TLS certificate is invalid or does not cover the name. If the certificate is the suspect, check it with the SSL checker.
The part people skip: the tool list is an interface for a model
A tool list is not documentation for a human. It is the entire basis on which a model decides which tool to call, with what arguments, and when. A model never sees your code, only the name, the description and the schema. That makes these three fields the most important thing in the server.
Names. Use letters, digits, underscores and hyphens, and keep them short and specific. dns_lookup tells a model more than query. Some clients reject or rewrite names outside that character set, and two tools with the same name make one of them unreachable.
Descriptions. Say what the tool does and when to use it, in a sentence or two. "Look up DNS records for a domain. Omit type to return every record type that exists, or pass a specific type" works because it says what it does and what the optional argument does. A tool with no description is rarely chosen, and a vague one is chosen at the wrong moment. Very long descriptions have a cost, because the whole list is sent to the model on every request.
Input schemas. The specification requires inputSchema to be a JSON Schema of type object. Describe each parameter, mark the required ones, and use enum where only certain values are valid. A model fills in a parameter far more reliably when the schema tells it the allowed values and what the field means. An undescribed parameter called q is a guess.
How many tools. A long list uses a lot of the model's context and makes selection less reliable. If you find yourself past a few dozen, consider whether some belong in a separate server or can be merged.
The inspector checks for these: tools with no description, duplicate or unusual names, input schemas that are not objects, parameters without descriptions, and unusually long descriptions or lists. It reports what it finds as notes and warnings, not as a verdict, because the right answer depends on your server.
Reading a result
Pointed at toolhq's own server, which has eight tools, the inspector reports protocol revision 2025-06-18, a stateless server, and a tool list where every tool is named, described, and takes an object schema. It also shows timing. A first request to a serverless host can take several seconds because the function has to start, while later requests are quicker. During testing the first initialize against the toolhq endpoint took about four seconds and warm requests took between one and two. Part of any measured time is connection setup, so read timings as a rough guide rather than a benchmark.
Before you ship
A short checklist:
- Run the inspector on the public URL, not just localhost.
- Fix redirects so the URL you publish is the final one.
- Give every tool a specific description and every parameter a meaning.
- Mark required parameters and use
enumfor fixed choices. - Keep the surface as small as the job allows. Tools are model controlled, so a server that cannot do much is the safest.
If you are new to the protocol, what MCP is and why an agent needs real network tools explains the roles and the transports. For a worked example of an agent using a server, see debugging DNS, SSL and mail with an AI agent, and for the wider picture, how toolhq helps you work with AI. The MCP page lists the toolhq server and how to connect to it.