---
title: MCP agent workflows
description: Connect an agent, query governed metrics, author reports, and follow reviewed requests with complete MCP calls.
---

Connect your remote MCP client to `https://mcp.metricmaven.io/mcp` using OAuth or a Maven API key. The client sends its bearer credential on every request.

Use the [public operation reference](https://www.metricmaven.io/docs/mcp.md) for every customer operation, required scopes, nested input schemas, and complete argument examples. Your connection's authenticated reference is `https://mcp.metricmaven.io/docs.md`; add `?family=report` to narrow it. Fetch it only with the same credential your MCP client uses. If your host keeps its token private, use the public reference and your advertised tools instead.

## Every call has four fields

Invoke the **family tool** (for example, `report`) with `target`, `operation`, `options`, and `context`. The JSON blocks below are tool arguments, not separate REST requests. Empty `target` and `options` objects are still required. Unknown fields are rejected.

`target` identifies the workspace or record; `options` contains that operation's payload. Top-level `context` records the verbatim user request, this call's goal, a stable turn ID, and fidelity. A request's `options.context` is separate business context. For a new user turn, use a new turn ID and the new verbatim request.

Replace angle-bracket placeholders with actual values from prior responses. Numeric revision examples are illustrative: always use the returned revision. Never invent workspace IDs, metric names, checkpoints, or digests.

## 1. Identify the connection and workspace

Tool: `whoami`. Read authorization, scopes, and documentation links before acting.

```json
{
  "target": {},
  "operation": "inspect",
  "options": {},
  "context": {
    "user_request": "Compare paid media efficiency with qualified pipeline by month.",
    "agent_goal": "Inspect the connection and granted scopes.",
    "turn_id": "turn_example_001",
    "fidelity": "exact"
  }
}
```

For topic guidance (report authoring, reconciliation entity scoping, cross-client freshness, canonical vs compatibility metrics, data readiness), call `whoami` with `operation: "docs"` and `options.topic`; omit the topic to list the topics and documentation links.

Tool: `workspace`. Operation: `list`. Select an allowed workspace ID from the result. Customer-wide credentials need a workspace for workspace-bound work; only omit it where the operation permits a workspace-bound credential to supply it.

```json
{
  "target": {},
  "operation": "list",
  "options": {},
  "context": {
    "user_request": "Compare paid media efficiency with qualified pipeline by month.",
    "agent_goal": "Find the workspace authorized for this analysis.",
    "turn_id": "turn_example_001",
    "fidelity": "exact"
  }
}
```

## 2. Discover metrics before querying

Tool: `describe_schema`. Operation: `schema`. Read the returned metric identifiers, supported dimensions, and compatible grains. Use `metrics` for metric discovery and `dimension_values` before filtering categorical values.

```json
{
  "target": {
    "workspace_id": "<workspace_id>"
  },
  "operation": "schema",
  "options": {},
  "context": {
    "user_request": "Compare paid media efficiency with qualified pipeline by month.",
    "agent_goal": "Discover available metrics and compatible dimensions.",
    "turn_id": "turn_example_001",
    "fidelity": "exact"
  }
}
```

Tool: `query_metrics`. Operation: `aggregate`. Use exact discovered identifiers. Start with compatible metrics from one source; cross-source queries require the documented `allowCrossTable` conditions. Maven computes totals and comparisons.

```json
{
  "target": {
    "workspace_id": "<workspace_id>"
  },
  "operation": "aggregate",
  "options": {
    "metrics": [
      "<metric_from_schema>"
    ],
    "timeDimension": {
      "granularity": "month",
      "range": {
        "start": "2026-07-01",
        "end": "2026-08-31"
      }
    },
    "groupByTime": true
  },
  "context": {
    "user_request": "Compare paid media efficiency with qualified pipeline by month.",
    "agent_goal": "Query monthly performance over the requested period.",
    "turn_id": "turn_example_001",
    "fidelity": "exact"
  }
}
```

Use `compare` for two explicit periods and `rank` for ranked results. Preserve provenance and coverage warnings from the response. Do not silently join incompatible grains or calculate replacement totals from record reads.

## 3. Author a report directly

The `report` family supports creating reports, presentations, and custom drafts; editing source files; governed data bindings; previews; exports; and explicit publication. A durable request is another workflow, not a prerequisite for direct authoring.

Report authoring uses four operations, each selecting what it does with `options.action`: `draft` (create, find, import, restore, abandon), `read` (state, context, files, history, collaboration), `edit` (source files and bindings), and `check` (validate, resolve, verify, open). Before creating, call `draft` with `options.action: "list_drafts"` or `read` with `options.action: "inspect_state"` to find existing work. Tool: `report`; operation: `draft` with `options.action: "create"` for a new draft:

```json
{
  "target": {
    "workspace_id": "<workspace_id>"
  },
  "operation": "draft",
  "options": {
    "action": "create",
    "format": "report",
    "title": "Monthly performance"
  },
  "context": {
    "user_request": "Create a monthly performance report for this workspace.",
    "agent_goal": "Create the requested report draft.",
    "turn_id": "turn_example_001",
    "fidelity": "exact"
  }
}
```

Keep the returned draft session identity. Call `read` with the actions `inspect_state`, `inspect_context`, and `list_files` to read its current revision, source structure, and design context before editing. Call `edit` with the action `apply_changes`, `write_file`, or `edit_file` and the current `expected_revision`.

For a governed query binding, tool: `report`; operation: `edit` with `options.action: "upsert_binding"`. The binding's `request.timeSlot` is different from the analytics call's `timeDimension`. Fill its metric and time field from schema discovery:

```json
{
  "target": {
    "workspace_id": "<workspace_id>",
    "session_id": "<session_id>"
  },
  "operation": "edit",
  "options": {
    "action": "upsert_binding",
    "expected_revision": 1,
    "binding": {
      "key": "monthly_performance",
      "label": "Monthly performance",
      "source": "query-metrics",
      "grain": "trend",
      "request": {
        "metrics": [
          "<metric_from_schema>"
        ],
        "groupByTime": true,
        "timeSlot": {
          "field": "<time_field_from_schema>",
          "granularity": "month"
        }
      }
    }
  },
  "context": {
    "user_request": "Create a monthly performance report for this workspace.",
    "agent_goal": "Bind the report to governed monthly metrics at the current revision.",
    "turn_id": "turn_example_001",
    "fidelity": "exact"
  }
}
```

Every successful source or binding edit can change the revision. Re-read state after a conflict instead of retrying against an invented revision.

| Next call on `report` | Required input beyond workspace and session | What to carry forward |
| --- | --- | --- |
| `check`, action `validate` | `options.expected_revision` | Validation issues to fix |
| `check`, action `resolve` | `options.expected_revision` | Frozen checkpoint identity |
| `check`, action `verify` | `options.expected_revision`, `options.checkpoint_id` | Verification result; resume with returned tokens when needed |
| `check`, action `open` | `options.expected_revision`, `options.checkpoint_id` of a verified checkpoint | Viewer identity/link for human review |
| `export`, action `export_start` | Revision, checkpoint, `format` (`pdf` or `pptx`) | Export ID; poll `export`, action `export_get` |

Read each operation's complete example in the reference and include `context` on every call. Validation, verification, preview, and export do not publish.

## 4. Publish an exact reviewed checkpoint

Tool: `report`; operation: `publish` with `options.action: "publish"` (a call that omits the action also publishes). First prepare against the verified revision, checkpoint, and current live version. For a first publication with no live version, use `null`; otherwise use the actual live version ID from state.

```json
{
  "target": {
    "workspace_id": "<workspace_id>",
    "session_id": "<session_id>"
  },
  "operation": "publish",
  "options": {
    "action": "publish",
    "phase": "prepare",
    "expected_revision": 2,
    "checkpoint_id": "<checkpoint_id>",
    "expected_live_version_id": null,
    "idempotency_key": "publish-example-001"
  },
  "context": {
    "user_request": "Create a monthly performance report for this workspace.",
    "agent_goal": "Prepare the verified checkpoint for review without publishing.",
    "turn_id": "turn_example_001",
    "fidelity": "exact"
  }
}
```

Review the returned effects with the user. After explicit authorization for that checkpoint, call `publish` (action `publish`) with `phase: "confirm"`, the exact returned action ID and digest, `approved: true`, and an authorization statement. Do not copy a sample digest or infer consent from the original request to create a report.

Continue with the documented `execute` phase if execution remains pending, and inspect `phase: "status"` using the same action ID. If the execution outcome is unknown, use `phase: "reconcile"` with the exact action ID and digest before retrying. Report success only when the returned receipt confirms publication. Changes to source or the live version require fresh preparation and review.

## 5. Submit and follow a durable request

Use the `request` family for report or tagging work handled through Maven's durable request workflow. Customer tagging work uses this workflow; do not assume staff tracking operations are available.

Tool: `request`; operation: `submit`; `options.action`: `submit`:

```json
{
  "target": {
    "workspace_id": "<workspace_id>"
  },
  "operation": "submit",
  "options": {
    "action": "submit",
    "kind": "report",
    "request": "Compare paid media efficiency with qualified pipeline by month.",
    "context": "Use approved KPI definitions and call out missing coverage.",
    "idempotency_key": "request-example-001"
  },
  "context": {
    "user_request": "Compare paid media efficiency with qualified pipeline by month.",
    "agent_goal": "Submit the report request for durable processing.",
    "turn_id": "turn_example_001",
    "fidelity": "exact"
  }
}
```

Keep the returned request identity. Reuse the idempotency key for a retry of the same submission.

Tool: `request`; operation: `status`; `options.action`: `inspect`:

```json
{
  "target": {
    "workspace_id": "<workspace_id>",
    "request_id": "<request_id>"
  },
  "operation": "status",
  "options": {
    "action": "inspect"
  },
  "context": {
    "user_request": "Compare paid media efficiency with qualified pipeline by month.",
    "agent_goal": "Read the request status and next required action.",
    "turn_id": "turn_example_001",
    "fidelity": "exact"
  }
}
```

Every `request` operation takes `options.action`. The action names are the operation names used before consolidation; those old names are retired as operations and return `OPERATION_RETIRED` naming the replacement below.

| Next call on `request` | `options.action` | Inputs and purpose |
| --- | --- | --- |
| `status` | `list` | Workspace target; optional `options.cursor` and `limit` |
| `submit` | `add_context` | Request target; `options.context` and a new `idempotency_key` for the clarification |
| `prepare` | `prepare` | Request target; `expected_revision`; defaults to `dry_run: true` (read-only inspection). Set `dry_run: false` with an idempotency key to enqueue preparation; this may run the agent, browser journeys, provider checks, staging, and QA, but never authorizes publication |
| `review` | `review` | Request target; read the exact checkpoint, staged changes, and QA evidence |
| `decide` | `decide` | Request target; reviewed `expected_revision`, `checkpoint_id`, `artifact_revision`, `approved`, and `confirm: true`, after explicit user approval |
| `prepare` | `prepare_provider` | Provider preflight/preparation where supported; see the exact required event fields in the reference |
| `decide` | `decide_provider` | Confirm an explicitly approved provider action using its returned action ID and digest; tag-manager publication is separate |
| `decide` | `decide_action` | Pending-action target (`pending_action_id`); `confirmation_digest`, `approved`, and `authorization_statement`, after the user explicitly decides that pending action |
| `help` | `request_help` or `submit_bug` | Workspace target; a confirmed support request or a reproducible platform bug |

Include the same four-field envelope on these calls. Use current returned revisions, not the sample report revisions above. A timeout or closed connection is not proof of completion; inspect the same request after reconnecting.

## 6. Report on a CRM custom field

Custom fields from your CRM (GoHighLevel, HubSpot, and other connected CRMs) can be grouped and filtered like any other dimension once they are promoted. A connection with `write:reports` (standard customer keys) can run every step; `write:context` or `admin` also works.

1. Store the value on the CRM record. For GoHighLevel, create a contact custom field (for example `contact.cta_button`) and map your form or webhook value into it. A value that only exists in a webhook payload is not visible to Maven. Maven reads the field as `cf_<field key>`, so `contact.cta_button` becomes `cf_cta_button`.
2. Wait for the next CRM sync so the field reaches the lead and deal tables.
3. Discover it. Tool: `describe_schema`. Operation: `custom_fields` with `refresh: true`. New keys appear as `suggested`.
4. Check the values. Operation: `custom_field_values` with the `cf_key`.
5. Promote it. Tool: `context`. Operation: `promote_custom_field` (`options.action` may be omitted; it defaults to `promote_custom_field`). Promotion is workspace-wide and immediate. Fields classified restricted (password, secret, SSN, or card-like names) need `write:context`. Field names containing `id`, `email`, `name`, or similar are classified sensitive and can still be promoted. Email-, phone-, and SSN-shaped sample values are masked in discovery output.

```json
{
  "target": {
    "workspace_id": "<workspace_id>"
  },
  "operation": "promote_custom_field",
  "options": {
    "action": "promote_custom_field",
    "cf_key": "cf_cta_button",
    "display_name": "CTA button"
  },
  "context": {
    "user_request": "Show leads by which CTA button they clicked.",
    "agent_goal": "Make the CTA button custom field a queryable dimension.",
    "turn_id": "turn_example_002",
    "fidelity": "exact"
  }
}
```

6. Query it. Tool: `query_metrics`. Operation: `aggregate`. Use the `cf_key` as a dimension or filter with a lead metric such as `lead_count`.

```json
{
  "target": {
    "workspace_id": "<workspace_id>"
  },
  "operation": "aggregate",
  "options": {
    "metrics": [
      "lead_count"
    ],
    "dimensions": [
      "cf_cta_button"
    ],
    "timeDimension": {
      "range": {
        "last": 30,
        "unit": "days"
      }
    }
  },
  "context": {
    "user_request": "Show leads by which CTA button they clicked.",
    "agent_goal": "Break down leads by CTA button over the last 30 days.",
    "turn_id": "turn_example_002",
    "fidelity": "exact"
  }
}
```

Promoted fields also work in report bindings. Leads created before the field existed have no value and group as null.

## Other available capabilities

The reference also covers integration discovery and connections (`integration`), alerts and scheduled deliveries (`notification`), workspace business context, notes, and site context (`context`), plus freshness, users, and media-budget pacing (`workspace`). Each operation lists its scopes and approval requirements. Only call operations authorized for your connection.

## Errors and recovery

- `CONTEXT_REQUIRED`: resend with valid top-level context; the rejected call did not run.
- `INVALID_OPERATION_INPUT`: check the exact target/options split, required fields, nested schema, and chosen phase.
- `OPERATION_DENIED`: inspect scopes; do not retry unchanged credentials expecting access.
- `UNKNOWN_OPERATION`: refresh the reference and advertised tools. Use family operations, not historical standalone tool names.
- Revision conflicts: inspect current state and reconcile changes before preparing again.
- Uncertain writes: inspect status and use documented reconciliation/idempotency instead of creating a duplicate action.
- `RATE_LIMITED` (`retryable: true`, `retry_after` seconds): Maven or an upstream provider such as a Google API quota (`upstream_code: GOOGLE_API_RATE_LIMITED`) is throttling. Wait at least `retry_after` seconds, then retry the same call unchanged; do not retry immediately.
- `PUBLISHED_BRAND_THEME_REQUIRED` (`retryable: false`): `brand operation=propose` needs a published customer Brand Theme. Follow the returned `remediation` (a customer admin publishes branding in Settings → Branding), then propose again; retrying first returns the same error.

Check `isError` and the returned content even when the transport succeeds. Keep opaque IDs, pagination cursors, resume tokens, and digests unchanged. The operation reference includes output schemas where declared; an open object schema does not promise particular fields.

Refresh `tools/list` or reconnect if your host cached an older catalog. The initialized connection and tool-list metadata carry a catalog fingerprint.
