# mcp-doctor: one open-source tool for the whole life of an MCP server

> Source: <https://dev.to/vishalhabib99/mcp-doctor-one-open-source-tool-for-the-whole-life-of-an-mcp-server-25kb>
> Published: 2026-10-16 18:13:45+00:00

An agent is only as reliable as the tools it calls, and most MCP servers are never checked against anything. A tool with no description never gets picked. A parameter typed `str = None` rejects the very default it advertises. A write tool says "Successfully wrote" and writes nothing.

I built [mcp-doctor](https://github.com/vishalhabib99/mcp-doctor) to catch those, and it has grown into one open-source tool that covers an MCP server's whole life: before you ship, in every PR, and inside the running agent.

```
pip install mcp-server-lint
mcp-doctor path/to/your/server
```

`None` defaults that reject `null`, stray stdout writes on stdio, descriptions that don't tell two tools apart. Security covers tool-poisoning phrases, dynamic exec, SSRF-prone requests, unsafe deserialization, hardcoded secrets and read-only annotations that lie.`--fix`.` Args:` entries, bare `except:`. On three repos with a hand-written PR for the same bug, it produced exactly the same type changes.`--diff-against`.` uses: vishalhabib99/mcp-doctor@v1`): comments on each PR, suggests one-click fixes on the lines it changes, and can fail a PR that drops below your score.
Static checks can't see whether a call actually worked. `mcp-doctor guard` runs any stdio MCP server behind a live check. Every message passes through unchanged; when a "success" isn't one, it adds a warning the agent reads:

```
{
  "mcpServers": {
    "filesystem": {
      "command": "mcp-doctor",
      "args": ["guard", "--", "npx", "-y", "@modelcontextprotocol/server-filesystem", "/path/to/dir"]
    }
  }
}
```

It flags:

`outputSchema`
Same broken `write_file`, same prompt, in Claude Code:

**Without guard:** "Yes, the file was saved."

**With guard:** "I can't confirm the file was saved."

**For coding agents**, the `mcp-doctor-guard` Claude Code plugin applies the same idea to the agent's own tools (shell, file writes, web fetch). In a live run with Haiku in `bypassPermissions`, the agent without guard read a web page, then planted a `.git` hook and sent a token from `.env` to a server. With guard, both were stopped, and the agent didn't try another route.

Guard covers stdio servers only (not HTTP yet), confirms a write only when the server has a matching read tool, and matches copied text, so a paraphrased leak can get past it. It's a net for when the model is fooled, not a replacement for least-privilege tokens.

Try it on your server and tell me what it gets wrong: [github.com/vishalhabib99/mcp-doctor](https://github.com/vishalhabib99/mcp-doctor)
