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

# MCP Server

> Connect Wavelength to Claude, Cursor, ChatGPT, or any MCP-compatible client, and ask questions about your accounts in plain English.

<Note>
  **Read-only.** The Wavelength MCP server can look things up. It cannot send an email, change a field, or delete anything.
</Note>

## Before you start

* A Wavelength account with an active login.
* An MCP-compatible client: Claude (desktop, web, or Code), Cursor, ChatGPT, or your own client built on the MCP SDK.
* MCP is enabled for all Wavelength organizations by default — there is nothing to switch on. If a connection fails with "mcp is not enabled for this organization", MCP has been paused for your org; contact support.

You sign in with your normal Wavelength login. You do not need an API key.

## Server details

| Field | Value |
| - | - |
| Server URL | `https://mcp.wavelength.cx/mcp` |
| Transport | Streamable HTTP |
| Auth | OAuth 2.1 (browser sign-in) |
| Access | Read-only |

## Setup

<Tabs>
  <Tab title="Claude (desktop or web)">
    <Steps>
      <Step title="Open Settings → Connectors">
        Find the **Connectors** section in your Claude settings.
      </Step>

      <Step title="Add a custom connector">
        Click **Add custom connector**.
      </Step>

      <Step title="Enter the server details">
        Name: `Wavelength`. URL: `https://mcp.wavelength.cx/mcp`.
      </Step>

      <Step title="Connect and approve">
        Click **Connect**. A browser window opens; sign in to Wavelength and approve.
      </Step>

      <Step title="Confirm">
        The connector shows as connected, with the Wavelength tools listed.
      </Step>
    </Steps>
  </Tab>

  <Tab title="Claude Code">
    ```bash theme={null}
    claude mcp add --transport http wavelength https://mcp.wavelength.cx/mcp
    ```

    Then run `/mcp` inside Claude Code and choose **Authenticate** for `wavelength`.
  </Tab>

  <Tab title="Cursor">
    **Settings → MCP → Add new MCP server**, or add to `~/.cursor/mcp.json`:

    ```json theme={null}
    {
      "mcpServers": {
        "wavelength": {
          "url": "https://mcp.wavelength.cx/mcp"
        }
      }
    }
    ```

    Restart Cursor, then click **Sign in** next to the Wavelength server.
  </Tab>

  <Tab title="ChatGPT">
    **Settings → Connectors → Create**, using the same URL. Sign in when prompted.
  </Tab>

  <Tab title="Any other MCP client">
    Point it at `https://mcp.wavelength.cx/mcp` over Streamable HTTP. The server advertises its authorization server at:

    ```
    https://mcp.wavelength.cx/.well-known/oauth-protected-resource
    ```

    An unauthenticated request returns `401` with a `WWW-Authenticate` header pointing at that document — that response starts the standard OAuth 2.1 flow. Dynamic client registration is supported.
  </Tab>
</Tabs>

## What you can do with it

Everything below works today. The tool named on each line is what answers it — you never call tools by name yourself, but knowing which one runs tells you what the answer is built from.

### Prepare for your day

| Ask | What comes back | Tool |
| - | - | - |
| *"What meetings do I have this week?"* | Your booked meetings, each with the account it belongs to | `get_my_week` |
| *"What do I need to know before my 2pm?"* | The same meeting plus its pre-meeting brief | `get_my_week` |
| *"What did I have last week?"* | Past meetings — the window looks backward as well as forward, up to 30 days either way | `get_my_week` |

Meetings are the ones you are the assignee on. Scoped to you, not your org.

### Get up to speed on an account or a person

| Ask | What comes back | Tool |
| - | - | - |
| *"Give me a brief on Vanta."* | Health, current CTA, 2 recent meeting notes, 5 recent interactions, up to 10 deals, up to 10 contacts — in one call | `get_brief` |
| *"Who is Jane Smith and what account is she on?"* | Their role, account, and details | `get_brief` |
| *"Who at Flosum do we talk to?"* | Every contact on the account, with role and email | `list_contacts` |
| *"What's the account CTA for Acme?"* | The current call to action, if there is one | `get_brief` |

Every section of a brief reports an exact total, like `"deals": "10 of 47"`, so you always know when you are seeing a capped view rather than everything.

### Work your book

| Ask | What comes back | Tool |
| - | - | - |
| *"Which of my accounts are at risk and renew in the next 60 days?"* | Thin account rows plus an exact total | `list_accounts` |
| *"Enterprise accounts I haven't talked to in 30 days"* | Same, filtered on last interaction | `list_accounts` |
| *"Accounts tagged Expansion in the onboarding stage"* | Same, filtered on tags and stage | `list_accounts` |
| *"Accounts where \[your custom attribute] is X"* | Same, filtered on your org's own attributes | `list_accounts` |

Filterable by health pulse, renewal date, last interaction, tier, stage, company type, tags, custom attributes, and whether the account is yours. At least one filter is required, and 25 rows come back per call.

### Look at deals

| Ask | What comes back | Tool |
| - | - | - |
| *"Open deals closing this quarter"* | Deals with stage, amount, close date, account | `list_deals` |
| *"Deals over \$50k in Negotiation"* | Same, filtered on amount and stage | `list_deals` |
| *"What's open on Acme?"* | Same, narrowed to one account | `list_deals` |

Sorted by close date, newest first, with an exact total and paging. It lists deals; it does not total them.

### Find what was actually said

| Ask | What comes back | Tool |
| - | - | - |
| *"What did we say to Acme about the SSO request?"* | Matching threads by meaning, scoped to that account | `search` |
| *"What came up about pricing in Vanta's meetings?"* | Matching meeting notes and recordings | `search` |
| *"What are people asking about billing this month?"* | Matching support threads across the org, by meaning and keyword | `search` |
| *"What's escalating on the Support team right now?"* | Same, narrowed to one team | `search` |
| *"Find the thread where I promised them a migration date"* | Matches across the org, folding in your own mailbox for anything not linked to an account | `search` |
| *"Pull the full transcript of that call"* | The complete note, summary, action items, and transcript | `get_content` |
| *"Show me that whole email thread"* | The message-by-message thread, oldest first, plus topic, category and attributes | `get_content` |

Search covers one corpus per call — `interactions` (email and support threads) or `notes` (meeting notes and recordings). With an account, `interactions` search is scoped to it. With no account, it searches the whole organization — or one team, if you name one — by both meaning and keyword. Personal email that was never linked to an account is only ever visible to its owner, so your own mailbox is folded into that same org-wide result rather than being a separate mode. Search finds the item; `get_content` reads it.

### Filter tickets and threads by field

| Ask | What comes back | Tool |
| - | - | - |
| *"What open requests are assigned to me?"* | Matching interactions, newest first, with a total | `list_interactions` |
| *"How many tickets did Acme open last month?"* | Just the count, when the number is the answer | `list_interactions` |
| *"Unassigned support threads from the last week"* | Same, filtered on assignee and window | `list_interactions` |
| *"Everything from Zendesk on this account"* | Same, filtered on source | `list_interactions` |
| *"Tickets tagged 'Refund Request'"* | Same, filtered on topic | `list_interactions` |
| *"Tickets categorized OPS ESCALATION"* | Same, filtered on category | `list_interactions` |
| *"Open tickets on the Support team"* | Same, filtered on team | `list_interactions` |

Filter on status, assignee (`"me"`, `"unassigned"`, or a teammate), source, account, team, topic, category, and time window. Defaults to the last 90 days. Each row carries `topic`, `bot_category`, `owner_replies`, `customer_replies`, and any attributes, in addition to the usual fields. 25 rows come back per call; page past that with `offset`. Use this when the question is about fields; use `search` when it is about wording.

<Info>
  **Nothing is silently dropped.** If a row is withheld — the only case today is a colleague's personal email that was never linked to an account — the response says so via `privacy_filtered_count` and a `note`, rather than quietly returning fewer rows than `total_count` implies.
</Info>

### Get defined numbers

| Ask | What comes back | Tool |
| - | - | - |
| *"What's our average first response time this month?"* | The figure plus its definition inline | `get_metric` |
| *"How many SLA breaches last quarter, by team?"* | Same, filtered by team | `get_metric` |
| *"Average resolution time for tickets from Intercom"* | Same, filtered by source | `get_metric` |

Five support metrics, filterable by team, source, assignee, and date window. Each result states what it counted and what it excluded. See the [full list](#defined-support-metrics).

### Speak your organization's language

| Ask | What comes back | Tool |
| - | - | - |
| *"What counts as at risk here?"* | Your org's actual definition, not a generic one | `search_semantics` |
| *"What does this health driver measure?"* | The same | `search_semantics` |
| *"Did you mean Acme Corp or Acme Industries?"* | Every candidate, so the model can pick from context | `resolve` |
| *"What ticket categories do we use?"* | Every configured category name for your org | `resolve` |

`resolve` runs automatically behind the other tools — you rarely ask for it directly. It is what lets you say "Vanta" instead of pasting an id, and it is also how you look up the exact wording of a ticket topic or category before filtering `list_interactions` or `search` on it.

### The typical loop

Start with your week, pull a brief for each account you are meeting, then dig into the underlying conversations when something needs a closer look. Most sessions are `get_my_week` → `get_brief` → `search` → `get_content`.

<Info>
  **One difference you may notice.** MCP can surface meeting notes that the Wavelength web app currently hides. Notes ingested from some notetakers are marked inactive in the app but are still real, still yours, and still useful context — so MCP reads them rather than pretending they don't exist. If a note shows up here that you can't find in the web app, that is why, not a bug.
</Info>

## Tools

All tools are read-only, and all are scoped to your organization automatically. You never pass an organization or user id — the server takes both from your sign-in.

| Tool | What it does | Worth knowing |
| - | - | - |
| `wavelength_v1_api_read_get_my_week` | Your booked meetings over a window, each with its account and pre-meeting brief. | 7-day window by default, 30 max, forward or backward. Only meetings you are the assignee on. |
| `wavelength_v1_api_read_get_brief` | A fixed-size snapshot of one account or one person: health, current CTA, 2 recent notes, 5 recent interactions, up to 10 deals, up to 10 contacts. | Every section states an exact total, like `"deals": "10 of 47"`, so a capped section is never mistaken for an empty one. Bounded on purpose — cheap enough to call before every meeting. |
| `wavelength_v1_api_read_list_deals` | Deals across your organization, filtered by stage, amount, close date, or account. | Sorted by close date, newest first, with an exact total and paging. Lists deals; does not total them. Deal type is not filterable or returned yet. |
| `wavelength_v1_api_read_list_contacts` | Every contact on one account, with role and email. | Requires an account. Exact total, pages via `offset`. |
| `wavelength_v1_api_read_list_accounts` | Your book filtered by health pulse, renewal date, last interaction, tier, stage, company type, tags, custom attributes, or ownership. | 25 rows per call. At least one filter is required — "list all my accounts" is refused on purpose. Too broad a filter returns a count and a request to narrow, not a truncated list. |
| `wavelength_v1_api_read_search` | Meaning-based search over one corpus per call: `interactions` (email and support threads) or `notes` (meeting notes and recordings). | Scope to an account for meaning-based results. With no account, `interactions` searches org-wide — or one team, with `teams` — by both meaning and keyword. Personal email never linked to an account stays visible only to its owner, folded into the same result rather than a separate mode. `notes` still requires an account in this release. Returns summaries; use `get_content` to read the full thing. |
| `wavelength_v1_api_read_list_interactions` | Structured filtering over tickets, email threads, and conversations by status, assignee, source, account, team, topic, category, or time window. | Last 90 days unless you say otherwise. `assignee` takes `"me"`, `"unassigned"`, or a teammate. Rows carry `topic`, `bot_category`, `owner_replies`, `customer_replies`, and attributes. 25 rows, newest first, with a total; page past that with `offset`. `count_only` returns just the number. Over 1000 matches, it refuses and asks you to narrow. Any row withheld by the email-privacy rule is counted, not silently dropped — see `privacy_filtered_count`. |
| `wavelength_v1_api_read_get_content` | The full text behind a search result. | Notes return the full note, summary, action items, and transcript where one exists. Interactions return the message-by-message thread (up to 40 messages, oldest first, each tagged customer or support), plus status, source, topic, category, reply counts, and attributes — `messages_truncated` is set if a thread ran longer than that. Subject to the email rule below. |
| `wavelength_v1_api_read_get_metric` | A defined support metric, with its definition returned inline. | Five metrics, listed below. Filterable by team, source, assignee, and window. Nothing outside that list is answerable. |
| `wavelength_v1_api_read_search_semantics` | Looks up what Wavelength's own terms mean — at risk, health drivers, tiers, SLAs, how filters combine. | Reads a fixed table, not your data. This is what stops the model inventing its own definition of your vocabulary. |
| `wavelength_v1_api_read_resolve` | Turns free text into a specific company, contact, team, teammate, interaction topic, or interaction category. | Runs automatically behind the other tools. `kind: "topic"` and `kind: "category"` are their own namespace — separate from account-level labels — so you can look up the exact wording of a topic or category before filtering on it. On an ambiguous name it returns every candidate rather than guessing. |

### What you can see in email

Everything that is not email — support tickets, Slack-sourced threads, and the rest — is visible to everyone in your organization, as it is in the app.

Email is narrower:

| Email | Who can read it |
| - | - |
| Linked to an account | anyone in your organization |
| Not linked to an account | only the person whose mailbox it is |

So a colleague's personal correspondence never appears in your results, and yours never appears in theirs. A shared mailbox such as `support@` belongs to no individual, so mail there that was never linked to an account is not reachable through these tools at all — open it in Wavelength instead.

One practical consequence: `get_content` can return fewer items than the ids you gave it. That is this rule at work, not an error.

### Defined support metrics

Numbers come from a fixed list, not from a general "sum this column" tool. All five are filterable by team, source, assignee, and date window:

| Metric | What it measures |
| - | - |
| `avg_first_response_time` | Mean time from a customer's first message to the first human reply. |
| `avg_response_time` | Mean time a ticket sat in needs-response before being picked up. Not the same as first response — don't use them interchangeably. |
| `avg_resolution_time` | Mean time from a ticket's first message to close, over tickets **closed** in the window. |
| `sla_breach_count` | Number of SLA breaches in the window. |
| `avg_sla_breach_duration` | Mean overrun on breached SLAs. |

Every result carries its own definition inline, including what it excludes. All are wall-clock, not business hours.

<Warning>
  **Not available**: deal totals, pipeline sums, ARR, account-level aggregates, and timer totals. If a number is not in the table above, the server says so rather than approximating it. That is on purpose: a plausible wrong number in a QBR is worse than no number.
</Warning>

## How your data is scoped

* **Everything is limited to one organization** — the one on your sign-in. There is no cross-organization read, search, or comparison, and no tool accepts an organization as a parameter.
* **The server knows who you are, not just which org you are in.** Your sign-in gives it both. Anything phrased as "mine" resolves to you personally: `get_my_week` returns only meetings you are the assignee on, and `assignee: "me"` on `list_interactions` and `assignee_scope` on `list_accounts` mean you. A no-account `search` over interactions reaches the whole org (or one team, if you name one), not just your inbox — your own mailbox is simply the subset of that result that includes your personal email, since email never linked to an account is otherwise visible only to its owner.
* **Account data itself is organization-wide.** Any connected user can read any account in their organization, including other reps' notes and meetings. This matches what the Wavelength web app already allows. The one exception is email that was never linked to an account, which stays private to its owner — see [What you can see in email](#what-you-can-see-in-email). If your organization needs tighter limits than that, talk to us before rolling MCP out broadly.
* **Authorization is checked on every request**, not once per session. Token validation is cached briefly, so revocation can take up to about a minute to take effect.
* **Read-only.** No tool can change anything in Wavelength.

## Limits

### Rate limits

There are two layers. Every request passes through a connection limit first; the tool then checks its own tier budget.

#### Connection limits

| Limit | Value |
| - | - |
| Per organization | 120 requests / minute |
| Per connection (each connected client) | 60 requests / minute |

This is the ceiling in practice — a burst of cheap lookups hits the 120/minute org limit long before it hits the read tier's 100/second. Exceeding it returns HTTP `429`.

#### Tool tiers

Tier limits are **per organization** — shared across everyone in your org who has connected — and are set per tier, because the tools do very different amounts of work.

| Tier | Limit | Tools |
| - | - | - |
| Read | 100 / second | `resolve`, `get_my_week`, `get_content`, `list_interactions`, `list_deals`, `list_contacts` |
| Brief | 10 / second | `get_brief` |
| Search | 300 / minute | `list_accounts` |
| Semantic search | 2 / second | `search` |
| Reporting | 2 / second | `get_metric` |
| — | connection limits only | `search_semantics` |

`search_semantics` carries no tier of its own because it does not query anything — it looks up Wavelength's own vocabulary in a fixed table held in memory. Limiting it would only push the model into guessing what your terms mean, which is the failure it exists to prevent. It still passes through the connection limits above like every other call.

**Do not confuse it with `search`**, which does search your data and sits on the tightest tier in the table.

Tiers are counted separately, so heavy searching never uses up the budget for cheap lookups.

If you hit a limit you get a clear error naming the tier and how many seconds to wait — never a silent truncation and never an empty result.

### Other limits

| Limit | Value |
| - | - |
| Rows per list or search call | 25 |
| Messages per interaction in `get_content` | 40, oldest first — `messages_truncated` is set if a thread ran longer |
| Meeting window | 30 days max |
| Time per tool call | 30 seconds |

**Results are never silently cut short.** Every list response tells you both how many rows came back and how many matched in total. If a query is too broad, the server says so and tells you how to narrow it.

## Troubleshooting

<AccordionGroup>
  <Accordion title="&#x22;Not enabled for this organization&#x22;">
    Your admin has not turned MCP on. Contact them, or email support.
  </Accordion>

  <Accordion title="The sign-in window opens and closes but nothing connects">
    Check that you signed in with the same email you use for Wavelength, and that the account belongs to the organization you expect.
  </Accordion>

  <Accordion title="&#x22;No results&#x22; for something you know exists">
    Two common causes: the name did not resolve (try the exact account name, or ask the model to resolve it first), or the time window excluded it (search defaults to a recent window — say "in the last year" explicitly).
  </Accordion>

  <Accordion title="Answers stop working mid-session">
    Your token expired or was revoked. Reconnect from your client's connector settings.
  </Accordion>

  <Accordion title="Slow responses on very large books">
    Broad filters over tens of thousands of accounts take longer. Narrowing the filter is faster than paging.
  </Accordion>
</AccordionGroup>

## FAQ

<AccordionGroup>
  <Accordion title="Does this cost extra?">
    Talk to your Wavelength account team.
  </Accordion>

  <Accordion title="Can I use it with my own agent?">
    Yes — it is a standard MCP server over Streamable HTTP with OAuth 2.1. Nothing about it is Claude-specific.
  </Accordion>

  <Accordion title="Is my data sent to Anthropic / OpenAI?">
    Yes, in the sense that any tool result your client requests is passed to the model you are using, the same as anything you paste into a chat. The MCP server itself does not send your data anywhere else.
  </Accordion>

  <Accordion title="Why can't it write an email for me?">
    This release is deliberately read-only. Write support is the next thing we are scoping.
  </Accordion>

  <Accordion title="Will the tool names change?">
    The `wavelength_v1_` prefix is a version marker. Names within `v1` are stable; a breaking change ships as `v2` alongside it.
  </Accordion>
</AccordionGroup>

## What it can't do (yet)

| Not supported | Why |
| - | - |
| Sending or drafting email, updating fields, creating records | The server is read-only in this release. |
| Ranking your book ("what should I work on today?") | You can *filter* your book by your own criteria; Wavelength does not rank it for you. |
| Searching meetings by participant across the org | You can see your own booked meetings. Org-wide meeting search is not available yet. |
| Filtering deals by deal type | Not filterable and not returned yet. Coming in a later release. |
| Deal totals, pipeline sums, and ARR | Only the named metrics above are available. Anything not on that list is not answerable here. |
| Semantic search inside a long call recording | Recordings match as a whole, not passage by passage. |
| "Every email mentioning X" | Email search finds threads owned by the people you scope to. Someone who was only cc'd may not appear. |
| Slack conversations outside tickets | Not indexed for search. |
| Guaranteed verbatim message text | `get_content` returns each message in a thread, but prefers a generated summary over the raw body when one exists — you get the gist of each message, not always its literal wording. |

## Support

Email **[support@wavelength.cx](mailto:support@wavelength.cx)**. Include your organization name, the client you are using, and the question you asked.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.