Avo MCP
The Avo MCP (Model Context Protocol) server exposes your Avo tracking plan to AI coding assistants. Tools like Claude, ChatGPT, Cursor, Codex, Claude Code, and other MCP-compatible clients can read your tracking plan, explore branches, and write changes on a branch — without you copy-pasting specs into the chat.
- Transport: Streamable HTTP at
https://mcp.avo.app/mcp - Authentication: OAuth 2.0 + PKCE, scoped to your Avo identity
- Writes: always happen on a branch (never directly on main). Merging to main stays a human step in the Avo app.
The Avo MCP is in general beta. Both the read and write tools are enabled for every workspace — no need to request access. We’re still refining them, so let us know at support@avo.app if you hit anything unexpected.
Writes require the write scope and always happen on a branch. The MCP server will never merge a branch into main — that remains a human step in the Avo web app.
What you can do
Read (scope: read)
- Browse branches and see who created, reviewed, or collaborated on them
- Get implementation guides and code diffs for a specific source on a branch
- Look up details for any tracking plan item — events, properties, metrics, categories, property bundles, sources, destinations, group types, event variants
- Search the plan semantically by meaning
- Discover available sources in your workspace
Write (scope: write)
- Create a new branch from main
- Create, update, and (for some entities) remove events, properties, and event variants on a branch
- Cross-reference newly created items inside a single batch using temporary IDs
Capability matrix
| Capability | Tool | Scope |
|---|---|---|
| Health check | health_check | read |
| List workspaces you can access | list_workspaces | read |
| List branches in a workspace | list_branches | read |
| Branch details (reviewers, status, impacted sources) | get_branch_details | read |
| What changed on a branch (implementation guide) | get_branch_implementation_guide | read |
| Per-event code diffs for a branch + source | get_branch_code_snippets | read |
| List sources in a workspace | get_sources | read |
| Look up any item by ID or exact name | get | read |
| Semantic search across the plan | search | read |
| Create a branch | workflow | write |
| Create / update / remove events, properties, event variants on a branch | save_items | write |
See the Tools reference for full parameters, return shapes, and examples per tool.
Setup
Claude Code (CLI)
claude mcp add avo --transport http https://mcp.avo.app/mcpClaude Desktop app
- Open Claude Desktop → Customize → Connectors
- Click Add custom connector
- Name:
Avo, Remote MCP server URL:https://mcp.avo.app/mcp
Adding connectors in Claude Desktop requires admin permissions in your organization.
Cursor
Add the following to your mcp.json (or ~/.cursor/mcp.json for global config):
{
"mcpServers": {
"Avo": {
"url": "https://mcp.avo.app/mcp"
}
}
}Other MCP clients
{
"mcpServers": {
"Avo": {
"url": "https://mcp.avo.app/mcp"
}
}
}Your client must support HTTP transport and the browser-based OAuth authorization flow. The first tool invocation opens a browser, you sign in with your Avo credentials, the client receives a token, and the token is cached for subsequent calls. Clients that cannot complete the OAuth flow will not work with the Avo MCP.
Authentication
The MCP server uses OAuth 2.0 with PKCE.
- Protected resource metadata: served at
https://mcp.avo.app/.well-known/oauth-protected-resourceper RFC 9728. The authorization server ishttps://api.avo.app— clients discover its endpoints viahttps://api.avo.app/.well-known/oauth-authorization-server. - Dynamic client registration:
POST https://api.avo.app/oauth/registerper RFC 7591. Most MCP clients register themselves automatically on first connect. - Scopes:
readandwrite. Clients requestreadby default. When you invoke a write tool, your client will step up and request thewritescope (a second browser prompt). Tokens carry the user identity; workspace access is verified at call time against your Avo workspace membership. - Token signing: RS256 keys backed by Google Cloud KMS (HSM) in production.
If a tool that requires write is called with a token that only has read, the server returns an error prompting the client to re-authorize with write.
Getting started
Most tools are workspace-scoped (health_check and list_workspaces are the exceptions). The typical first-use sequence:
1. Discover your workspaces
Call list_workspaces to find your workspaceId.
2. Use any tool
Pass workspaceId to every workspace-scoped tool. (Stdio clients can also set the WORKSPACE_ID environment variable so it’s picked up automatically.)
Example workflows
The connector’s core flows, each with a concrete example. Tool calls are shown as tool(arguments); sample JSON shows the response shape. Real responses include the full item shape documented in the Tools reference.
Discover what’s in the plan
Use search for fuzzy lookup by meaning (“user signed up” matches Account Created), get for an exact name or ID, and structural-filter search (no query, just filter fields like eventNames or properties) to list items by relationship.
Semantic search requires Avo Intelligence Smart Search to be enabled in your workspace. Workspace admins can enable it in Workspace Settings. Without it, fall back to get with an exact name.
You: What events do we have for signup?
Claude calls search({ query: "signup", itemType: "event" }).
Returns:
{
"results": [
{
"rank": 1,
"name": "Account Created",
"itemId": "evt-9f2b...",
"relevance": 0.91,
"description": "Sent when a new account is successfully created..."
},
{
"rank": 2,
"name": "Signup Started",
"itemId": "evt-3c11...",
"relevance": 0.87,
"description": "Sent when the user opens the signup screen..."
}
]
}
Claude then calls get({ type: "event", id: "evt-9f2b...", includePropertyDetails: true }) for the full shape, and replies:
You have two signup events. The closest match is **Account Created** —
sent when a user successfully creates an account — with properties
Authentication Method (Email, Google, Apple) and Referral Source. There's
also **Signup Started**, fired when the signup screen opens. Want a closer
look at either?Design tracking for a new feature
The flagship write flow. Claude reads the workspace’s audit rules with get(workspaceConfig), does both-lenses recon (semantic search and structural-filter search) to find what already exists, proposes a plan, and on approval creates a branch with workflow and writes the new items in a single batched save_items call — using tempId to attach a newly-created property to a newly-created event atomically.
You: We're adding social sharing to the post detail screen — Twitter,
LinkedIn, or copy link. Design the tracking for it.
Claude: I'll check the workspace's audit rules, see what already exists,
and propose a plan before touching a branch.
Claude calls get({ type: "workspaceConfig" }), which returns the workspace's naming and audit rules:
{
"eventNaming": {
"structure": "object-action",
"casing": "Title Case",
"tense": "past"
},
"rules": [
"Event names must end in a past-tense verb",
"Property names must be descriptive (e.g. Product Name, not Product)"
]
}
Claude then searches for existing share-related events with search({ query: "share", itemType: "event" }), and lists the properties on the matched Article Shared event with search({ itemType: "property", eventNames: ["Article Shared"] }) — finding Share Method and Share Destination already exist.
Claude: Here's the plan, anchored on a **Post Share Rate** metric:
**Reuse**
- `Share Method` (string: Twitter, LinkedIn, Copy Link) — already on `Article Shared`
- `Share Destination` — same shape we need
**Create**
- **Post Shared** event — sent when a user shares a post from the post detail screen
- **Post ID** property (string, event) — the ID of the post being shared
Matches the workspace convention (Title Case, object-action, past tense).
Proceed with the branch?
You: yes
Claude calls workflow({ action: "create_branch", branchName: "add-post-sharing-tracking" }), then batches the new property and the new event in one save_items call. The event's properties array references the new property by "$tmp:post_id" alongside the real IDs of the two reused properties — the server resolves the temp ID into a real one and attaches everything atomically.
save_items returns:
{
"success": true,
"createdEntities": [
{ "name": "Post ID", "entityId": "prop-9d44...", "entityType": "property" },
{ "name": "Post Shared", "entityId": "evt-3f01...", "entityType": "event" }
],
"updatedEntities": [],
"removedEntities": [],
"errors": [],
"warnings": []
}
Claude: Done. Branch
[`add-post-sharing-tracking`](https://www.avo.app/schemas/default/branches/br-4e8a...)
has the new **Post Shared** event with one new property (**Post ID**) and
two reused ones (**Share Method**, **Share Destination**). Open the branch
in the Avo app to review and merge to main.Review and implement a branch in code
Resolve a branch by name with list_branches, read the high-level change set with get_branch_implementation_guide, then pull the per-event code diff for a specific source with get_branch_code_snippets (after looking up the sourceId via get_sources). Implementation handoff: the diff goes into the codebase, code review happens in git, and the human merges the Avo branch from the web app.
You: I'm implementing the update-signup-flow branch on iOS. Walk me through it.
Claude resolves the branch name with list_branches({ branchName: "update-signup-flow" }), then calls get_branch_implementation_guide({ branchId: "br-6c2d..." }):
{
"summary": { "newEvents": 1, "modifiedEvents": 1, "deletedEvents": 0 },
"newEvents": [
{
"name": "Signup Step Completed",
"description": "Sent when the user completes a step in the signup funnel.",
"properties": ["Signup Step", "Step Outcome"],
"implementationType": "Codegen"
}
],
"modifiedEvents": [
{
"name": "Signup Completed",
"changes": [
{ "field": "properties", "added": ["Authentication Method"] }
],
"implementationType": "Codegen"
}
]
}
Claude looks up the iOS source with get_sources(), then pulls per-event code diffs with get_branch_code_snippets({ branchId: "br-6c2d...", sourceId: "src-ios" }):
{
"snippets": [
{
"event": "Signup Step Completed",
"status": "New",
"label": "Codegen",
"diff": "+ Avo.signupStepCompleted(signupStep: ..., stepOutcome: ...)"
},
{
"event": "Signup Completed",
"status": "Updated",
"label": "Codegen",
"diff": "- Avo.signupCompleted()\n+ Avo.signupCompleted(authenticationMethod: ...)"
}
]
}
Claude: Here's what's on `update-signup-flow` for iOS:
**1 new event** — `Signup Step Completed` (Codegen)
**1 modified event** — `Signup Completed` gains an `Authentication Method`
property (Codegen)
The iOS source uses Avo Codegen, so the next step is to run `avo pull`
locally to regenerate `Avo.swift`, then update each call site:
- Add `Avo.signupStepCompleted(...)` at each signup-step transition
- Pass `authenticationMethod` to existing `Avo.signupCompleted()` calls
Want me to find the call sites in the iOS project, or are you good from here?Troubleshooting
A second browser prompt appears the first time you write. Write tools require the write scope, which is a step-up consent on top of read. Your client opens the OAuth flow again and the prompt only appears once per session.
search returns nothing for a clearly relevant query. Semantic search requires Avo Intelligence Smart Search to be enabled. Workspace admins can turn it on in Workspace Settings. Without it, fall back to get with an exact name.
The wrong branch is returned by name. branchName resolves to a best match and prioritizes open branches, so an ambiguous name can pick the wrong one. Resolve the name to a branchId with list_branches and pass branchId to the follow-up call.
save_items returns a NotYetImplemented error. A small set of operations are not supported yet — removing events, removing event variants, and changing a property’s sendAs. See the save_items reference for the full list.
Authentication never completes. The first tool call opens a browser to sign in. MCP clients that cannot open a browser (CI runners, headless containers) cannot complete the OAuth flow.
workspace access denied. The MCP enforces the same membership rules as the Avo web app. Confirm you’re a member of the workspace at avo.app — and that you’re signing in with the same identity — before retrying.
Support and privacy
For bug reports, feature requests, or help connecting an MCP client, email support@avo.app.
How Avo collects, uses, and retains data is covered in the Avo Privacy Policy.
Tools
See the Tools reference for the full list of tools and their parameters.