qonto-assistant/README.md
tegwick ad500121f4 QONTO-WP-0003-T07: close out Phase 2 MCP workplan
T01-T06 all done. Final end-to-end confirmation before closing: pytest ->
31 passed; both scripts/smoke_rest_api.py and scripts/smoke_mcp.py exit 0
against fixtures in the same run; compileall clean.

REST/MCP policy-outcome parity is proven by test, not just asserted:
test_policy_decision_identical_across_protocols (decide() never branches on
transport) plus test_audit_parity.py (identical audit shape for the same
capability call over both transports, allow and deny paths).

Workplan status -> finished. Closure note records what shipped, the three
known gaps carried forward (OIDC federation, header-based actor identity,
unregistered agent-harness profile), and the Phase 3 seed. README updated
to match.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-23 13:56:06 +02:00

71 lines
3.1 KiB
Markdown

# qonto-assistant
Policy-governed Qonto domain API and MCP assistant for Binky (and later
multi-tenant dogfood).
**One choke point for bank access across every coding agent and harness.**
Clients never hold the Qonto API key. v1 policy: **read for awareness only —
no spend, no volume-cost actions.**
## Start here
| Doc | What |
| --- | --- |
| [`INTENT.md`](INTENT.md) | Why this exists; boundaries |
| [`specs/ArchitectureBlueprint.md`](specs/ArchitectureBlueprint.md) | Architecture, phases, policy model |
| [`research/2026-07-21-mcp-gateway-and-governed-domain-assistant.md`](research/2026-07-21-mcp-gateway-and-governed-domain-assistant.md) | External + internal research |
| [`docs/operator-runbook.md`](docs/operator-runbook.md) | How to run and verify Phase 1 (REST) |
| [`docs/mcp-integration.md`](docs/mcp-integration.md) | How to run and verify Phase 2 (MCP) |
## Status
Phase 1 runtime is implemented:
- Python 3.12 service under `src/qonto_assistant/`
- default-deny YAML policy
- Qonto read-only client (`organization`, `transactions`)
- REST endpoints: `/v1/health`, `/v1/accounts`, `/v1/transactions`, `/v1/snapshot`
- audit metadata, rate limiting, concurrency bounds, tests
Phase 2 (MCP surface, `workplans/QONTO-WP-0003-mcp-surface.md`) is
**finished**: a streamable-HTTP MCP adapter is mounted at `/mcp` on the same
capability core and policy kernel as REST — proven identical by test, not
just by construction (`tests/test_policy.py`, `tests/test_audit_parity.py`)
— with tools `qonto_org_summary`, `qonto_list_transactions`, and
`qonto_cost_run_rate_hints`. The endpoint is gated by a shared-secret bearer
token (`QONTO_ASSISTANT_MCP_TOKEN`); see `docs/mcp-integration.md` for the
auth model, its explicit gap vs. the OIDC/workload target (no issuer exists
in this fleet yet), and the shared multi-harness client config snippet. The
`finance-qonto-read` agent-harness tool profile is documented (qonto-assistant
side) but not yet registered in `agent-harness` itself — separate repo,
separate workplan.
Current verification:
- `PYTHONPATH=src ../state-hub/.venv/bin/python -m pytest``31 passed`
- `python3 -m compileall src tests scripts`
- `../state-hub/.venv/bin/python scripts/smoke_rest_api.py --python ../state-hub/.venv/bin/python`
- `../state-hub/.venv/bin/python scripts/smoke_mcp.py --python ../state-hub/.venv/bin/python`
Local fixture-backed smoke mode is available through `QONTO_FIXTURE_DIR`, so the
service can be exercised without real Qonto credentials. The REST smoke checks
both a `31`-day recent snapshot and a `90`-day recurring-cost snapshot; the MCP
smoke additionally exercises the bearer-token auth gate and an out-of-catalog
tool deny path.
Phase 3 (flex-auth resource `finance.qonto.read`, graduated quotas,
redaction profiles) is not started — see `workplans/QONTO-WP-0003-mcp-surface.md`
closure notes for the seed.
Normal local workflow, when toolchain support exists:
```bash
make install-dev
make test
make run
```
## Related
- OpenBao lane: `tenants/binky/qonto-api` (ops-warden `binky-qonto-api`)
- First pull / CostRunRate: `binky-control` BINKY-WP-0005