mureo_decision_record
Log decisions with rationale, metrics, and status; update via superseding records to preserve the full decision history for audit and reproducibility.
Instructions
Record a decision — a proposal, or the operator's answer to one — so the reasoning survives the session. Call it BEFORE you surface a proposal to the operator, with status='proposed', the figures you judged it on in metrics, and your reasoning in rationale. When the operator answers, call it AGAIN with status='adopted' / 'rejected' / 'deferred' and supersedes set to the first record's decision_id: the section is APPEND-ONLY, so a status change is a new record, never an edit — that is what keeps 'we proposed this on the 4th and it was turned down' recoverable. After you carry a decision out, record it once more (or name the entries in related_actions) so the change and the reason for it are joined. display.proposals is the SCREEN — one moment, replaced whole on every dashboard write; this is the RECORD. decision_id and recorded_at are minted by the server; do not compute either. Every bound below refuses the write rather than truncating it.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| path | No | Optional path to STATE.json. Defaults to STATE.json in the MCP server's current working directory. Paths outside it are refused. | |
| title | Yes | What is being decided, in one line (e.g. 'Pause the generic ad group in Search_Lead-Gen'). | |
| status | Yes | Where the decision stands. 'proposed' before the operator has answered; 'adopted' / 'rejected' / 'deferred' afterwards, with `supersedes` set. 'deferred' is not 'rejected' — 'not now' and 'no' call for different behaviour next week. | |
| metrics | No | The figures the decision was judged on, as they stood THEN (e.g. {"cpa_7d": 5200, "conversions_7d": 45}). At most 20 keys, each value a string, number, boolean or null — a nested object is refused, and so is a string longer than 200 characters (a figure that needs a sentence belongs in `rationale`). Without them a rationale read next month against today's numbers is unfalsifiable. | |
| batch_id | No | The declared change set this decision concerns. A CLOSED batch is fine — the verdict on a bulk pass is normally recorded after it finished. | |
| platform | No | Platform the decision is about (google_ads / meta_ads / ...), when it is about one. | |
| entity_id | No | The entity's id. Must be given together with `entity_type`. | |
| rationale | Yes | Why — the evidence you acted on and the effect you expect. This is the payload: nothing downstream can reconstruct it, and you are the last point at which it exists. | |
| supersedes | No | The `decision_id` of the record this one updates. Required in practice for any status other than the first 'proposed', and validated: it must name a decision already on record. | |
| campaign_id | No | Campaign the decision is about, if any. | |
| entity_type | No | Sub-campaign entity kind (ad_group / ad_set / placement / ...). Must be given together with `entity_id`. | |
| related_actions | No | Positional indices into the full action_log of the entries this decision produced. Validated against the log — an index past its end is refused. |