A well-behaved MCP client does not guess. Before it writes a page it asks for the page schema; before it charts your traffic it asks which metrics exist; and when a call is refused it asks what the connection is actually allowed to do. This page covers those tools — the two introspection calls that answer “what shape is this”, the two context calls that answer “who am I and where am I”, and query_analytics, which answers “how did that page do”.
Every tool here is read-only. None of them changes anything in your workspace, and none is gated by your plan — though the data one of them returns is bounded by your analytics retention, which is.
Analytics
Two tools, and they are meant to be used in that order: discover the metric names, then query one.
query_analytics
GET /api/analytics · Operator MCP only · read-only · requires analytics:read
| Parameter | Type | Required | Default | Notes |
|---|---|---|---|---|
metric | string | yes | — | A metric name from list_analytics_metrics. Validated by the route, not by the tool schema — see the warning below. |
start | string (ISO-8601 date-time) | yes | — | Start of the window. |
end | string (ISO-8601 date-time) | yes | — | End of the window. Must be strictly after start. |
type | "count" | "line" | no | both |
pageId | string | no | site-wide | The page’s internal id, never its title. Resolve a title through list_pages first. |
Returns the metric result — a value plus trend for a number metric, a ranked table for a list metric.
list_analytics_metrics
In-process · Operator MCP only · read-only · no arguments
Returns { numberMetrics: [...], listMetrics: [...] } — the two arrays of valid metric values. This is the only correct way to discover them. It has no backing HTTP route: the answer is a static catalog, so it is served in the MCP layer itself and never touches your data.
{
"numberMetrics": [
"averagePageViewsPerSessionMetric",
"distinctPagesViewedPerHourMetric",
"pageViewsMetric",
"totalSessionsMetric",
"uniqueSessionsMetric",
"uniqueVisitorsMetric"
],
"listMetrics": ["browsersUsedMetric", "referrersMetric", "sessionsByCountryMetric", "…"]
}The two shapes of metric
| Shape | Count | What it returns | Does type apply? |
|---|---|---|---|
| Number metrics | 6 | One counted value for the window, plus a time series | Yes — count, line, or both |
| List metrics | 22 | A ranked table of rows | No |
The definitions belong with the analytics screens that display them, not here: the six counted metrics are defined in the metrics reference, and the twenty-two ranked tables, with their columns, in the list metrics reference. A metric means the same thing over MCP as it does on the Know dashboard — there is one implementation behind both.
A handful of list metrics are gated by plan rather than by MCP: the video and audio engagement metrics, the internal-click metrics and hidden-UTM inbound attribution are Growth features. Querying one below Growth returns a 402 with an upgrade_required body, which reaches your client as a tool error naming the feature. Which metric needs which plan is in feature availability by plan; capture is never gated, only reporting, so the data is waiting when you upgrade.
Where your data stops
Analytics retention is a quota, not a feature switch. Free keeps 30 days, Starter 365, Growth 730, and Enterprise is unlimited. Nothing is ever deleted — retention is applied at query time as a cutoff.
That produces two different outcomes, and it is worth knowing which one you hit:
- A window that straddles the cutoff is silently clamped. Ask a Free workspace for 90 days and you get the most recent 30, with no error and no warning. The response echoes the window that was actually queried, so read it rather than assuming your requested bounds.
- A window entirely older than the cutoff is refused. You get a
402with{"error":"upgrade_required","reason":"quota_exceeded","feature":"analyticsRetention"}, carrying your current tier, the retention quota in days, and how far back the request reached.
Date ranges and retention covers the same clamp from the dashboard’s side, where the date picker enforces it before you can ask.
MCP returns data, the assistant draws a chart
There are two analytics tools in Leed and they are deliberately not the same one. query_analytics is Operator-MCP-only and returns rows for a model to reason over. get_analytics is assistant-only and renders a chart inline in the chat — a count, a line, a ranked list, or a US and world map for the two geographic metrics. Neither surface can see the other’s tool. If you connected a client and cannot find a tool that draws pictures, that is why; ask the Leed Assistant instead.
Calls made over MCP are also counted separately from human traffic in your own analytics — analytics for AI and MCP clients explains the three audience buckets.
Introspection
Two tools with no backing HTTP route. They are answered in the MCP layer itself, are read-only, and are the same for every workspace — they describe shapes and catalogs, not your content. They are still recorded in the audit trail like any other call.
describe_schema
In-process · Operator MCP only · read-only
| Parameter | Type | Required | Default | Notes |
|---|---|---|---|---|
target | "page" | "page_type" | "form" | "menu" |
The first four targets return JSON Schema, so a model can construct a valid input for the matching create or update tool without trial and error. The fifth returns prose.
| Target | Returns | Call it before |
|---|---|---|
page | JSON Schema for a page input | create_page, create_page_draft, update_page_draft |
page_type | JSON Schema for a page type input | Reading or reasoning about a page type’s fields |
form | JSON Schema for a form input | create_form, update_form_draft |
menu | JSON Schema for a menu input | update_menu_draft |
leed_markdown | The full Leed Markdown syntax guide, as text | Writing any page body |
The leed_markdown target is worth calling out. It returns the same syntax guide the page-writing tools embed in their own descriptions and the same one authors read at the Leed Markdown cheat sheet — alerts, collapsibles, tabs, embeds, attribute syntax, the lot. A client that fetches it once writes markdown that survives the round trip through the editor. Authoring pages over MCP shows what that looks like in practice.
{
"target": "leed_markdown",
"guide": "# Leed Markdown Format\n\nAlerts:\n:::note\n…"
}list_analytics_metrics
The second introspection tool, covered under Analytics above because that is where you will use it. It is listed here so the pair is not surprising: both are in-process, both are argument-light, and both are cheap enough to call at the start of every session.
Workspace context
Two tools that answer “what is this workspace, and what am I allowed to do in it”.
describe_capabilities
GET /api/ai/context/capabilities · Operator MCP and the assistant · read-only · requires rbac:read
No parameters. Returns your effective role, the full privilege list with the minimum role each one requires and whether you are granted it, and your resource-level overrides grouped by resource type.
{
"role": "Write",
"privileges": [
{ "privilege": "page:write", "minimumRole": "Write", "granted": true },
{ "privilege": "page:publish", "minimumRole": "Publish", "granted": false }
],
"overrides": {
"pagetype": [{ "resourceId": "u05nxr", "role": "Publish" }]
}
}The overrides matter as much as the role. A Content Writer with a Content Publisher override on one page type can publish there and nowhere else, and this tool is the only way a client can see that before it tries. The privilege matrix is the same grid in human form, and resource-level access overrides explains how one gets granted.
rbac:read itself requires the Read Only role or higher, so a Restricted user cannot call this tool — or query_analytics, which needs analytics:read on the same floor.
get_company
GET /api/ai/context/company · Operator MCP only · read-only
No parameters. Returns a deliberately narrow summary of the workspace:
| Field | Meaning |
|---|---|
siteTitle | The site’s display title |
public.domain / public.customDomainActive | Your live domain and whether the custom hostname is active |
preview.domain / preview.customDomainActive | The same for the preview site |
tier | The entitlement tier: free, starter, growth or enterprise |
languages | The languages configured for API documentation code samples |
It is a safe subset by design and does not expose provisioning internals — no DNS or DKIM records, no Cloudflare project ids, no Turnstile keys, no repository credentials. A client that wants to build a link to a published page combines this with resolve_path and list_paths, which live with the rest of the URL tools in MCP tools: site structure.