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:
parent
b96b8cd5b3
commit
1e476309a3
2 changed files with 103 additions and 1 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue