Diagnose MCP client configs, local process startup, and stdio handshakes before tools fail to load.
Project description
mcp-server-doctor
Diagnose the MCP client-to-server boundary: configuration discovery, process launch, and the stdio JSON-RPC handshake that must succeed before tools can load.
mcp-server-doctor is a dependency-free Python CLI for people who configure local Model Context Protocol servers in Claude, Cursor, Copilot, VS Code, or another agent client and then see missing commands, hidden startup failures, or empty tool lists.
It statically checks client configuration and can launch a configured local stdio process to verify initialize, notifications/initialized, and advertised capability listing such as tools/list.
This is not a generic MCP server test client. It focuses on failures that happen before tool invocation: locating client config, resolving the executable and working directory, starting the process, preserving JSON-RPC stdout framing, and completing the stdio handshake.
Why This Exists
MCP adoption is moving quickly across AI coding tools, IDEs, and desktop assistants. The painful part is still local setup:
- Config files live in different places across clients.
npx,uvx, Docker, Python, and absolute-path commands fail differently.- A server can show as configured but still expose no tools.
- Tokens often get pasted into config files during troubleshooting.
- Server logs accidentally written to stdout can break JSON-RPC.
This tool gives developers and maintainers a fast preflight check for the exact boundary where an MCP client tries to start and discover a local server.
| In scope | Out of scope |
|---|---|
| Client config discovery and validation | Testing whether individual MCP tools are semantically correct |
| Command, package, environment, cwd, and shell-wrapper checks | Acting as an interactive MCP tool runner |
| Local process startup and stdio JSON-RPC framing | Dynamic testing of remote HTTP or OAuth transports |
| Initialize and advertised capability listing | Security approval for calling a discovered tool |
Install
Run without installing:
uvx mcp-server-doctor check .
Or install the isolated CLI:
pipx install mcp-server-doctor
For local development:
python -m pip install -e .
Standard pip installation:
python -m pip install mcp-server-doctor
Quick Start
Check the current repository for MCP config files:
mcp-server-doctor .
Check a specific config file:
mcp-server-doctor check ~/.cursor/mcp.json
Run static checks plus stdio startup probes:
mcp-server-doctor doctor ~/.cursor/mcp.json
Probe one server:
mcp-server-doctor doctor ~/.cursor/mcp.json --server filesystem
Return JSON for CI or editor integrations:
mcp-server-doctor doctor . --format json
Write SARIF for GitHub code scanning:
mcp-server-doctor check . --format sarif --output mcp-server-doctor.sarif
Short alias:
mcp-doctor doctor .
What It Checks
Static checks:
- Valid JSON
- Required
mcpServersobject - Local stdio server command, args, env, and cwd types
- Missing executable on
PATH - Missing absolute command path
- Missing or invalid cwd
- Literal token-like values in
envorargs - Secret-looking env values such as API keys and passwords
- Shell wrapper usage such as
bash -corpowershell -Command - Unpinned
npx,uvx, orbunxpackage names - Broad Docker volume mounts
- Remote MCP server configs, reported as static-check only
Dynamic stdio probe:
- Starts the configured command
- Sends
initialize - Sends
notifications/initialized - Lists tools when available
- Lists resources and prompts when advertised
- Detects non-JSON stdout before a protocol response
- Captures stderr tail on failures without exposing config secrets
Example
Given:
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
}
}
}
Run:
mcp-server-doctor check mcp.json
Output:
mcp-server-doctor checked 1 config file(s), 1 server(s)
errors=0 warnings=1 info=0
Configs:
- mcp.json
- filesystem (stdio)
Findings:
[warning] mcp.json#filesystem unpinned-package: npx package is not version-pinned: @modelcontextprotocol/server-filesystem
hint: Pin package versions for reproducible MCP startup.
Supported Config Locations
When no path is provided, the tool scans the current directory and common user-level locations when present:
mcp.json.mcp.json.cursor/mcp.json.vscode/mcp.json.github/copilot/mcp.json- Claude Desktop config on Windows, macOS, and Linux
Large generated folders such as .git, node_modules, dist, build, and virtual environments are skipped.
CI
Use the packaged GitHub Action:
name: MCP config check
on:
pull_request:
push:
branches:
- main
permissions:
contents: read
security-events: write
jobs:
mcp-doctor:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7.0.0
- uses: Uky0Yang/mcp-server-doctor@v0.2.0
with:
path: .
command: check
upload-results: "true"
warnings-as-errors: "true"
Or install the CLI directly:
name: MCP config check
on:
pull_request:
push:
branches:
- main
jobs:
mcp-doctor:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7.0.0
- uses: actions/setup-python@v6.3.0
with:
python-version: "3.12"
- run: python -m pip install mcp-server-doctor
- run: mcp-server-doctor check . --warnings-as-errors
Use check in CI unless your workflow intentionally installs and starts every configured MCP server.
PyPI Release
This repository is prepared for PyPI Trusted Publishing. Configure a pending publisher on PyPI with:
- Project:
mcp-server-doctor - Owner:
Uky0Yang - Repository:
mcp-server-doctor - Workflow:
release.yml - Environment:
pypi
Then publish with:
git tag v0.2.0
git push origin v0.2.0
See docs/publishing.md.
Exit Codes
0: no errors1: static check failed, or warnings failed under--warnings-as-errors2: static checks passed, but at least one stdio probe failed
Design Principles
- No model calls
- No network calls by the doctor itself
- No runtime dependencies
- No secret values printed
- Clear findings that point to a fix
- Dynamic probing limited to local stdio commands from the provided config
Current Limitations
- Streamable HTTP and OAuth flows are not dynamically probed yet.
- The stdio probe uses newline-delimited JSON-RPC, which is what common MCP SDK stdio transports use.
- The tool does not rewrite configs yet.
- It cannot know whether an MCP tool is safe to call; it only verifies discovery and startup.
Contributing
See CONTRIBUTING.md. Useful contributions are real-world diagnostics from broken MCP setups, additional client config locations, and tests for server startup edge cases.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mcp_server_doctor-0.2.0.tar.gz.
File metadata
- Download URL: mcp_server_doctor-0.2.0.tar.gz
- Upload date:
- Size: 19.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3c56a076369837a6cd9ac2b97a85fdd8024d2de3058c1b605b83b3a38304a7c2
|
|
| MD5 |
2b9840fc7ec6cf93d333d52385ab505f
|
|
| BLAKE2b-256 |
51e2a056b88717bb7ad4415b55c4638d09cea8c77424d8757013085c0ef4659d
|
Provenance
The following attestation bundles were made for mcp_server_doctor-0.2.0.tar.gz:
Publisher:
release.yml on Uky0Yang/mcp-server-doctor
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mcp_server_doctor-0.2.0.tar.gz -
Subject digest:
3c56a076369837a6cd9ac2b97a85fdd8024d2de3058c1b605b83b3a38304a7c2 - Sigstore transparency entry: 2170899772
- Sigstore integration time:
-
Permalink:
Uky0Yang/mcp-server-doctor@e75f585df93a393bbb9548b6a6621c5d7d5d591c -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/Uky0Yang
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@e75f585df93a393bbb9548b6a6621c5d7d5d591c -
Trigger Event:
push
-
Statement type:
File details
Details for the file mcp_server_doctor-0.2.0-py3-none-any.whl.
File metadata
- Download URL: mcp_server_doctor-0.2.0-py3-none-any.whl
- Upload date:
- Size: 18.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c50b585e3d3d781058e76a77c731492a056d3cb85478a22599833a829d69b358
|
|
| MD5 |
b76f35170ba3875fb6bba3ce1a935999
|
|
| BLAKE2b-256 |
9a8a2171c89c928b049b4b9eeccc99e484b607cefe0dea31f300885a6405cfa4
|
Provenance
The following attestation bundles were made for mcp_server_doctor-0.2.0-py3-none-any.whl:
Publisher:
release.yml on Uky0Yang/mcp-server-doctor
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mcp_server_doctor-0.2.0-py3-none-any.whl -
Subject digest:
c50b585e3d3d781058e76a77c731492a056d3cb85478a22599833a829d69b358 - Sigstore transparency entry: 2170899792
- Sigstore integration time:
-
Permalink:
Uky0Yang/mcp-server-doctor@e75f585df93a393bbb9548b6a6621c5d7d5d591c -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/Uky0Yang
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@e75f585df93a393bbb9548b6a6621c5d7d5d591c -
Trigger Event:
push
-
Statement type: