Add qonto_org_summary, qonto_list_transactions, and qonto_cost_run_rate_hints MCP tools, all routed through CapabilityService with protocol="mcp" -- same PolicyEngine.decide() path as REST, same deny-reason vocabulary. Skip snapshot_bundle as an MCP tool (REST already covers the composite read; not a separate privilege). CapabilityService now threads protocol through _execute/_emit_audit instead of hardcoding "rest". cost_run_rate_hints gets its own service method since it's an independent policy capability, not only a snapshot sub-field. Actor identity reuses REST's X-Actor-* header convention via a shared auth.actor_claims_from_headers(), read from the MCP Context's request when present. Fixed streamable_http_path defaulting to "/mcp", which doubled to "/mcp/mcp" once mounted under the "/mcp" prefix. Verified end-to-end with the mcp SDK's streamablehttp_client against the live fixture-backed server: tool list, allow/deny paths, and X-Actor-ID flowing through to the audit log exactly like REST. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2.3 KiB
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 |
Why this exists; boundaries |
specs/ArchitectureBlueprint.md |
Architecture, phases, policy model |
research/2026-07-21-mcp-gateway-and-governed-domain-assistant.md |
External + internal research |
docs/operator-runbook.md |
How to run and verify Phase 1 |
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 in
progress: a streamable-HTTP MCP adapter is mounted at /mcp on the same
capability core and policy kernel as REST, with tools qonto_org_summary,
qonto_list_transactions, and qonto_cost_run_rate_hints. Client auth is
still the REST-style X-Actor-* header convention; real OIDC/workload auth,
the shared multi-harness client config snippet, and the finance-qonto-read
tool profile are not yet implemented.
Current verification:
PYTHONPATH=src ../state-hub/.venv/bin/python -m pytest→16 passedpython3 -m compileall src tests scripts../state-hub/.venv/bin/python scripts/smoke_rest_api.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 smoke path checks
both a 31-day recent snapshot and a 90-day recurring-cost snapshot.
Normal local workflow, when toolchain support exists:
make install-dev
make test
make run
Related
- OpenBao lane:
tenants/binky/qonto-api(ops-wardenbinky-qonto-api) - First pull / CostRunRate:
binky-controlBINKY-WP-0005