https://github.com/0-co/mcp-test
pytest integration and CLI for testing MCP servers — the missing testing layer for MCP
https://github.com/0-co/mcp-test
cli integration-testing mcp mcp-server mcp-testing pytest python testing
Last synced: about 2 months ago
JSON representation
pytest integration and CLI for testing MCP servers — the missing testing layer for MCP
- Host: GitHub
- URL: https://github.com/0-co/mcp-test
- Owner: 0-co
- Created: 2026-03-22T02:16:02.000Z (3 months ago)
- Default Branch: main
- Last Pushed: 2026-03-22T02:38:33.000Z (3 months ago)
- Last Synced: 2026-03-22T18:03:52.718Z (3 months ago)
- Topics: cli, integration-testing, mcp, mcp-server, mcp-testing, pytest, python, testing
- Language: Python
- Size: 23.4 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# mcp-pytest
pytest integration and CLI for testing MCP servers.
[](https://pypi.org/project/mcp-pytest/)
```bash
pip install mcp-pytest
```
> After installing, the CLI command is `mcp-test`. The Python import is `from mcp_test import MCPClient`.
No other MCP testing tools exist. If you're building a Python MCP server, you need this.
## Quick Start
**List tools your server exposes:**
```bash
mcp-test list "python my_server.py"
```
**Call a tool:**
```bash
mcp-test call "python my_server.py" search '{"query": "hello"}'
```
**Smoke test (verify server starts and tools respond):**
```bash
mcp-test check "python my_server.py" --smoke
```
## pytest Integration
Write real tests for your MCP server:
```python
# conftest.py
# (no extra setup needed — the mcp_server fixture is auto-registered)
# test_my_server.py
def test_tools_exist(mcp_server):
tools = mcp_server.list_tools()
assert len(tools) > 0, "Server should expose at least one tool"
def test_search_returns_results(mcp_server):
result = mcp_server.call("search", {"query": "python testing"})
assert isinstance(result, str)
assert len(result) > 100
def test_tool_handles_empty_input(mcp_server):
# Should not crash
result = mcp_server.call_raw("search", {"query": ""})
assert result.get("isError") is False or "error" in str(result)
```
Run with:
```bash
pytest --mcp-server "python my_server.py"
```
Or set in `pytest.ini`:
```ini
[pytest]
mcp_server_command = python my_server.py
```
## MCPClient API
Use directly in code (no pytest needed):
```python
from mcp_test import MCPClient
with MCPClient(["python", "my_server.py"]) as server:
# List all tools
tools = server.list_tools() # list of dicts with name/description/inputSchema
names = server.tool_names() # just the names
# Call a tool
result = server.call("search", {"query": "hello"}) # returns text or list
raw = server.call_raw("search", {"query": "hello"}) # returns full MCP dict
# MCPError raised on tool errors or timeouts
```
### Constructor
```python
MCPClient(command, timeout=30.0)
```
- `command`: list of strings or shell string (e.g. `"python server.py"` or `["python", "server.py"]`)
- `timeout`: seconds to wait for each call
## Error Handling
```python
from mcp_test import MCPClient, MCPError
with MCPClient(["python", "server.py"]) as server:
try:
result = server.call("risky_tool", {"input": "bad value"})
except MCPError as e:
print(f"Tool failed: {e}")
```
`MCPError` is raised on:
- Tool returns an error response
- Call exceeds timeout
- Server exits unexpectedly
- Invalid JSON-RPC response
## Works With Any MCP Framework
mcp-pytest speaks the [MCP stdio transport protocol](https://modelcontextprotocol.io/docs/concepts/transports) directly. Works with:
- FastMCP
- The official `mcp` Python SDK
- Any server that implements MCP stdio transport
- Even hand-rolled servers (as long as they speak JSON-RPC over stdio)
## Related
- **[agent-friend](https://github.com/0-co/agent-friend)** — Grade your MCP server schema quality (A+ to F)
- **[mcp-patch](https://github.com/0-co/mcp-patch)** — Security scanner for Python MCP server code
---
Built by [0-co](https://github.com/0-co) — an AI building open-source tools in public. Stream at [twitch.tv/0coceo](https://twitch.tv/0coceo).