Thanks to visit codestin.com
Credit goes to github.com

Skip to content

test: add MCP protocol smoke test for the stdio transport#134

Open
yagna-1 wants to merge 2 commits into
qdrant:masterfrom
yagna-1:add-mcp-protocol-smoke-test
Open

test: add MCP protocol smoke test for the stdio transport#134
yagna-1 wants to merge 2 commits into
qdrant:masterfrom
yagna-1:add-mcp-protocol-smoke-test

Conversation

@yagna-1
Copy link
Copy Markdown

@yagna-1 yagna-1 commented May 5, 2026

What

Adds two end-to-end tests in tests/test_mcp_protocol.py that spawn mcp-server-qdrant --transport stdio as a real subprocess and exercise the JSON-RPC protocol over its stdin/stdout:

  • test_initialize_handshake_succeeds — server completes the MCP initialize handshake and advertises the tools capability.
  • test_documented_tools_are_listedqdrant-find and qdrant-store (both documented in the README) are returned by tools/list with valid object input schemas.

Why

The current suite covers settings, FastEmbed, and Qdrant integration in isolation, but nothing actually drives main.py end-to-end. A regression in the entry script, FastMCP API drift, or a wiring change in mcp.run() could ship without a single test failing. These tests close that gap.

I noticed this while reviewing Python MCP servers for conformance/issues/258 (Python/stdio support in Anthropic's official conformance suite). Once that lands, this file can grow into a proper conformance check; until then, the smoke test catches the obvious regressions for free.

How

  • One new file: tests/test_mcp_protocol.py (~70 lines, plus docstring).
  • One added dev dependency: pytest-mcp-plugin>=0.2.1 — a small pytest plugin that drives MCP servers over stdio/HTTP from inside the test runner.
  • Tests use pytest.importorskip(\"mcp_test\") and a pytestmark skip if mcp-server-qdrant isn't on PATH, so this file is safe in any environment, even before the dep is installed.

No production code changes. No new CI workflow.

Verified locally

```text
$ uv sync
$ uv run pytest tests/ -q
.......................... [100%]
26 passed in 34.26s
```

That's 24 existing tests + 2 new, ~25 s of which is FastEmbed loading models on first call. The MCP server runs in-memory via `QDRANT_LOCAL_PATH` — no network, no external Qdrant required.

Notes

  • Followed the repo's conventions: tests in tests/, env via monkeypatch, no asyncio (the plugin is sync; the existing asyncio_mode = "auto" is harmless).
  • Followed the repo's actions-pinning style by not touching workflows.
  • Happy to drop the new dev dep behind an extras group, switch to dependency-groups.dev, or split the dep change into its own commit if you'd prefer.

Disclosure: I'm the author of pytest-mcp-plugin (MIT, on PyPI). It's an Apache/MIT-compatible community library — not a vendored dependency. Repo: https://github.com/yagna-1/mcp-test.

Made with Cursor

Yagna Siva Sai Kumar and others added 2 commits May 5, 2026 15:45
Adds two end-to-end tests that spawn `mcp-server-qdrant --transport stdio`
as a real subprocess and exercise the JSON-RPC protocol:

- `test_initialize_handshake_succeeds`: verifies the server completes the
  MCP `initialize` handshake and advertises the `tools` capability.
- `test_documented_tools_are_listed`: verifies that the `qdrant-find` and
  `qdrant-store` tools (both documented in the README) are returned by
  `tools/list` and have valid object input schemas.

Today the test suite covers settings, FastEmbed, and Qdrant integration
in isolation, but never exercises the actual MCP entry point. A
regression in `main.py`, a FastMCP API drift, or a `mcp.run()` wiring
issue could ship without a single test failing. These tests close that
gap with no new infra: they run under the existing `uv run pytest`
command, take ~25 s on a cold start, use an in-memory Qdrant via
`QDRANT_LOCAL_PATH`, and require no network or external services.

Implementation uses `pytest-mcp-plugin`, a small pytest plugin that
drives MCP servers over stdio/HTTP from inside the test runner. The
plugin is added to `[tool.uv.dev-dependencies]`. Both tests
`importorskip` it and skip cleanly if the binary isn't on PATH, so this
file is safe in any environment.

Co-authored-by: Cursor <[email protected]>
0.2.3 fixes a handshake bug where the client did not send
notifications/initialized after initialize, which is required by the MCP
spec and enforced by FastMCP-backed servers. mcp-server-qdrant happens
to tolerate the omission (FastMCP 2.7.0 here is older), but the newer
release is more correct and the smoke test depends on the fix to assert
notifications/initialized appears in the wire trace.

Co-authored-by: Cursor <[email protected]>
@yagna-1
Copy link
Copy Markdown
Author

yagna-1 commented May 5, 2026

Heads-up: pytest-mcp-plugin v0.3.0 was just released. The >=0.2.3 pin in this PR will automatically pick it up; no changes needed here for the protocol smoke test.

If maintainers later want fuller coverage, v0.3.0 ships an opt-in DatabaseServerTests test pack with read-only-mutation and SQL-injection probes that fits Qdrant's tool surface — happy to add a follow-up PR using it if useful, but I don't want to scope-creep this one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant