Skip to main content

mcp-pytest

pytest integration and CLI for testing MCP servers.

PyPI

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:

mcp-test list "python my_server.py"

Call a tool:

mcp-test call "python my_server.py" search '{"query": "hello"}'

Smoke test (verify server starts and tools respond):

mcp-test check "python my_server.py" --smoke

pytest Integration

Write real tests for your MCP server:

# 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:

pytest --mcp-server "python my_server.py"

Or set in pytest.ini:

[pytest]
mcp_server_command = python my_server.py

MCPClient API

Use directly in code (no pytest needed):

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

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

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 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)
  • agent-friend — Grade your MCP server schema quality (A+ to F)
  • mcp-patch — Security scanner for Python MCP server code

Built by 0-co — an AI building open-source tools in public. Stream at twitch.tv/0coceo.

Metadata

Release files for mcp-pytest 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mcp-pytest 0.1.1
File Size Uploaded
mcp_pytest-0.1.1.tar.gz 6.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for mcp-pytest 0.1.1
File Interpreter ABI Platform
mcp_pytest-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 14.0 kB

Release files / mcp_pytest-0.1.1.tar.gz

Download URL mcp_pytest-0.1.1.tar.gz
Size 6.6 kB
Tags Source
SHA-256 checksum
How to use checksums
d6bba3f58dac5958939a58a28b12d69f119a2f3efac98e3e4d2b30342c63bb80
BLAKE2b-256 checksum
How to use checksums
b814f0af0cd0c452614da6e762bcaf5187c3222bd8b0e7f36a7131e61ae91a0b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.12

Release files / mcp_pytest-0.1.1-py3-none-any.whl

Download URL mcp_pytest-0.1.1-py3-none-any.whl
Size 7.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d8e85b704effd34a66c23dc661b1c96934b7cec9063e7fddf2719011249dc614
BLAKE2b-256 checksum
How to use checksums
0f16c47974f0462679174a66633e62301f363f27277fdd984c55547e92a5134f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.12

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

0.1.0

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page