QONTO-WP-0003-T06: MCP smoke script + operator runbook update

Add scripts/smoke_mcp.py, same shape as smoke_rest_api.py (random port,
subprocess-launch against QONTO_FIXTURE_DIR, wait on /v1/health, assert,
clean teardown), but goes further: generates a fresh
QONTO_ASSISTANT_MCP_TOKEN per run and connects through it with the mcp
SDK's streamablehttp_client, so the smoke exercises T03's bearer-token gate
instead of bypassing it. Lists tools, calls all four, and confirms an
out-of-catalog tool name comes back as a normal isError result through the
real wire protocol rather than a crash.

Extend docs/operator-runbook.md with a "One-command MCP smoke" section next
to the REST one; cross-link from docs/mcp-integration.md's manual smoke
walkthrough so the two don't drift.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
tegwick 2026-07-23 11:04:39 +02:00
parent c1e33decd9
commit 0dc001bf53
4 changed files with 208 additions and 1 deletions

View file

@ -256,7 +256,7 @@ write exists to accidentally wire up. `pytest` → `31 passed`.
```task
id: QONTO-WP-0003-T06
status: todo
status: done
priority: medium
state_hub_task_id: "1093ec79-eb16-4797-8c9c-5423a925db77"
```
@ -270,6 +270,31 @@ alongside the existing REST section.
Done when: smoke script passes locally against fixtures without real Qonto
credentials, matching the Phase 1 REST smoke pattern.
**Done 2026-07-23:** Added `scripts/smoke_mcp.py`, same shape as
`scripts/smoke_rest_api.py` (random free port, subprocess-launch the
service against `QONTO_FIXTURE_DIR`, wait on `/v1/health`, assert, tear
down cleanly). Goes one step further than the REST smoke since MCP now has
an auth layer REST doesn't: generates a fresh `QONTO_ASSISTANT_MCP_TOKEN`
per run and connects with the `mcp` SDK's `streamablehttp_client` using it,
so the smoke exercises T03's bearer-token gate rather than bypassing it.
Lists tools and asserts the exact expected catalog; calls `qonto_ping`,
`qonto_org_summary`, `qonto_list_transactions`, and
`qonto_cost_run_rate_hints` against fixture data with the same balance/
recurring-debit assertions the REST smoke makes; calls a never-registered
tool name (`qonto_transfer_funds`) and asserts it comes back as a normal
`isError` result through the real wire protocol, not a crash — confirming
the low-level MCP protocol handler rejects unknown tools cleanly rather
than falling through to anything policy-adjacent.
Extended `docs/operator-runbook.md` with a "One-command MCP smoke" section
next to the existing REST one, and cross-linked it from
`docs/mcp-integration.md`'s manual smoke walkthrough so the two don't drift
out of sync.
Verified: `python3 scripts/smoke_mcp.py --python ../state-hub/.venv/bin/python`
exits `0` against fixtures, no real Qonto credentials. `pytest``31 passed`
(unchanged); `python3 -m compileall src tests scripts`.
## Task: Closure review
```task