# MCP server

> Reference for the CustomerCatalyst MCP server — URL, authentication, scopes, tools and limits.

CustomerCatalyst runs a remote MCP server for AI clients. To connect a client step by step, see [Claude and other AI clients](/integrations/claude-and-mcp/).

| | |
|---|---|
| URL | `https://mcp.customercatalyst.io` |
| Transport | Streamable HTTP |
| Auth | OAuth 2.1 (browser sign-in) or an API key, both as `Authorization: Bearer` |
| Tenancy | Every tool works only on the organization of the connection. No tool takes an organization ID. |

## Authentication

### OAuth (browser sign-in)

For clients that can open a browser. The server publishes its metadata at `https://mcp.customercatalyst.io/.well-known/oauth-protected-resource`; the same host is the authorization server.

- Authorization code flow with PKCE (S256). There is no client secret.
- The client identifies itself with a Client ID Metadata Document URL.
- The user signs in to CustomerCatalyst, picks data types and clicks **Allow**.
- Access tokens last one hour. The client refreshes them by itself; refresh tokens rotate on every use and stay valid for 60 days after their last use.
- If an old refresh token is used again after it was rotated, the connection is revoked.

### API key

For clients that can't sign in through a browser. Create the key under **Integrations › MCP servers › Connect with an API key**, choosing Read and Write per data type. Send it as a header:

```
Authorization: Bearer cc_…
```

The key is shown once and doesn't expire until it is revoked.

## Scopes

A connection is granted read and, optionally, write per data type. These are the scope names the server publishes in `scopes_supported`:

| Scope | Covers | Write tools |
|---|---|---|
| `customer` | Accounts, health scores, revenue, products | Yes |
| `contact` | People at customer accounts | Yes |
| `user` | Team members' names | No |
| `call` | Calls | Yes |
| `meeting` | Meetings and attendees | Yes |
| `task` | Tasks | Yes |
| `note` | Notes and playbook comments | Yes |
| `email` | Email metadata: who, whom, when. Never the message text. | No |
| `opportunity` | Deals and the pipeline | Yes |
| `revenue` | Revenue events and their products | No |
| `playbook` | Playbooks and playbook templates | Yes |
| `success_plan` | Success plans | Yes |
| `metric` | Metric definitions and values over time | No |
| `ticket` | Support tickets | Yes |

A browser sign-in gets write on every granted data type that has write tools; the user can turn it off later under **Edit access**. A tool outside the granted scopes answers `scope_not_granted`.

## Read tools

All `get_*` tools are read-only. Lists are paginated (default 25, at most 100 per page); pass the returned cursor to get the next page and treat it as opaque. Most take an optional `customer_id`.

| Tool | Scope | Returns |
|---|---|---|
| `get_connection_info` | none | Organization name, the connected user, granted read and write scopes, and whether the connection is OAuth or an API key. |
| `get_customer_data` | `customer` | Customers. |
| `get_customer_scores` | `customer` | Usage and engagement scores. |
| `get_products` | `customer` | Your product catalogue (subscriptions and add-ons). |
| `get_contacts` | `contact` | Contacts. |
| `get_users` | `user` | Team members: ID and name only. |
| `get_calls` | `call` | Calls. |
| `get_meetings` | `meeting` | Meetings. |
| `get_tasks` | `task` | Tasks. |
| `get_notes` | `note` | Notes. |
| `get_comments` | `note` | Comments on playbooks. |
| `get_opportunities` | `opportunity` | Opportunities. |
| `get_revenue_events` | `revenue` | Revenue events. |
| `get_playbooks` | `playbook` | Playbooks. |
| `get_playbook_templates` | `playbook` | Playbook templates. |
| `get_success_plans` | `success_plan` | Success plans. |
| `get_metrics` | `metric` | Metric definitions and values over time. |
| `get_tickets` | `ticket` | Support tickets. |
| `get_emails` | `email` | Email metadata: subject, dates, participants. No message bodies. |

People come back as IDs: resolve `owner_id`, `assignee_id` and participant IDs with `get_users`, contacts with `get_contacts`. A `customer_name` of `null` means the connection lacks `customer` read, not that the customer is missing. An archived customer counts as deleted and answers `not_found`.

## Write tools

Write tools take names, not IDs, for customers, people and products, and resolve them inside your organization. A name that matches nothing answers `not_found`; one that matches several answers `ambiguous`. Changes are made at once, as the connected user, with the app's own notifications, reminders and activity. The user needs the **Edit** permission.

| Scope | Tools |
|---|---|
| `customer` | `create_customer`, `update_customer` |
| `contact` | `create_contact`, `update_contact` |
| `call` | `create_call`, `update_call` |
| `meeting` | `create_meeting`, `update_meeting` |
| `task` | `create_task`, `update_task` |
| `note` | `create_note`, `update_note` |
| `opportunity` | `create_opportunity`, `update_opportunity` |
| `success_plan` | `create_success_plan`, `update_success_plan` |
| `playbook` | `apply_playbook`, `add_playbook_task`, `complete_playbook_stage`, `set_playbook_owner`, `add_playbook_member`, `remove_playbook_member`, `share_playbook`, `stop_sharing_playbook` |
| `ticket` | `reply_to_ticket`, `add_ticket_note`, `update_ticket` |

Rules worth knowing:

- **No deletes**, except removing an attendee in `update_call` / `update_meeting`, `remove_playbook_member`, and `stop_sharing_playbook` (removes every customer contact from a playbook).
- **Email goes out** from `reply_to_ticket` (to the requester, from your support address) and `share_playbook` (an invitation to each contact). Neither can be unsent.
- **CRM records.** Calls and meetings synced from the CRM can't be changed (`crm_managed`). For other CRM records, an `update_*` that would be overwritten at the next sync answers `crm_overwrite_warning` and writes nothing; repeat with `accept_crm_overwrite: true` only if the user agrees.
- **Tickets.** `reply_to_ticket` and `update_ticket` work only on tickets that came in through CustomerCatalyst support; `add_ticket_note` works on any ticket, CRM tickets too.
- **Time.** `create_call` and `create_meeting` take a local `date`, `time` and an IANA `timezone` such as `Europe/Istanbul`.

The tool descriptions the server returns are the full reference for each tool's arguments.

## Limits and errors

| | |
|---|---|
| Rate limit | 120 requests per minute per connection. Over it: HTTP `429` with `Retry-After`. |
| Page size | Default 25, at most 100. |
| Cache | Reads may be up to 60 seconds old. |

| Error | Meaning |
|---|---|
| `scope_not_granted` | The connection doesn't have that data type. Grant it under **Edit access**; don't retry. |
| `not_found` | No such record in your organization (also for archived customers). |
| `ambiguous` | A name matched more than one record. |
| `permission_denied` | The connected user isn't allowed to make that change in the app. |
| `crm_managed` | The call or meeting is managed by the CRM. |
| `crm_overwrite_warning` | The change would be replaced at the next CRM sync. Nothing was written. |
| `invalid_arguments` | An argument is missing or invalid. |
