Developer reference · MCP
Optimly MCP connector
One endpoint, 13 tools, and the brand named per call — by a credential that reaches every brand in your organization, or one pinned to a single brand. The connector speaks Streamable HTTP and keeps no session, so any request can land on any instance.
Connect a client
Create a key in the application under Connections — it is shown once, and leaving its scope on every brand gives you one credential for all of them. The three shapes below cover the clients most people use; the Connections page has the paste-ready setup, extraction, and interview prompts that go with them.
Claude Code
claude mcp add optimly --url https://app.optimly.ai/api/mcp --bearer-token-env-var OPTIMLY_KEY
Keep the key in the named environment variable rather than a committed file.
Cursor, and other JSON clients
{
"mcpServers": {
"optimly": {
"url": "https://app.optimly.ai/api/mcp",
"headers": { "Authorization": "Bearer <your-key>" }
}
}
}
Hosted connectors
Add a custom connector pointing at https://app.optimly.ai/api/mcp and complete the OAuth consent screen in the browser. The connector discovers the flow on its own: an unauthenticated request answers 401 with a WWW-Authenticate header naming the resource metadata at https://app.optimly.ai/.well-known/oauth-protected-resource, which in turn advertises the authorization server at https://app.optimly.ai/.well-known/oauth-authorization-server. PKCE with S256 is required.
Tool reference
All 13 tools, as the connector advertises them. Reading is unconstrained; writing is limited to publish_vault and act_on_recommendation. No tool starts a measurement run.
list_brands
The brands this credential can reach — the list every other tool's `brand`
argument is drawn from, with each brand's id, name, domain and slug. A
brand-bound credential sees only its own; an org-wide one sees the whole
organization.
Listed first on purpose: a caller that does not know what it can reach should
be able to find out before it tries to read or write anything.
No parameters beyond the authenticated brand.
get_brand
Identity of the authenticated brand: name, canonical domain, slugs, claim state.
get_vault
The brand's active vault: all sections (with publish_state),
competitors, and disambiguation. Falls back to the draft when nothing is
published.
publish_vault
Publish a new vault version.
Payload shape:
`{"sections": {<registry key>: {"content", "publish_state":
"public"|"internal", "evidence_url"?}}, "competitors": [{name, url,
competitor_type: "direct"|"indirect_adjacent"|"legacy_category",
is_primary}], "disambiguation": {<one of the six field keys>: [str]}}`.
The full schema, including every section and disambiguation key, is in this
tool's input schema.
**Presence means replace; omission means keep.** Omitted `sections` copy
forward from the active version. Omitted `competitors` and
`disambiguation` PRESERVE the current living sets; to change them, send
the complete list/object (a present object replaces the whole set), or
`[]` / `{}` to clear. Sending only the fields you are adding will delete
the rest of that set. `alternate_domains` is the exception: it carries
forward when omitted and cannot be changed through the API.
Competitor URLs may omit the scheme (`example.com`, `example.com/pricing`);
they are stored as https://. Rows whose URL does not resolve are dropped,
never fatal. Measurement is not re-triggered by publishing — runs are
scheduled in the app.
Publishing changes what the world sees, so this tool does not guess which
brand it is for: state `brand`, and **confirm the brand with the user
before calling it** — name it in the confirmation ("publish to Acme?"),
and if the organization has more than one brand, never infer which one
they meant.
list_vault_versions
Version history of the brand's vault, newest first (metadata only).
get_vault_version
One vault version snapshot by number: metadata + the full section rows.
list_recommendations
All recommendations for the brand, newest first. Optional filters:
status (todo|done|dismissed), effort (low|medium|high).
act_on_recommendation
Act on a recommendation: status todo|done|dismissed; acted_at (optional
ISO-8601) backdates the completion. Provide status and/or acted_at.
This writes, so it names its brand: state `brand` rather than letting it be
inferred, and when the organization has more than one, confirm with the user
which brand's recommendation this is.
list_reports
All measurement reports for the brand, newest version first. Reports
are read-only — runs are triggered in the app, never here.
get_report
One report: frozen summary metrics, the model panel snapshot, and the
run block (trigger, timing).
get_report_questions
Question Analysis for one report: every question with per-model answers
and judgments. Pass question_id to narrow to a single question.
get_report_sources
Sources for one report: per-domain citation aggregation with
owned / competitor / third-party classification.
get_attribution
Attribution for the brand: metric trend across report versions plus the
acted-on recommendation timeline.