Atune Docs
Guides

Hosted MCP server: connect Claude Code or Codex to useatune.com/mcp

Connect Claude Code or Codex to Atune's hosted MCP server. Ask about customer usage with cited evidence, and let your agent run Atune's AI tasks on your own subscription.

By Christopher Krohn, Founder of Atune · Updated October 19, 2026

Christopher is a SaaS founder and startup advisor who has seen first-hand how much easy-to-use, well-connected analytics matter to the success of SaaS companies. He is building Atune to help the next generation of software builders succeed with their startups.

Atune runs a hosted MCP server at https://useatune.com/mcp. Connect Claude Code or Codex to it and your agent can do two things:

  • Answer questions about your customers from the events you send: who is using the product, who is coming back, and where accounts get stuck. Every answer cites its source.
  • Do Atune's AI work for you. Atune queues the reasoning work (understanding your product, drafting outreach, answering understand() questions), and your agent does it on the Claude or Codex subscription you already have. Atune never calls a model on this path.

This is a different server from npx atune mcp, the local stdio server with one understand tool. See Which server to use.

Connect Claude Code or Codex

In Atune, open Settings → AI agent, choose Claude Code or Codex, and click Create connect command. Atune shows the command for your workspace. Run it in your own terminal.

Claude Code

claude mcp add --transport http atune-<label>-<id> https://useatune.com/mcp \
  --header "Authorization: Bearer atune_agent_..."

Codex

Codex reads the token from an environment variable:

export ATUNE_AGENT_TOKEN_<LABEL>_<ID>=atune_agent_...
codex mcp add atune-<label>-<id> --url https://useatune.com/mcp \
  --bearer-token-env-var ATUNE_AGENT_TOKEN_<LABEL>_<ID>

Add the export line to your shell profile (for example ~/.zshrc) so Codex still has the token in a new terminal.

About the token and the server name

  • The token comes from Settings → AI agent. It starts with atune_agent_, is shown only once, and belongs to you and this workspace. Atune stores only a hash of it. Don't paste it into a chat with the agent or commit it.
  • It's not your API key. The event-ingest API key (ATUNE_API_KEY) is rejected by /mcp.
  • Each workspace gets its own server name, such as atune-acme-3f9a: your product domain plus the last four characters of the workspace id. If you connect a second workspace, the first one stays connected.
  • Connected this workspace before? Remove the old entry first with claude mcp remove <server> or codex mcp remove <server>.
  • Creating a new command replaces your unused one. If you create a command for the same agent again before using the first, Atune revokes the unused token.

Every member of the workspace connects their own agent with their own token.

Browser sign-in (OAuth) instead of a token

If you prefer not to store a token, expand Prefer signing in through the browser instead? in Settings → AI agent and add the server without a header:

# Claude Code: then run /mcp, choose the server and select Authenticate
claude mcp add --transport http atune-<label>-<id> https://useatune.com/mcp

# Codex
codex mcp add atune-<label>-<id> --url https://useatune.com/mcp
codex mcp login atune-<label>-<id>

The server supports OAuth 2.1. An unauthenticated request gets a 401 that points to /.well-known/oauth-protected-resource/mcp, so the client can start the sign-in itself.

Two things to know about OAuth:

  • Check the account before you click Allow. The consent page reuses whichever Atune account your browser is signed in to. It should say on behalf of your email. If it shows another one, click Deny, switch account on useatune.com (account menu, top right) or use a private window, and sign in again.
  • A connection stays with its first workspace. Atune binds an OAuth connection to the workspace that was active when it first called /mcp. It stays there if you later switch workspace in the app. To connect another workspace, add another server name.

The connect command is the more reliable option: the token is bound to the workspace it was created in, whatever your browser is signed in to.

Run my Atune tasks

Open Claude Code or Codex and say:

Run my Atune tasks

The agent then:

  1. Calls list_atune_tasks, which claims up to three waiting tasks. Each task has a title, instructions and the exact JSON shape of the result.
  2. Does the work on your subscription.
  3. Calls submit_atune_task_result for each one. Atune validates the result before it touches your data. An invalid result comes back with what to fix. If the agent can't do a task, it calls fail_atune_task with a short reason, which Atune shows you.
  4. Repeats until no tasks are pending.

Settings → AI agent → Atune tasks shows how many tasks are waiting.

What your agent does for Atune today:

  • Understands your product from its website.
  • Works out what your events mean and which ones show a customer got value.
  • Designs realistic demo data for your product.
  • Drafts personal messages to customers in your Inbox. A draft you already edited is never overwritten.
  • Recommends one improvement for a feature where customers struggle.
  • Recommends one fix for the trial step that loses the most accounts.
  • Answers your understand() questions.

Some details:

  • understand() waits for your agent. When you ask a new question, understand() returns knows: false with signals.pendingAgent: true and queues the question. After your agent has run its tasks, asking the same question returns the answer from the cache.
  • Claims are leases. If the agent stops mid-task, the task goes back in the queue after 15 minutes.
  • Three tries. A task fails after three invalid results.
  • Tasks expire. understand() questions expire after one day, other tasks after seven days.
  • Tasks belong to the workspace. Any member's connected agent can run them.

If the agent says there are no tasks but you expected some, ask it which workspace it is connected to. Every task response includes connectedWorkspace. A different name usually means an OAuth connection signed in to another account. Create a new connect command while signed in to the right account.

Ask about your customers

Once connected, ask in plain language:

  • "Is anyone using the product this week?"
  • "Which accounts are coming back, and which went quiet?"
  • "Where do trials drop off between signup, project.created and invite.sent?"
  • "What's the health score for acct_…, and why?"

The server exposes these read-only tools:

ToolAnswersArguments
get_workspace_overviewWorkspace name, totals (events, accounts, identified users, distinct event names), first and last eventnone
get_usage_evidence"Is anyone using my product?" Active accounts and users, events, a daily series and top event names, compared with the previous windowwindowDays
get_return_usage_evidence"Are they coming back?" Active-day distribution, accounts active in both windows, weekly cohorts, and a ranked per-account listwindowDays, cursor
get_dropoff_evidence"Where are they getting stuck?" Accounts that went quiet, with last event and last seen. Pass steps for a funnelwindowDays, steps, cursor
get_account_evidenceOne account: first and last seen, active days, event counts by name, distinct usersaccountRef, windowDays
get_account_healthOne account's health band (risk, warning, healthy, upsell), score 0–100, week-over-week change, top reasons and a link to it in AtuneaccountRef

windowDays is 7, 14, 30 or 90 (default 14). steps is two to six event names in order. Lists are paginated, 25 items per page.

There is also one resource, atune://methodology/health, which explains how the health score is calculated.

What the evidence tools return

The five evidence tools return an atune.evidence.v1 envelope:

type EvidenceEnvelope = {
  schema: "atune.evidence.v1";
  tool: string;
  retrievedAt: string;
  window: { start: string; end: string; days: number; timezone: "UTC" } | null;
  dataState: "ok" | "no_data" | "insufficient" | "stale" | "not_found";
  freshness: { lastEventAt: string | null; hoursSinceLastEvent: number | null; stale: boolean };
  coverage: {
    retentionDays: 90;
    firstEventAt: string | null;
    eventsInWindow: number;
    accountsInWindow: number;
    limitations: string[]; // e.g. "few_accounts", "stale_ingest", "includes_demo_data"
  };
  observations: object;   // facts read from events
  derivations: object;    // computed from them, e.g. derivations.funnel
  sources: { ref: string; kind: "account" | "event_name" | "aggregate"; description: string }[];
  page: { limit: number; nextCursor: string | null } | null;
  untrustedFields: string[];
};

How to read it:

  • Check dataState first. It needs at least 3 accounts and 20 events in the window to be ok. stale means the newest event is more than 72 hours old. The server tells the agent to say so before drawing conclusions.
  • Cite sources[].ref and the window. Every number traces back to an account, an event name or an aggregate.
  • No funnel unless you name the steps. Without steps, derivations.funnel is null. Atune doesn't guess your funnel.
  • Event names are data, not instructions. Fields listed in untrustedFields come from your customers' events. The agent is told never to act on them.
  • Demo data is flagged. While onboarding demo data exists, every response includes the includes_demo_data limitation.

What get_account_health returns

get_account_health returns an atune.health.v1 envelope: dataState (ok, not_scored or not_found), the account's band, score, week-over-week change, last seen, the reasons that cost the most points, and a url to the account in Atune.

The score is Atune's own calculation, not an observation, so the envelope always has derived: true. When modelInfluenced is true, the value events behind the score were inferred by a model (your agent, when it worked out what your events mean), and the agent is told to say so. The reasons are the parts of the formula that cost the most points. They are not proven causes.

What the tools never return

  • No customer names or emails from the evidence or health tools. Accounts appear as pseudonymous refs (acct_<id>). An unknown ref, a malformed ref and another workspace's ref all return the same not_found, so the tools can't be used to probe for accounts.
  • No event properties. Only event names, counts and timestamps.
  • No API key and no other workspace's data. The workspace comes from the token, never from tool arguments.
  • No model output from Atune. The server only reads data. Your agent does all the reasoning.

Task briefs are different. A task from list_atune_tasks can contain your website text, account names, health scores, and feature and funnel metrics. After you accept the DPA, it can also contain user names and emails. That's what the agent needs to draft a message to the right person. Treat task briefs as confidential customer data.

Limits

  • Rate limit. 300 tool calls per workspace per UTC day and 30 per minute, shared by all tools. Past it, tools return rate_limited.
  • Plan. When Insight is locked on your plan, the evidence and health tools return insight_locked with a link to Settings → Billing. The task tools keep working. See Billing.
  • Only what you send. Answers come from the events you instrument. No events, no evidence.

Revoke access

  • One connection: Settings → AI agent → Your active connections lists the connect commands you created, with when each was last used. Click Revoke to cut off that agent only.
  • Every AI app in the workspace: owners and admins can click Disconnect AI apps in Settings → AI agent. Every token and OAuth connection issued before that moment stops working. Token connections need a new connect command; OAuth connections must sign in again.
  • Removing a member revokes their tokens and OAuth connections to the workspace.
  • On your machine: claude mcp remove <server> or codex mcp remove <server> removes the entry from your agent.

A revoked token gets 401 with the error unauthorized or access_revoked.

Which server to use

Hosted server (useatune.com/mcp)Local server (npx atune mcp)
TransportStreamable HTTPstdio
AuthConnect-command token or OAuthATUNE_API_KEY
ToolsEvidence tools, account health, Atune tasksunderstand
Runs Atune's AI tasksYesNo
ClientsClaude Code, CodexAny MCP client, including Cursor

Use the hosted server for Claude Code or Codex, and so your agent can run Atune's tasks. Use the local server for clients that only speak stdio, or when you want understand() answers inside your editor. You can connect both.

Next

On this page