---
updatedAt: 2026-08-05T18:42:41.000Z
---

Fetch the complete documentation index at: https://dev.frontapp.com/llms.txt. Use this file to discover all available pages before exploring further.

# MCP Server

## Connect AI assistants to Front via the MCP server (open beta)

<Callout icon="👍" theme="okay">
  ### Open beta

  This feature is in open beta. Everyone has access, but bug fixes, improvements, and other details are still being worked on. Your feedback in our [community group](https://community.front.com/groups/beta-mcp-server-83) is invaluable for shaping the direction of the MCP server!
</Callout>

Front's MCP server (`mcp.frontapp.com/mcp`) lets AI agents act on Front conversation data using a single OAuth-authenticated endpoint. Agents authenticate as a specific Front user, with permissions matching that user's role (user-scoped authorization).

This article covers how to connect any MCP-compatible client to Front using an OAuth app you create yourself in the Front developer settings. For the user-facing overview, official directory listings (Claude, and others coming), and use case inspirations for Front teammates, see the general [Help Center article on the MCP server](https://help.front.com/en/articles/4883136).

> **Looking for examples before you build?**
>
> The [MCP space in the Front Community](https://community.front.com/groups/beta-mcp-server-83) has workflow walkthroughs, sample prompts, video demos, and a feedback channel where the team responds directly. If you want to see what's possible before you set anything up, start there.

## Overview

|                      |                                                                                                                                                                                                                                                                                                    |
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Endpoint**         | `https://mcp.frontapp.com/mcp`                                                                                                                                                                                                                                                                     |
| **Transport**        | Streamable HTTP                                                                                                                                                                                                                                                                                    |
| **MCP spec version** | 2025-11-25                                                                                                                                                                                                                                                                                         |
| **Auth**             | OAuth 2.1 + PKCE compatability<br /><br />**Note:** Front does not support Dynamic Client Registration. Your AI assistant must support a ***confidential connection that sends an OAuth client ID and secret***. Some popular AI assistants are currently [not compatible](#incompatability-list). |
| **Identity model**   | Per-user tokens — every tool call attributes to a specific Front teammate                                                                                                                                                                                                                          |
| **Scopes**           | `read`, `write`, `send`                                                                                                                                                                                                                                                                            |

The identity model is the part most worth internalizing: the agent's effective permissions are exactly the authorizing teammate's permissions. If the teammate can't see an inbox, the agent can't either.

### Incompatability list

Some AI assistants do not support confidential connections. These clients cannot connect to the Front MCP server:

* Codex
* Any client that requires Dynamic Client Registration (DCR)

## Use cases

A few patterns this surface unlocks:

* **Custom agent harnesses.** Wire Front into Claude Code, Cursor, or an in-house orchestrator alongside your other tools (GitHub, Notion, Jira, Slack, Linear, your CRM) for cross-system workflows: customer reports a bug, agent reproduces it, identifies the suspect PR, and posts an internal comment with the diagnosis.
* **Multi-tenant partner integrations.** Publish an OAuth app that any Front admin can install. Each end user authorizes individually.
* **Triage and routing agents.** Scheduled or event-driven agents that search the inbox, classify by topic, assign to the right teammate, and draft a first-pass reply for human review.
* **Conversation insights and enrichment.** Pull conversation data into your own pipelines for analysis, KB extraction, or feedback ingestion. The conversation timeline includes messages, comments, tags, assignment history, and more in a single stream.

## Set up the MCP server connection

<Callout icon="📘" theme="info">
  ### Connect Claude from the official directory

  If you're using Claude, we recommend you connect the Front MCP server from the [official directory](https://claude.ai/directory/connectors/front). If you are not using Claude, follow the steps in this section to set up the MCP server as a custom connector.<br /><br />If you install Claude from the official directory, you do not need to complete either step in this section (**Set up the Front developer app** **with an OAuth feature** or **Connect your AI assistant)**.
</Callout>

Connecting an AI assistant to Front's MCP server has two general steps: create a Front developer app, configure its OAuth scopes, and then connect your AI client using the app's credentials.

<Callout icon="👍" theme="okay">
  After you complete these two steps, your teammates will be able to find the Front MCP server in your AI assistant and connect to it without having to create a developer app or configure the connection details on the AI client side.
</Callout>

### 1. Set up the Front developer app with an OAuth feature

<Callout icon="👍" theme="success">
  ### These instructions are completed in your Front settings (Settings > Company > Developer)
</Callout>

1. [Create a developer app](https://dev.frontapp.com/docs/create-and-manage-apps) and give it an appropriate name (e.g. "Claude MCP Connector")
2. Click **Add feature** in the **Features** tab.
3. Add an [OAuth feature](https://dev.frontapp.com/docs/create-and-manage-apps#obtain-oauth-credentials-for-your-app) to your developer app.
   1. Note the **Client ID** and **Client secret**.
   2. Add a **redirect URL** that corresponds to the AI assistant you're sending data to. For example, as of this writing, the Claude documentation instructs you to use `https://claude.ai/api/mcp/auth_callback` for most versions of Claude. If you're using Claude Code or similar CLI, you should enter `http://localhost/callback`. This URL will allow you to connect to a randomly generated local port.
   3. Enable **MCP Server** under **Feature access**.
      <Callout icon="📘" theme="info">
        **Only enable the MCP Server option**. Enabling other types of feature access can lead to 403 errors when you authorize through your AI assistant.
      </Callout>
   4. Skip the **Namespace access**. This section is disabled when you enable the MCP Server option above.
   5. Under **Resource permissions**, select the resources available to the MCP server.
      <Callout icon="👍" theme="okay">
        Request the narrowest set that covers your use case. A read-only research agent only needs `read`. A drafting copilot needs `read` + `write` but not `send`. Only request `send` if your agent will actually send messages.
      </Callout>
      <Callout icon="📘" theme="info">
        Remember that despite the permissions selected in the OAuth client, agents connecting to the MCP server will be further limited by the subset of data and permissions that the user who connects the agent has access to.
      </Callout>

<br />

### 2. Connect your AI assistant

<Callout icon="👍" theme="success">
  ### These instructions are completed in your AI assistant, not Front
</Callout>

Once the app is configured, connect from your MCP client so that you and your team can view the Front MCP server. Once it is set up for your company, individual teammates can find the MCP server in the list of connectors and authorize it for their individual accounts, but they will not need to configure the technical details involving the server URL and credentials, as explained in this section.

The exact configuration syntax for initial configuration varies by AI client, but every client will need:

* The MCP server URL: `https://mcp.frontapp.com/mcp`
* Your app's `client_id` and `client_secret`
* The OAuth scopes the app should request
* If your AI assistant requests information about our OAuth URLs, use the following values:<br />
  | URL                 | Value                                      |
  | ------------------- | ------------------------------------------ |
  | Authorization       | `https://app.frontapp.com/oauth/authorize` |
  | Token & refresh URL | `https://app.frontapp.com/oauth/token`     |

<Callout icon="📘" theme="info">
  **Use the UI or command line to connect the MCP server**

  We recommend using your AI assistants UI menus to connect the Front MCP server, or terminal commands for CLI assistants. Configuring JSON files is not recommended for most users because varying local paths and environment settings can cause issues. We've provided two recommended examples for Claude below, plus a general JSON shape if you have to modify your AI assistant's configuration file directly.

  If you have issues connecting the MCP server, please reach out to your AI assistant's support team and share this documentation with them so they can recommend the correct steps.
</Callout>

#### Example for Claude (Web and Desktop)

1. Open **Settings** and navigate to the **Connectors** tab (or the **Customize** page).
2. Click **+** and then **Add custom connector**.
3. Enter the server URL: <https://mcp.frontapp.com/mcp>
4. Click **Advanced** settings and enter your OAuth Client ID and Client Secret.
5. Click **Add** and complete the OAuth authentication flow.

<Callout icon="📘" theme="info">
  You may have to close out Claude and re-open it before it sees the new MCP server and has you authorize permissions.
</Callout>

#### Example for Claude Code

1. In Front, make sure your OAuth feature contains the `http://localhost/callback` redirect URL.
2. In your terminal, run the following command and enter your client secret when prompted:
   <Callout icon="📘" theme="info">
     Including `MCP_CLIENT_SECRET` is optional. If you don't include it, Claude should prompt you for it after. If it fails to do so, then include it inline.
   </Callout>
   <Callout icon="👍" theme="okay">
     You can name the MCP server something other than `front` if you desire.
   </Callout>
   ```Text Terminal
   MCP_CLIENT_SECRET=<your-client-secret> claude mcp add --transport http --client-id <your-client-id> --client-secret front https://mcp.frontapp.com/mcp
   ```
3. Exit Claude and re-open it in your terminal so that it pulls the latest list of servers.
4. Run **/mcp** to see a list of MCP servers.
5. Select the server you added and choose to **Authenticate** it.
6. Authorize in your browser.

#### Example for generic MCP server config (confirm with your client's docs on exactly how you structure and pass these properties) - Not recommended for most users

```json
{
  "mcpServers": {
    "front": {
      "url": "https://mcp.frontapp.com/mcp",
      "transport": "streamable-http",
      "oauth": {
        "client_id": "<your-client-id>",
        "client_secret": "<your-client-secret>",
        "scopes": ["read", "write", "send"]
      }
    }
  }
}
```

### Tips for authorization

<Callout icon="📘" theme="info">
  **Match your client's requested scopes to your OAuth app.** By default, many AI assistants (including Claude) will request every scope the MCP server supports. If those scopes exceed what you enabled on the Front OAuth app, the authorization flow may return an error.

  If you encounter this error, configure your client to only request the scopes your app is set up for. In Claude, for example, this is set in the client's JSON config — see Claude's [docs on restricting OAuth scopes](https://code.claude.com/docs/en/mcp#restrict-oauth-scopes) for the exact syntax. Other clients have similar settings; check their documentation if you hit an authorization error.
</Callout>

When the client first connects, each user will be redirected to Front to log in and consent to the requested scopes. The resulting token is bound to that specific Front user and they can only act on data their Front role allows.

<Callout icon="📘" theme="info">
  **A note on enterprise deployment:** If your AI assistant is centrally managed (e.g. Claude Enterprise, ChatGPT Enterprise), your IT team may need to allow the connection or distribute the app credentials. Each end user still completes the OAuth consent flow individually — this is how Front guarantees that every tool call has a real, attributable user behind it.
</Callout>

## Rate limits

The MCP server uses separate rate limits from the Core API and other Front platform features, so you don't need to worry about stability issues for your existing integrations. We will publish more specifics on rate limits once the MCP server exits beta.

## Tool reference

<Callout icon="📘" theme="info">
  **Please note that the tools are still under development for the beta**. The exact list, names, and descriptions are subject to change as we evolve them in response to feedback and further development.
</Callout>

<Callout icon="📘" theme="info">
  The MCP server currently exposes the following tools. To get the most updated list, ask your AI agent to refresh the tool list.

  All write tools that mutate state in user-visible ways carry `destructiveHint: true`, which prompts MCP clients to request per-call user confirmation.
</Callout>

***

## Conversations

| Tool                         | Type                    | Description                                                                                                                                                                                          | Flags                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| ---------------------------- | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `search_conversations`       | Read                    | Full-text and filter search across conversations                                                                                                                                                     | `query` — full-text search string (optional if at least one filter is provided)<br />`scope` — `my_conversations` (default), `my_workspace`, or `all_inboxes`; **must set to&#x20;**`all_inboxes`**&#x20;for unassigned conversations to appear**<br />`filters.inboxId` — restrict to inbox `inb_xxx`<br />`filters.teammateId` — restrict to assigned teammate `tea_xxx`<br />`filters.teamId` — restrict to team `tim_xxx`<br />`filters.tags` — array of tag IDs `tag_xxx` (matches all)<br />`filters.status` — one of `open`, `archived`, `trashed`, `spam`<br />`filters.after` / `filters.before` — date range `YYYY-MM-DD`<br />`cursor` — pagination cursor from previous call                                                                    |
| `read_conversation`          | Read                    | Full timeline of a conversation, its contents, and its header information: subject, message content, internal comments, tag/assignment changes, status transitions, rule actions, and other metadata | `conversationId` *(required)* — public conversation ID `cnv_xxx`<br />`limit` — max timeline entries to return (default 50, max 200)<br />`cursor` — pagination cursor for timeline entries                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `create_draft`               | Write                   | Creates a draft reply on an existing conversation, or a new outbound conversation. Does not send.                                                                                                    | `body` *(required)* — draft body text<br />`conversationId` — public conversation ID `cnv_xxx` for a reply draft; omit to create a new outbound draft (requires `channelId`)<br />`channelId` — channel ID `cha_xxx`; required for new outbound drafts, optional override for reply drafts<br />`bodyFormat` — `html` (default), `markdown`, or `plain`<br />`inReplyToMessageId` — pin to specific message; defaults to latest<br />`replyAll` — reply to all original recipients (default `true`)<br />`shared` — share with teammates (default `false`)<br />`to` — recipients for new outbound drafts (channel handles)<br />`subject` — subject line for new outbound email drafts<br />`cc` / `bcc` — CC/BCC recipients for new outbound email drafts |
| `update_draft`               | Write                   | Updates the body, subject, or recipients of an existing draft. Uses version token for conflict detection.                                                                                            | `draftId` *(required)* — public draft message ID `msg_xxx` from `list_drafts` or `read_message`<br />`version` *(required)* — opaque version token from `read_message.draft_version`; fails if draft changed since read<br />`body` — new draft body; omit to leave unchanged<br />`bodyFormat` — `html` (default), `markdown`, or `plain`<br />`subject` — new subject for email drafts; omit to leave unchanged<br />`to` / `cc` / `bcc` — replace recipient lists; pass `[]` to clear<br />`channelId` — override the sending channel `cha_xxx`<br />`takeOver` — if `true`, claim authorship from another teammate before editing                                                                                                                       |
| `delete_draft`               | Write                   | Discards an unsent draft owned by the authenticated teammate. Owner-only.                                                                                                                            | `draftId` *(required)* — public draft message ID `msg_xxx` from `list_drafts` or `read_message`<br />`version` *(required)* — opaque version token from `read_message.draft_version`; fails if draft changed since read                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `send_message`               | Send<br />(destructive) | Sends a draft message created via `create_draft`. The draft must be in compose state, owned by the authenticated teammate, and have at least one recipient.                                          | `draftId` *(required)* — draft ID `msg_xxx` as returned by `create_draft`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| `update_conversation_status` | Write (destructive)     | Archives or reopens a conversation. Can also set a ticket status. If the requester is the assignee, the change is global; otherwise only their view is affected.                                     | `conversationId` *(required)* — public conversation ID `cnv_xxx`<br />`status` — `open` or `archived` (provide either this or `statusId`, not both)<br />`statusId` — ticket-status tag `sts_xxx` from `list_statuses`; sets ticket status and updates open/archived state to match                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `assign_conversation`        | Write                   | Assigns a conversation to a teammate, or unassigns it                                                                                                                                                | `conversationId` *(required)* — public conversation ID `cnv_xxx`<br />`assigneeId` *(required)* — teammate ID `tea_xxx` to assign, or `null` to unassign                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |

***

## Messages

| Tool             | Type | Description                                                                                                                                                                                                                                                  | Flags                                                                                            |
| ---------------- | ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------ |
| `read_message`   | Read | Fetches a single message by ID with full content. Returns body (quoted replies stripped), recipients, attachments, author, draft status, and delivery error if applicable. Use this to get the full message body when `read_conversation` truncates content. | `messageId` *(required)* — message ID `msg_xxx`                                                  |
| `get_attachment` | Read | Gets a single attachment on a message or comment. Returns metadata (filename, content type, size) plus a short-lived download URL. Attachment IDs come from `read_message`.                                                                                  | `attachmentId` *(required)* — public attachment link ID `fil_xxx`, as returned by `read_message` |

***

## Comments

| Tool          | Type  | Description                                                                                                                  | Flags                                                                                                                                             |
| ------------- | ----- | ---------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `add_comment` | Write | Posts an internal comment on a conversation. Not visible to customers. Supports `@mentions` auto-resolved to teammate names. | `conversationId` *(required)* — public conversation ID `cnv_xxx`<br />`body` *(required)* — comment body text; `@mentions` resolved automatically |

***

## Tags

| Tool               | Type  | Description                                                                       | Flags                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| ------------------ | ----- | --------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `list_tags`        | Read  | Lists all tags in the workspace, including hierarchy                              | `name_query` — filter by tag name keywords<br />`inbox_ids` — filter to tags that apply to specific inboxes `inb_xxx`<br />`all_inboxes` — filter to tags that apply to all inboxes (`true`/`false`)<br />`is_visible_in_conversation_lists` — filter by list visibility<br />`parent_tag_id` — filter by parent tag `tag_xxx` for hierarchical tags<br />`limit` — max results (default 50, max 100)<br />`offset` — pagination offset |
| `tag_conversation` | Write | Adds or removes tags on a conversation. Idempotent — safe to call multiple times. | `conversationId` *(required)* — public conversation ID `cnv_xxx`<br />`addTags` — array of tag IDs `tag_xxx` to add<br />`removeTags` — array of tag IDs `tag_xxx` to remove                                                                                                                                                                                                                                                            |

***

## Contacts & Accounts

| Tool              | Type | Description                                                         | Flags                                                                                                                            |
| ----------------- | ---- | ------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `search_contacts` | Read | Searches contacts by name, email, or handle                         | `query` *(required)* — search string (name, email, or handle)<br />`cursor` — pagination cursor from previous call               |
| `read_contact`    | Read | Returns a full contact record including handles and linked accounts | `contactId` *(required)* — public contact card ID `crd_xxx`                                                                      |
| `search_accounts` | Read | Searches accounts (companies) by name                               | `name_query` — filter by account name keywords<br />`limit` — max results (default 10, max 25)<br />`offset` — pagination offset |
| `read_account`    | Read | Returns the full account (company) record                           | `account_id` *(required)* — numeric account ID or public account ID `acc_xxx`                                                    |

***

## Organization

| Tool             | Type | Description                                                                                                             | Flags                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| ---------------- | ---- | ----------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `list_inboxes`   | Read | Lists inboxes accessible to the authenticated user                                                                      | `name_query` — filter by inbox name keywords<br />`access_mode` — `everyone` or `restricted`<br />`ai_enabled` — filter to AI-enabled inboxes (`true`/`false`)<br />`ticketing_enabled` — filter to ticketing-enabled inboxes (`true`/`false`)<br />`business_hours_enabled` — filter by business hours status<br />`global_rules_enabled` — filter by company rules status<br />`teammate_ids` — filter to inboxes accessible by specific teammates<br />`circle_ids` — filter to inboxes accessible by specific teammate groups<br />`limit` — max results (default 25, max 50)<br />`offset` — pagination offset |
| `list_channels`  | Read | Lists channels accessible to the authenticated user. Use to discover channel IDs before calling tools that require one. | `name_query` — filter by channel display name or address keywords<br />`inbox_ids` — filter to channels belonging to specific inboxes `inb_xxx`<br />`types` — filter by channel type (e.g. `email`, `chat`, `sms`, `gmail`, `twilio`, etc.)<br />`account_statuses` — filter by channel account status (`ok`, `quarantined`, `degraded`, `offline`, `deleted`)<br />`limit` — max results (default 25, max 50)<br />`offset` — pagination offset                                                                                                                                                                   |
| `list_teammates` | Read | Lists all teammates and their roles in the workspace                                                                    | `name_query` — search by name or email keywords<br />`statuses` — filter by account status: `active`, `pending`, `pending_email`, `blocked` (defaults to active statuses)<br />`limit` — max results (default 10, max 25)<br />`offset` — pagination offset                                                                                                                                                                                                                                                                                                                                                         |
| `list_teams`     | Read | Lists all teams in the workspace                                                                                        | `name_query` — filter by team name or alias keywords<br />`limit` — max results (default 10, max 25)<br />`offset` — pagination offset                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| `list_statuses`  | Read | Lists the company's ticket statuses. Returns empty when ticketing is not enabled.                                       | `name_query` — filter by status name keywords<br />`limit` — max results (default 50, max 100)<br />`offset` — pagination offset                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `list_drafts`    | Read | Lists in-flight draft messages authored by the authenticated teammate                                                   | `limit` — max drafts to return (default 50, max 200)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |

## Troubleshooting

### `401 Unauthorized` on every request

The token is invalid, expired, or has been revoked. Common causes:

* The user revoked the app's access in Front's connected apps settings.
* A workspace admin uninstalled the OAuth app entirely.
* The access token expired and the refresh flow didn't fire. Re-authenticate to mint a new token.

### `403 Forbidden` on a tool that worked before

The token has scopes for some tools but not the one being called. For example, a `read`-scoped token will get `403` on `add_comment`. Re-authorize the user and request the broader scope set on consent.

This also fires if the authenticated Front user lost access to the relevant inbox, team, or resource between authorization and the tool call. Permissions are enforced at call time against the user's current Front role.

### `429 Too Many Requests`

Rate limits are tiered per teammate per minute:

* Light reads (`list_*`, `get_*`): 120/min
* Heavy reads (`search_conversations`, `read_conversation`): 30/min
* Writes (drafts, comments, tags, assignment, status, contacts): 20/min
* Send (`send_reply`): 20/min

Additional caps apply at the per-teammate (1,000/hour) and per-workspace (10,000/hour) level. The response includes a `Retry-After` header and an `x-ratelimit-tier` header indicating which tier was exceeded.

If you're seeing rate-limit errors during normal operation, the most common cause is a polling loop that's tighter than it needs to be. Approval-by-polling loops should generally poll on the order of seconds-to-minutes, not sub-second.

## Feedback

To share feedback during this beta, please [join our community group](https://community.front.com/groups/beta-mcp-server-83) and create a new post.

***