Skip to main content

pytest for MCP servers — the testing framework for the Model Context Protocol

Project description

pytest-mcp-plugin

pytest for MCP servers — the testing framework for the Model Context Protocol.

PyPI Python License: MIT

pip install pytest-mcp-plugin
mcp-test demo            # runs a bundled MCP server + tests in 5 seconds

Note on the name. This package is published on PyPI as pytest-mcp-plugin. The mcp-test name on PyPI is reserved by Anthropic for their official MCP SDK, and PyPI's name-similarity policy blocks close variants like mcptest. The CLI binary is still mcp-test, and the Python module is still mcp_test.


Why

MCP (Model Context Protocol) is the standard interface every AI agent now uses to talk to tools, files, databases, and APIs. Thousands of teams are shipping MCP servers in 2026. Almost none of them are tested.

pytest-mcp-plugin fixes that. Write tests for your MCP tools, resources, and prompts with the same developer experience you expect from pytest.

  • pytest plugin with auto-registered fixtures
  • stdio and HTTP/SSE transports
  • Schema validation, snapshot testing, coverage reports
  • Auth + policy assertions
  • Drop-in GitHub Action

60-second tour

pip install pytest-mcp-plugin
mcp-test demo

That spins up a bundled MCP server and runs a real test suite against it — no setup, no API keys, no servers to write first.

🚀 mcp-test demo
   server  : python -m mcp_test._demo_server
   workdir : /tmp/mcptest-demo-xxxx

test_demo.py::test_lists_tools         PASSED
test_demo.py::test_echo                PASSED
test_demo.py::test_add                 PASSED
test_demo.py::test_uppercase           PASSED
test_demo.py::test_fail_returns_error  PASSED

✅ Demo passed. Now write tests for your own MCP server:
   mcp-test init

Test your own server

cd my-mcp-server/
mcp-test init
pytest --mcp-command "python my_server.py" -v

Or pin the command in your pyproject.toml:

[tool.mcp-test]
command = "python my_server.py"
timeout = 10

…and just run:

mcp-test run

Write tests

# tests/test_my_server.py
from mcp_test import assert_tool_ok, assert_tool_error, assert_tool_text_contains


def test_search_returns_results(mcp_client):
    result = mcp_client.call_tool("search", query="machine learning")
    assert_tool_ok(result)
    assert len(result.content) > 0


def test_search_handles_empty_query(mcp_client):
    result = mcp_client.call_tool("search", query="")
    assert_tool_error(result)


def test_search_schema(mcp_client):
    tools = mcp_client.list_tools()
    search = tools.find("search")
    assert search.required == ["query"]
    assert search.properties["query"]["type"] == "string"

Use as a library

from mcp_test import MCPTestClient

with MCPTestClient.from_command("python my_server.py") as client:
    tools = client.list_tools()
    print(tools.names())

    result = client.call_tool("echo", message="hello")
    print(result.text())

Run on every PR (GitHub Action)

pytest-mcp-plugin ships as a composite action you can drop into any repo:

# .github/workflows/mcp-tests.yml
name: MCP Tests

on:
  pull_request:
  push:
    branches: [main]

jobs:
  mcp-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: yagna-1/mcp-test@v0.2.0
        with:
          command: "python my_server.py"
          test-dir: "tests"

That's it. The action installs pytest-mcp-plugin, runs your suite against your MCP server, and posts a JUnit XML report.


CLI reference

Command Description
mcp-test demo Run the bundled demo server + tests (zero setup)
mcp-test init Scaffold tests/ with example MCP tests
mcp-test run -c "python server.py" Run pytest against your server
mcp-test snapshot -c "..." Run snapshot tests (--update to refresh)
mcp-test coverage -c "..." Print coverage report (tools/prompts/resources)
mcp-test validate -c "..." Validate tool input schemas

All commands accept --help for full options.


Fixtures

The pytest plugin auto-registers three fixtures:

Fixture Scope Use for
mcp_client session Fast — one server process for the whole test run
mcp_client_fresh function Clean state per test
sandboxed_client function Fresh server with cwd=tmp_path and DATA_DIR=tmp_path
snapshot function Snapshot testing helper
pytest --mcp-command "python my_server.py" --mcp-timeout 15

Spec-version markers

Mark tests by required MCP spec version; the plugin auto-skips tests against older servers.

import pytest

@pytest.mark.mcp_v3  # requires spec >= 2025-06-18
def test_uses_recent_feature(mcp_client):
    ...

Available markers: mcp_v2, mcp_v3, mcp_v4.

Assertion helpers

from mcp_test import (
    assert_tool_ok,
    assert_tool_error,
    assert_tool_error_code,
    assert_tool_text_contains,
    assert_tool_text_equals,
    assert_tool_content_count,
    assert_policy_allows,
    assert_policy_blocks,
    assert_task_completes_within,
    assert_task_cancelled,
    assert_task_failed,
)

Architecture

pytest-mcp-plugin runs your MCP server as a subprocess and speaks JSON-RPC 2.0 over stdio (or HTTP/SSE for the HTTP transport). A background message pump handles response routing, notification dispatching, and concurrent request support — so your tests just work.

Source modules:

mcp_test/
  client.py            # stdio JSON-RPC client
  http_client.py       # HTTP + SSE client
  plugin.py            # pytest plugin (fixtures, options, markers)
  cli.py               # mcp-test CLI
  assertions.py        # assert_tool_*, assert_policy_*, assert_task_*
  schema_validator.py  # JSON Schema validation for tool inputs
  coverage.py          # tools/prompts/resources coverage tracker
  snapshot.py          # snapshot testing
  auth.py              # OAuth / PKCE / RFC 9728 helpers
  pagination.py        # cursor pagination helpers
  types.py             # ToolResult, ToolSchema, MCPError, ...
  _demo_server.py      # bundled demo server (used by `mcp-test demo`)

Status

pytest-mcp-plugin is beta. The CLI surface and plugin API are stable; minor internals (schema validator details, snapshot format) may still change.

Contributing

Bug reports, feature requests, and PRs welcome at github.com/yagna-1/mcp-test.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pytest_mcp_plugin-0.2.0.tar.gz (53.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pytest_mcp_plugin-0.2.0-py3-none-any.whl (37.9 kB view details)

Uploaded Python 3

File details

Details for the file pytest_mcp_plugin-0.2.0.tar.gz.

File metadata

  • Download URL: pytest_mcp_plugin-0.2.0.tar.gz
  • Upload date:
  • Size: 53.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for pytest_mcp_plugin-0.2.0.tar.gz
Algorithm Hash digest
SHA256 76712c1a059aa58adf96e4424aef3d8660a32433b2a49c45180500020c8eae87
MD5 843397c2d3022110497a2f05f63ebe98
BLAKE2b-256 4beae436fad24d53ddd24a11fe142013b51092e5ba5ec93b4d4d135c695ad517

See more details on using hashes here.

File details

Details for the file pytest_mcp_plugin-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for pytest_mcp_plugin-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3ad6e6c598b7ad5ed7989a4aa25abcd31d0fb4350c37ab9e3f33d61836e454a0
MD5 37032ca436dec6438aca436c0f307933
BLAKE2b-256 63ab974d8a03f10524017bd3a342652e053b6bd2193080eb9f43d1f05fd8eeaa

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page