> ## Documentation Index
> Fetch the complete documentation index at: https://docs.traceten.com/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP safety and permissions

> What an assistant connected to Traceten can and cannot do, and what data leaves your account when it calls a tool.

## What this page is for

You are handing an AI assistant a credential to your analytics account. This page states exactly what that credential can reach, what stops an assistant acting without your say-so, and what data leaves your account when a tool runs.

## Permissions decide everything

The MCP server has no permission model of its own. Every tool call is executed as a real API request against the same endpoint a `curl` command would hit, carrying your key, and the endpoint decides. There is no second path and no elevated mode.

That has one consequence worth stating plainly: **an assistant can do exactly what your credential can do, and nothing more.**

If you [connected with your Traceten account](/mcp/install#connect-with-your-traceten-account) rather than pasting a key, "your credential" means *you*: the connection carries your own permissions in the organization you chose on the sign-in screen, including any restriction to specific sites. It cannot see another organization, and it cannot do anything you could not do in the dashboard.

| Key permission                | What the assistant can do                                                                                              |
| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| `stats:read`                  | Read every number. Cannot change anything.                                                                             |
| `stats:read` + `config:write` | Also create and edit goals and funnels, and edit or delete sites and webhooks.                                         |
| Plus `credentials:write`      | Also create sites, mint API keys and bot tokens, and register or rotate webhooks: everything that hands back a secret. |
| No `stats:read`               | Nothing. Every read tool fails, naming the missing permission.                                                         |

**Give it `stats:read` only unless you have a reason not to.** Permissions cannot be changed after a key is created, so mint a second key if you later want write access, and revoke it when you are done.

### Only approved apps can connect

Before any of the above applies, the app has to be one we allow. Connecting is not open to whatever application asks: we keep a list of the AI apps permitted to start a connection, and one that is not on it is refused before your sign-in page ever loads.

That is what stops someone sending an admin on your team a Traceten-branded sign-in link from an app you have never heard of, and getting your numbers when they approve it. Claude, Claude Code, Codex, ChatGPT and VS Code are on the list today. Anything else has to be added by us first.

Each entry also fixes **which permissions that app may ask for**. An approved app requesting something outside its entry is refused at the same point, before you are asked to approve anything. So the list bounds not only who can connect, but how much they can request.

### A connection can never issue a credential

`credentials:write` (the permission behind creating a site, minting an API key or a bot token, and registering or rotating a webhook secret) **is not offered when you connect with your account**. It is not a setting you can turn on.

The reason is asymmetry, not distrust. A connection can be stopped by removing the person from your organization, which takes effect within about 30 seconds and needs nobody to go looking for anything. An API key minted through one is not bounded by that or by anything else. It keeps working indefinitely, it does not appear in your AI app alongside the connection, and someone has to go and find it to stop it. A credential on a short leash should not be able to leave behind one on no leash at all.

So a connected assistant asking to mint a key gets a permission error naming `credentials:write`, and should tell you to do it in the dashboard. Everything else (goals, funnels, site settings, editing and testing webhooks) works normally.

### Turning a connection off

<Warning>
  **There is no button that revokes a connection, and a connection does not expire on its own.**
  Checked against our identity provider on 1 September 2026: its account portal has no "authorized
  applications" screen, so you cannot revoke a grant yourself, it offers us no way to revoke one on
  your behalf, and an access token in JWT form cannot be withdrawn once issued. Every connection
  also holds a refresh token (our identity provider issues one to these apps by default and it
  cannot be turned off), so the app replaces its own token before it runs out. **Removing the person
  from your organization is the only thing that ends a connection.**
</Warning>

Three things are worth telling apart.

**Removing the connector in your AI app** stops that app from using the connection. It does not end the grant: the app may still hold a refresh token, and nothing has been withdrawn centrally.

**Removing the person from your organization is the control.** Every request re-checks their membership with our identity provider (reads included, not just writes), so their connection stops working **within about 30 seconds**. Each of our API servers holds its own 30-second view of your membership list, so an unlucky request lands at the far end of that window rather than the near end.

**Waiting is not a control.** A connection nobody touches keeps working indefinitely, because the app refreshes its own access token. The 24-hour token lifetime bounds something narrower and worth knowing separately: an access token **on its own** (copied out of a log or a chat transcript, with no refresh token beside it) stops working within a day.

Two details behind those numbers:

* **Before any write we ask our identity provider whether the token is still good**, and refuse the write if we cannot get an answer. That check catches an expired token and would catch a revoked one if revocation existed; it is not a substitute for removing someone.
* **Reads are answered without that round-trip.** That is what keeps them fast, and it is why the 30-second membership window is the bound on reads rather than something shorter.

If the window matters (a laptop lost, a contractor offboarded), remove them from the organization, and treat everything the connection could reach as already read. There is nothing to rotate for a read-only connection; the exposure is the data itself.

### Write tools stay visible on a read-only key

An assistant connected with a `stats:read` key still sees all 83 tools listed. Calling a write tool fails with a permission error naming the missing permission.

This is deliberate. If the write tools were hidden, your assistant would tell you "Traceten cannot create goals", which is false and unhelpful. Instead it tells you your key is not allowed to, which is true and fixable.

### A dashboard session token is not permission-limited

The permission table above describes API keys. The endpoint also accepts a Clerk **dashboard session token**, because every tool call runs against the same endpoint the dashboard uses and that endpoint has always taken either credential.

A session token carries no permissions of its own: it identifies a person, and that person's account access is what applies. So an assistant given one can reach **every** tool, including the write tools, with no way to narrow it.

This is not a weakness specific to MCP. The same token reaches the same endpoints over plain HTTP, and the checks are the same code. But it means there is only one safe rule: **connect an assistant with an API key, never with a dashboard session token.** A key is the only credential you can scope, and the only one you can revoke without signing yourself out.

### Site-scoped keys

A key restricted to one site reaches only that site. `traceten_sites_list` returns just that one, and any tool naming another site returns "not found" rather than "forbidden", so a key cannot be used to discover which sites exist.

## The confirmation gate

Twelve tools either destroy something, issue a credential, or change how your numbers are measured. Called normally, they **do not act**. They return a preview describing what would happen, and your assistant shows it to you.

| Tool                              | What the preview warns you about                                                  |
| --------------------------------- | --------------------------------------------------------------------------------- |
| `traceten_goals_archive`          | Archiving hides a goal but does not stop collection. Reversible.                  |
| `traceten_funnels_delete`         | Permanent, with no restore. No analytics data is destroyed.                       |
| `traceten_annotations_delete`     | The note's date and current text, and that it disappears for the whole team.      |
| `traceten_annotations_update`     | Only when the text changes: the note's date, its current text and the new text.   |
| `traceten_apikeys_create`         | Which permissions the new key would carry, and that it is shown only once.        |
| `traceten_apikeys_revoke`         | Everything using the key stops working immediately. No grace period, no undo.     |
| `traceten_sites_create`           | A new site, and a live API key returned into your assistant's conversation.       |
| `traceten_webhooks_create`        | The destination URL, and that it starts a continuous outbound flow of your data.  |
| `traceten_webhooks_rotate_secret` | No overlap window: your receiver rejects deliveries until you deploy the new one. |
| `traceten_sites_update`           | Only when it would change the cookie scope. See below.                            |

### Why registering a webhook is gated

`traceten_webhooks_create` is the one to read the preview carefully on. It does not just return a secret: it starts a **continuous outbound flow** of every session Traceten classifies, including the detected source and attributed revenue, to a URL supplied in the call.

Traceten refuses private, loopback and internal addresses at registration, so the endpoint has to be a public HTTPS URL. That leaves two things the product cannot check for you. The first is whether the URL is *yours*. An assistant that has read text from outside your control (a campaign value in your own traffic, a property attached to a conversion event) could be talked into registering someone else's endpoint, and nothing else about your account would look wrong afterwards.

Read the URL character by character before you approve it. Lookalike domains are the whole trick.

The second is that the address check runs at **registration time**. A hostname that is public when you register it but later resolves to a private or internal address is a known residual, and the delivery path does not re-check it.

To go ahead, tell your assistant to proceed. It re-sends the call with `confirm: true` and the change is made.

The preview is a normal successful result, not an error. An assistant that got an error would retry or give up; one that gets a preview shows it to you and waits.

### Why `traceten_sites_update` is conditional

Most site settings are harmless to change and apply immediately. One is not.

`cookie_apex_domain` sets the scope your first-party cookies are written at. Change it and cookies already set under the old scope stop being read, so returning visitors start counting as new and attribution spanning the change cannot be joined up. Nothing already recorded is altered, but your numbers change shape from that point on.

So the gate fires only when the value would actually change, checked against what the site currently has. Renaming a site, or re-sending the same cookie scope, needs no confirmation.

A site's **domain cannot be changed at all**, here or anywhere. It is fixed when the site is created. If you have moved domains, create a new site.

## Secrets

Credentials are returned exactly once, by the tool that creates them, and never again. **All four require confirmation first**, so none of them can hand a secret to an assistant without you approving it:

* `traceten_sites_create` and `traceten_apikeys_create` return a plaintext API key.
* `traceten_webhooks_create` and `traceten_webhooks_rotate_secret` return a webhook signing secret.

No listing tool returns key material. `traceten_apikeys_list` shows prefixes, permissions, site bindings and dates, never a key. Traceten stores only a hash, so a lost key cannot be recovered by anyone, including us.

Three practical consequences:

1. **A secret returned to your assistant enters your conversation.** It may be saved in that client's history. Treat any transcript containing one as sensitive, and revoke and re-mint if you are unsure.
2. `traceten_apikeys_list` requires `config:write`, not `stats:read`, when you authenticate with a key. A credential inventory names every key's permissions and site binding, so a leaked read-only key must not be able to produce a target list.
3. **If you connected with your Traceten account, `traceten_apikeys_list` is refused outright** and returns a permission error. A connection that cannot mint a credential should not be able to inventory them either. The same refusal applies to the bot-token listing on the REST API, which has no tool in this catalogue. View both in the dashboard under **Settings, then API keys**.

## What data leaves your account

Every tool description states this, so your assistant can tell you before it calls. In summary:

| Kind of tool                                                                            | What comes back                                                                                                                                                                                                    |
| --------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Stats, breakdowns, revenue, detection, crawls                                           | Aggregate counts and totals. No rows about individuals.                                                                                                                                                            |
| `traceten_sessions_list`                                                                | **Session-level rows**: the landing page and the exit page, detected source and confidence, device, country **and city**, revenue, active time, plus the `utm_campaign` and `ref` your own visitors' URLs carried. |
| `traceten_sessions_get`                                                                 | **One session in full**: the above plus operating system, browser, referrer and the list of page URLs viewed.                                                                                                      |
| `traceten_sessions_journey`                                                             | **The AI touchpoints before one conversion**, with the credit each gets under four attribution models.                                                                                                             |
| `traceten_visitors_list` / `traceten_funnels_step_visitors` / `traceten_goals_visitors` | **Many people at once**, one row each: an opaque site-scoped handle, first and last seen, visit and pageview counts, engaged time, how they first arrived, device, browser, country, city, and revenue.            |
| `traceten_visitors_get`                                                                 | **One person's whole footprint on this site**: the row above plus their per-day activity and the ids of every visit they made.                                                                                     |
| `traceten_visitors_timeline`                                                            | **One person's event trail**, grouped by visit: the page URLs they viewed, the event names your site recorded, timestamps, amounts, and the `properties` your own code attached. The most granular tool here.      |
| `traceten_ai_crawls_recent`                                                             | Individual crawl hits, including the **crawler's own** user-agent string.                                                                                                                                          |
| `traceten_goals_properties`                                                             | **Property values your own site sent**, as free text.                                                                                                                                                              |
| Configuration and account tools                                                         | Your own settings, plan, limits and member ids.                                                                                                                                                                    |

Traceten does not collect a visitor's name, email address or raw IP address, so no tool can return one. A visitor's IP is hashed with HMAC-SHA-256 under a per-site key at the edge before any storage, and the raw value is never written to storage, logs or disk. There is one deliberate exception and it is not visitor data: network-verified **AI crawler** IP addresses are retained, so a crawler claiming to be a given company can be checked against that company's published ranges. See [what we collect](/privacy/data-collected#ai-crawler-ip-addresses).

For the same reason, the only user-agent string anywhere in this surface belongs to a **crawler**, never a person: `traceten_ai_crawls_recent` returns each AI bot's own declared user agent, which is how the bot identifies itself and is the basis of the verification verdict beside it.

**Two qualifications on "no personal data", both worth reading before you connect an assistant.**

`traceten_goals_properties` returns whatever your own site attached to a conversion event. On ingest, values matching an email address, phone number, payment card or US SSN are replaced with a redaction marker, values are capped at 256 characters, and at most 20 keys per event are kept. A property whose key is exactly `email`, `phone`, `name`, `password`, `token`, `ssn`, `credit_card` or `card_number` is dropped before storage when it arrives from the tracking snippet or from a server SDK. It is not dropped on `/v1/ingest/conversions`, the authenticated ingestion API called with a server API key: there the value is redacted as everywhere else, but a property named `email` is stored under that name. Nothing recognises names, postal addresses or free-text notes. So if your site attaches customer details to goal events under other key names, they will appear here.

The visitor and session tools describe **people's own journeys on one site**, and they link up. `traceten_visitors_list` returns a page of visitors filtered by dimensions you already report on. Each row carries a `handle` that opens with `traceten_visitors_get`, which returns that person's visits. From there `traceten_visitors_timeline` returns the events inside those visits, and any one visit opens in full with `traceten_sessions_get`.

That chain runs in one direction only. There is no tool that takes a session id and returns the person behind it: an assistant reaches a person by listing visitors, never by starting from a visit.

So an assistant with a `stats:read` key can enumerate your audience at person grain and follow any one of them through every visit they made. That is the point of the feature, and it exists so an AI discovery visit can be joined to a purchase days later, which is the question this product answers. It is worth knowing before you connect an assistant.

Three limits on that reach, and they are structural rather than policy:

* **No identity is returned or accepted.** Rows carry an opaque handle, never a visitor identifier, and no tool takes a name, an email address, an IP address or a visitor identifier as an input. Traceten does not store any of them in a form a tool could match.
* **A handle works on one site only.** It is sealed against the site it was issued for, so a handle taken from one site returns `404` on another, and no key links a person's activity across two customers.
* **The reach is the API's.** These tools call the same endpoints a `tk_live_` key already reaches over HTTP. Connecting an assistant does not widen what a credential can see.

## Rate limits

Two limits apply to the MCP endpoint, and a request has to satisfy both:

* **600 requests per minute per network address**, for anyone we cannot identify at the door. It does not depend on your key, so several people behind one office connection share it. **A connection made with your Traceten account is exempt** once we have verified it, because hosted AI apps all reach us from a handful of their provider's addresses, so this limit would otherwise put every customer of that app in one bucket.
* **240 requests per minute per key**, once a valid key is presented. A connection gets the same 240, counted **per person** and again **per connected app**, so a colleague's usage never eats yours and one misbehaving app never eats your whole allowance.

Tool calls that read data also draw on your account's normal read allowance, so a long analysis session is usually bounded by that rather than by either number above.

Each request carries one tool call. Batched JSON-RPC is refused, because a batch is a way to turn one request into hundreds of them.

An assistant that hits a limit gets a clear error with a retry hint, not a truncated or partial answer.

## Revoking access

**If you pasted a key:** revoke it under **Settings, then API keys**. It stops working immediately, everywhere, including any assistant still holding it. Then remove the entry from your client configuration.

**If you connected with your account:** there is nothing to revoke, and nothing to wait for. See [Turning a connection off](#turning-a-connection-off). Remove the person from your organization; that takes effect within about 30 seconds and is the only thing that ends the connection.

## Next

* [Install](/mcp/install)
* [Tools](/mcp/tools)
* [API keys and permissions](/api/authentication)
