QONTO-WP-0003-T04: document finance-qonto-read tool profile contract

qonto-assistant's side only, per task scope: the contract a profile named
finance-qonto-read must satisfy in agent-harness (~/agent-harness, ADR-001,
ToolProfile) to reach this MCP surface -- lane (green/blue, never red), the
exact mcp__qonto-assistant__* allowed-tools list, and the optional
finance.qonto.read scope.

Checked agent-harness/agent_harness/profiles.py directly: only CLI-only
profiles exist today (green-commit-only, blue-mail-triage), none grant an
MCP server yet. Included a ready-to-paste ToolProfile entry matching its
actual schema, marked as a proposal for agent-harness's own PR -- not
applied here, since registering it is a separate repo/workplan. Added the
end-to-end example: instance manifest -> harness-injected MCP server config
-> the four allowed tool calls.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
tegwick 2026-07-23 09:48:36 +02:00
parent b96b8cd5b3
commit 1e476309a3
2 changed files with 103 additions and 1 deletions

View file

@ -74,6 +74,85 @@ Replace the `url` host/port with wherever the service is actually deployed.
whatever secret-interpolation syntax your harness config supports — never
paste the literal token into a shared config file.
## Agent-harness tool profile: `finance-qonto-read`
`agent-harness` (`~/agent-harness`, ADR-001) is the session runtime that
coding-agent sessions actually run inside. It enforces a hard tool allow-list
per session via a named `ToolProfile` (`agent_harness/profiles.py`) —
instances declare a profile by name in their manifest; the harness resolves
and enforces the allow-list; instances never enumerate tools themselves.
Today `agent_harness/profiles.py` only registers CLI/session profiles
(`green-commit-only`, `blue-mail-triage`) built from Claude Code
`--allowedTools` strings — no profile currently grants any MCP server.
This is **qonto-assistant's side only**: the contract a profile named
`finance-qonto-read` must satisfy so a session granted it can reach this
MCP surface and nothing else. Registering the profile itself is
agent-harness's own workplan/repo — this is not applied here.
**Contract:**
| Field | Value |
| --- | --- |
| Profile name | `finance-qonto-read` |
| Lane | `green` or `blue` only — never `red` (matches `specs/ArchitectureBlueprint.md` §4.6: reads are Green/Blue; plan/key/transfer changes are Red, and this surface never exposes those anyway) |
| MCP server | the `qonto-assistant` entry from the client config snippet below, with the bearer token and `X-Actor-*` headers injected by the harness — never left for the instance to fill in |
| Allowed tools | `mcp__qonto-assistant__qonto_ping`, `mcp__qonto-assistant__qonto_org_summary`, `mcp__qonto-assistant__qonto_list_transactions`, `mcp__qonto-assistant__qonto_cost_run_rate_hints` — the full catalog above, nothing more (no future write tool is ever silently included; adding one here always requires an explicit profile edit) |
| Required scope (optional today) | `finance.qonto.read` — matches `QONTO_ASSISTANT_REQUIRED_SCOPE`; only enforced when the service sets `QONTO_ASSISTANT_ENFORCE_SCOPE=true` |
**Proposed `agent_harness/profiles.py` entry** (for agent-harness's own PR,
not applied by this task):
```python
"finance-qonto-read": ToolProfile(
name="finance-qonto-read",
description=(
"Read-only Qonto finance awareness via qonto-assistant MCP. "
"No spend, transfer, card, or volume-cost tools."
),
allowed_tools=(
"mcp__qonto-assistant__qonto_ping,"
"mcp__qonto-assistant__qonto_org_summary,"
"mcp__qonto-assistant__qonto_list_transactions,"
"mcp__qonto-assistant__qonto_cost_run_rate_hints"
),
lane="green",
),
```
**End-to-end example** — an agent-harness instance manifest declaring the
profile, paired with the MCP server config the harness would inject for that
session (the same shape as the shared snippet above, scoped to one profile):
```yaml
# instance manifest (agent-harness side)
tool_profile: finance-qonto-read
```
```json
// MCP server config the harness injects for a finance-qonto-read session
{
"mcpServers": {
"qonto-assistant": {
"url": "http://127.0.0.1:8080/mcp",
"headers": {
"Authorization": "Bearer ${QONTO_ASSISTANT_MCP_TOKEN}",
"X-Actor-ID": "agent-harness:${INSTANCE_ID}",
"X-Tenant-ID": "binky",
"X-Actor-Lane": "green"
}
}
}
}
```
The instance never sees the bearer token or picks its own headers — the
harness resolves the profile, injects this config, and the session's
`--allowedTools` allow-list (from the profile) is the only thing standing
between the model and which of the four tools it can call. Policy
enforcement itself still happens inside qonto-assistant regardless of what
the harness allows, per the shared `PolicyEngine.decide()` path.
## Local smoke: start with auth enabled, connect with only this snippet
```bash

View file

@ -175,7 +175,7 @@ headers) listed tools and called `qonto_org_summary` successfully, with
```task
id: QONTO-WP-0003-T04
status: todo
status: done
priority: medium
state_hub_task_id: "c6805812-8419-4200-b4ad-a048a541b3be"
```
@ -191,6 +191,29 @@ callers to present.
Done when: profile contract is documented and referenced from the MCP
integration doc; at least one harness config example uses it end-to-end.
**Done 2026-07-23:** Checked `~/agent-harness` (ADR-001,
`agent_harness/profiles.py`) directly rather than guessing the shape —
`ToolProfile` is real: instances declare a profile by name, the harness
resolves and enforces a hard `--allowedTools` allow-list, instances never
enumerate tools. Today only `green-commit-only` and `blue-mail-triage` are
registered, both CLI-only; no profile currently grants any MCP server.
Added a **`finance-qonto-read`** section to `docs/mcp-integration.md` with
the qonto-assistant-side contract: lane (`green`/`blue` only, never `red`),
the exact `mcp__qonto-assistant__*` allowed-tools list (all four tools,
nothing more), and the optional `finance.qonto.read` required scope. Included
a ready-to-paste proposed `ToolProfile` entry matching agent-harness's actual
`profiles.py` schema, explicitly marked as a proposal for agent-harness's own
PR — **not applied to that repo by this task**, since registering it there is
outside qonto-assistant's scope and a separate repo/workplan. Added the
end-to-end example the done-criteria asks for: an instance manifest
(`tool_profile: finance-qonto-read`) paired with the MCP server config the
harness would inject for that session, showing the full path from profile
name to the four allowed tool calls.
No code changes — this task is qonto-assistant-side documentation only, per
its own scope note. `pytest``28 passed` (unchanged).
## Task: Unified audit schema across REST and MCP
```task