qonto-assistant/research/2026-07-21-mcp-gateway-and-governed-domain-assistant.md
tegwick e1ab23f83e Bootstrap qonto-assistant: intent, blueprint, research, workplans
Author INTENT and SCOPE; persist ArchitectureBlueprint under specs/ and MCP
gateway research under research/. Register with State Hub (QONTO-WP- prefix);
seed QONTO-WP-0001 (bootstrap, finished) and QONTO-WP-0002 (Phase 1 REST
policy kernel, ready).
2026-07-21 23:32:24 +02:00

172 lines
7.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Research: MCP gateways and governed domain assistants for bank access
> Date: 2026-07-21
> Purpose: Capture external and internal research that informed
> `specs/ArchitectureBlueprint.md` and `INTENT.md`.
> Not a product spec — evidence and pattern notes.
---
## 1. Question under investigation
How should multiple coding agents and harnesses interact with Qonto
**conveniently and under one policy**, without wiring vendor MCP into each
client (policy drift) and without relying on Qonto to enforce
read-only / no-spend rules at the API key layer?
---
## 2. Internal facts already established (BINKY-WP-0005)
| Fact | Evidence |
| --- | --- |
| Credentials live at `tenants/binky/qonto-api` | OpenBao; fields `API_KEY`, `API_USER` |
| Thirdparty REST works | First pull 2026-07-21; 122 txs; CostRunRate v2 |
| Auth shape | `Authorization: <API_USER>:<API_KEY>` |
| Self-hosted MCP env map | `API_KEY``QONTO_API_KEY`, `API_USER``QONTO_ORGANIZATION_ID` |
| API keys not scope-limited | Design note in binky-control `integrations/qonto-mcp.md` |
| Hosted OAuth MCP rejected | Corporate access policy: no native connector custody |
| Catalog / CCR | ops-warden `binky-qonto-api` active; CCR-2026-0008 active |
| Founder policy intent | No spend / no volume-cost actions for agents; payments Red lane |
---
## 3. External pattern research (20252026 MCP ecosystem)
### 3.1 MCP gateway / proxy as control plane
Industry deployments place a **gateway between untrusted MCP clients and
tools**:
| Source | Relevant capability |
| --- | --- |
| **Envoy AI Gateway MCPRoute** | Multiplex backends; `toolSelector` include/regex; upstream API-key injection so clients never hold vendor secrets; OAuth on gateway; CEL on `tools/call` params (`request.mcp.tool`, `request.mcp.params`) |
| **Kong AI Gateway MCP Tool ACLs** | Default-deny; per-consumer tool subsets at gateway (solves all-or-nothing MCP) |
| **Portkey / Speakeasy / Permit MCP Gateway** framing | Authn, RBAC, audit every tool call; policy on each call not only at connect time |
| **Harness MCP server docs** | Compatible with MCP gateways: centralized credentials, governance, audit, single endpoint |
**Lesson:** Clients connect to one governed endpoint; the gateway owns
credentials, published tool inventory, and policy.
### 3.2 MCP security best practices
Synthesized from MCP security best-practice docs and industry guides
(confused-deputy / token passthrough / OAuth proxy guidance):
| Practice | Application |
| --- | --- |
| No token passthrough | Clients must not present the bank key; assistant is sole Qonto client |
| Tool-level scopes | “Access to Qonto” too coarse; allow list_transactions, never create_transfer |
| Default deny | Unknown tools fail closed |
| JIT escalation for high privilege | Future spend only with explicit re-auth; never session-global write mode |
| Audit end-to-end | Actor + tool + decision; no secrets in logs |
| Inventory of MCP servers | Fleet must know what is connected (anti shadow-MCP) |
### 3.3 Gateway vs domain assistant
| Approach | Strength | Weakness for bank access |
| --- | --- | --- |
| Generic MCP gateway in front of **vendor** MCP | Fast tool filtering | Vendor catalog still includes write tools; weak **semantic** spend rules; unmaintained self-hosted Qonto MCP |
| **Domain assistant** (own MCP + REST, policy inside) | Safe catalog we design; dual protocol; productizable | Build cost |
| Per-client allow-lists only | Zero new service | Guaranteed policy drift |
**Conclusion adopted in blueprint:** build domain assistant; treat generic
gateways as optional later mesh in front of *our* service, not as sole
control in front of vendor MCP.
### 3.4 Anchoring policy at Qonto (API / MCP)
**Not available** for the chosen custody model:
- Self-hosted API keys: no fine-grained scopes from Qonto.
- Hosted OAuth MCP: write tools + credentials outside OpenBao = rejected
by corporate access policy.
Defense-in-depth still belongs in our choke point even if Qonto later adds
scopes.
---
## 4. Internal platform fit
| Component | Boundary (from INTENT/ADR) | Role for Qonto access |
| --- | --- | --- |
| **agent-harness** | Sole session credential holder / policy shell for *sessions*; not domain logic | Grant profile pointing at qonto-assistant only |
| **llm-connect** | Multi-provider LLM adapters | Models only — not bank tools |
| **flex-auth** | Authorization from identity claims | `finance.qonto.read` (etc.) |
| **OpenBao + ops-warden** | Custody + routing | Existing `binky-qonto-api` lane |
| **email-connect** | Purpose-built connector | Sibling pattern to copy |
| **binky-control** | Company brain / AutonomyPolicy | Policy source + CostRunRate consumer |
| **activity-core** | Schedule, not execute | When Finance Steward runs |
ADR-001 (agent-harness) implies: instances declare profiles; harness
enforces. Domain bank rules must live **below** the harness so interactive
IDE agents and unattended sessions share one policy.
---
## 5. Founder constraints captured in research session
1. Multiple coding agents and harnesses already in use; agent-harness +
llm-connect exist.
2. Desired policy: **no spending**, **no actions with volume cost**.
3. Direct per-harness MCP wiring is suboptimal (policy drift).
4. Preference to explore **qonto-proxy / governed API+MCP service**.
5. Interest in known agentic patterns — research above.
---
## 6. Architectural recommendation (outcome)
See `specs/ArchitectureBlueprint.md` in full. Summary:
```text
Many harnesses
→ authenticate to qonto-assistant (MCP and/or REST)
→ policy kernel (default-deny, no spend / no volume-cost)
→ sole OpenBao consumer of tenants/.../qonto-api
→ Qonto thirdparty API
```
Phased delivery:
0. Custody + first REST pull (done in binky-control)
1. Policy kernel + REST
2. MCP surface for all harnesses
3. flex-auth + rate limits
4. Multi-tenant / productization
---
## 7. Open questions carried into work planning
1. Repo runtime stack (Python FastAPI vs other) — decide in first
implementation workplan, not in research.
2. Whether vendor MCP is ever an internal backend (default: **no**; prefer
direct REST client).
3. AppRole for assistant-only secret fetch vs OIDC role only.
4. IBAN / PII redaction levels for agent channels.
---
## 8. Source index (non-exhaustive)
### Internal paths
- `binky-control/integrations/qonto-mcp.md`
- `binky-control/integrations/qonto-governed-assistant/ArchitectureBlueprint.md` (origin copy)
- `binky-control/finance/CostRunRate.md`, `finance/qonto-first-pull-2026-07-21.json`
- `agent-harness/INTENT.md`, `docs/adr/ADR-001-agent-harness-architecture.md`
- `llm-connect/ARCHITECTURE-LAYERS.md`
- `flex-auth/INTENT.md`
- ops-warden catalog entry `binky-qonto-api`; railiance-platform CCR-2026-0008
### External (retrieved 2026-07-21)
- Envoy AI Gateway MCP documentation (MCPRoute, toolSelector, authorization CEL)
- Kong AI Gateway MCP Tool ACLs product notes
- MCP gateway explainers (Speakeasy, Portkey, Permit, community)
- MCP security best practices (token passthrough, proxy consent, tool-level scopes)
- CSA / industry agentic MCP security maturity notes
- Harness MCP server gateway compatibility notes
- GitHub `qonto/qonto-mcp-server` README (env vars; maintained status warning for local server)