Announcing CIMD support for MCP Client registration
Learn more

Should you use Front MCP or Front API for building AI Agents?

Vinayak Ravi
Head of Marketing

TL;DR

  • Front's MCP server (open beta, https://mcp.frontapp.com/mcp) publishes 23 tools covering search, conversation timelines, drafts, comments, tags, assignment, and status. The Core API documents more than 200 endpoints across roughly two dozen resource families. Knowledge bases, analytics, message templates, webhooks, contact writes, and inbox administration are Core API only.
  • The identity rule is the real decision point. Front requires that any end user authorizing an OAuth app be an admin, for both private and public apps. The MCP server is the single documented exception: it issues user-scoped tokens, so any teammate can authorize it.
  • That inverts the usual pattern. On the MCP path you get one token per teammate by default. On the Core API path you get an admin-authorized, company-scoped token, and per-user attribution becomes an author_id parameter rather than an identity.
  • Headless agents have a third door. Front's AI agents feature, in closed beta, issues client_credentials credentials that mint roughly 15-minute tokens against the same MCP server, attributed to the agent's own identity rather than a human teammate.
  • Neither path stores, refreshes, or revokes credentials for you. Scalekit's Front and Front MCP connectors hold both credential types in a token vault, resolve the right one per identifier at call time, and log every call with an execution ID, so the MCP versus API choice does not change your auth infrastructure.

Two ways into Front

Your agent needs to work inside Front: read a thread, draft a reply, leave an internal comment, tag and route the conversation. Front now ships two ways in, an OAuth-authenticated MCP server in open beta and the Core API your integrations have used for years. They read the same data and they are not interchangeable. They expose different surfaces, they put a different identity on every action, and one of them has an authorization constraint that quietly decides your architecture. Here is how to pick.

What Front MCP and the Front Core API actually are

Both paths sit on the same conversation store. What differs is the shape of the contract and who is standing behind each call.

Front's MCP server

Front's MCP server is a vendor-hosted endpoint at https://mcp.frontapp.com/mcp, running Streamable HTTP against MCP spec version 2025-11-25. It is in open beta, and Front states plainly that tool names and descriptions are still subject to change.

Auth is OAuth 2.1 with PKCE compatibility, using read, write, and send scopes. Front does not support Dynamic Client Registration (DCR), so the client must be confidential and must send a client ID and secret. Front lists Codex, and any client that depends on DCR, as unable to connect.

Every tool call attributes to a specific Front teammate, and the agent's effective permissions are exactly that teammate's permissions. Full details are in Front's MCP server documentation.

Front's Core API

The Core API is a Bearer-token REST interface at https://api2.frontapp.com, covering accounts, analytics, channels, comments, contacts, conversations, drafts, events, inboxes, knowledge bases, links, message templates, rules, shifts, signatures, statuses, tags, teammates, teams, time off, and views.

Tokens come from one of two places: an API token generated in Front settings, or an OAuth app using the authorization_code grant. Scopes are composed from a feature (access resources, MCP server, application triggers), a namespace (global, shared, or private resources), and a permission set (read, write, delete, send). Reference material lives in Front's Core API documentation.

How the two surfaces are packaged in Scalekit

Scalekit ships them as two separate connectors. The Front MCP connector lists 25 tools under the frontmcp_ prefix, two more than Front's published table, including frontmcp_get_my_identity and frontmcp_move_conversation. The Front connector wraps the Core API as 55 prebuilt tools under the front_ prefix.

Comparing them where it matters for agents

The gap is not a rounding error. It follows a clean line: the MCP server covers what a teammate does inside a conversation, and the Core API covers everything that configures, reports on, or feeds the workspace.

What your agent can actually do

Capability
Front MCP
Front Core API
Search conversations by query and filters
Yes, frontmcp_search_conversations
Yes, front_search_conversations
Read a full conversation timeline in one call
Yes, frontmcp_read_conversation
Partial, stitch messages, comments, and events
Draft a reply
Yes, frontmcp_create_draft
Yes, front_create_draft_reply
Send a message in a single call
No, draft first, then frontmcp_send_message
Yes, front_send_message
Post an internal comment
Yes, frontmcp_add_comment
Yes, front_add_conversation_comment
Tag, assign, archive, snooze
Yes
Partial, snooze runs through conversation reminders
Create or update contacts
No, published tools are read and search only
Yes, front_create_contact, front_update_contact
Create, update, or delete tags
No
Yes, front_create_tag, front_update_tag, front_delete_tag
Knowledge base articles
No
Yes, front_list_kb_articles and the knowledge base endpoints
Import historical messages
No
Yes, front_import_message
Analytics exports and reports
No
Yes, the /analytics endpoints
Event subscriptions and webhooks
No
Yes, application webhooks and rule webhooks

Where a cell names a front_ or frontmcp_ tool, Scalekit ships it prebuilt. The analytics, webhook, and event rows are Core API endpoints with no prebuilt tool, reachable through the proxy call shown later.

Where the MCP ceiling sits

Anything that changes the shape of the workspace lives on the Core API. Inbox and channel administration, teammate groups, shifts, rules, views, and the analytics surface have no MCP equivalent, and that is a design decision rather than a backlog item.

The event story is the sharper limit. The MCP server exposes no subscription primitive, so a triage agent that must react within seconds of an inbound message needs Core API webhooks to know that something happened at all.

The send that takes two calls

frontmcp_send_message accepts exactly one argument, a draftId. The MCP path cannot send in one shot: the agent creates a draft, then queues it. The Core API sends directly with front_send_message or front_reply_to_conversation.

For a human-in-the-loop assistant, the two-step flow is the correct default. For a deterministic pipeline sending hundreds of templated replies, it doubles the call count against a tiered rate limit.

What the beta status actually costs you

Front's help center lists contact updates as supported today, while the developer portal's tool reference exposes contacts as read-only. Treat the tool reference as the contract, and refresh the tool list from the server rather than hardcoding a catalog you captured last month.

The auth path each one puts you on

This is where the two paths stop being a capability comparison and start being an architecture decision.

MCP: any teammate, user-scoped

A Front admin creates a developer app, enables the MCP Server feature, selects the resource permissions, and shares the client ID and secret. After that, each teammate runs their own consent flow, and the token is bound to that teammate.

The admin-selected permissions are a ceiling, not a grant. A teammate who cannot see a private inbox still cannot see it through the agent. What the user cannot do, the agent cannot do.

Core API: admin-authorized, company-scoped

Front's OAuth documentation is explicit: end users authorizing OAuth apps must be admins, for both private and public apps, and the MCP server is the only exception. The Core API path therefore has no per-teammate consent flow to offer.

The resulting token is scoped by namespace instead of by person. Global and shared resources come along by default, and private resources require each teammate to enable API access in their own settings before the token can touch them.

The attribution workaround and what it costs

Front's write endpoints accept an author_id so an agent can act on behalf of a named teammate. Omit it and the comment or message posts as the API token or OAuth client that made the request.

That is attribution by parameter, not by identity. The permission check runs against the token's namespaces and scopes rather than against the named teammate's role, so least privilege becomes something your application enforces instead of something Front enforces for you.

Headless agents get a third door

Front's AI agents feature, currently in closed beta, registers your agent as a named teammate with its own credentials. The agent exchanges a client ID and secret through the client_credentials grant for a bearer token with roughly a 15-minute TTL and no refresh token, then calls the same MCP server with it.

Every action is attributed to the agent's own identity, conversations can be routed to it by rules, and an inactivity timer unassigns it automatically. This is the honest answer to "MCP is interactive only": it is interactive only for human delegation.

Recommended reading: Access Control for Multi-Tenant AI Agents and API Access Patterns for AI Agents.

What you own in production

Front manages the MCP server, its schemas, and its hosting. Everything below is still yours on both paths.

Rate limits are shaped differently

The Core API limit is per company, not per token: 50 requests per minute on Starter, 100 on Professional, 200 on Enterprise, plus a burst allowance equal to half the plan limit; exhaust the burst and it takes ten minutes to return. Conversation search is capped at 40 percent of the company limit. Requests made by a partner integration through OAuth get their own 120 rpm pool per company.

The MCP server uses separate limits, tiered per teammate per minute: 120 for light reads, 30 for heavy reads such as search and timeline fetches, 20 for writes, and 20 for sends. Per-teammate and per-workspace hourly caps apply on top.

The design implication is direct. Ten agents on one company-scoped API token share a single bucket. Ten agents on ten teammate tokens do not.

Token lifetime and refresh

Core API access tokens expire after 60 minutes. The refresh token is valid for six months, and Front returns the same refresh token on every exchange until the final 24 hours of its life, when a new one is issued. Miss that window and the whole authorization flow restarts.

That is a rotation rule you have to encode somewhere. Waiting for a 401 to trigger a refresh gives you retry storms across concurrent agent threads instead of a token. For a deeper look at this problem, see how to handle token refresh for AI agents.

Schema drift and destructive-tool prompts

Every MCP write tool that mutates visible state carries destructiveHint: true, which prompts compliant clients to ask for per-call confirmation. In an interactive assistant that is the behavior you want. In an unattended run it is a stall, so confirm how your client handles the hint before scheduling anything.

When to use Front MCP, when to use the Core API

Most production Front agents end up using both. The split is predictable once you know which identity each action needs.

Use Front MCP when

  • The agent works a teammate's inbox with that teammate present: triaging, summarizing threads, drafting replies for review, posting internal comments for engineering.
  • You want a single call to return the full conversation timeline, including messages, comments, tag and assignment history, and rule actions, rather than stitching three endpoints together.
  • You need per-teammate permission enforcement without building your own inbox access checks, and you want each person to authorize individually without admin rights.
  • You are registering the agent as a named AI teammate that conversations get routed to by rule.

Use the Core API when

  • The agent runs on a schedule with no user in the loop and no AI teammate identity: nightly digests, CSAT sweeps, CRM sync jobs.
  • The work touches surfaces the MCP server does not expose: knowledge base publishing, analytics exports, message templates, contact writes, tag management, inbox and channel configuration.
  • You need to know that something happened, which means application webhooks or rule webhooks rather than polling search.
  • You are importing historical conversations or writing through custom channels, where front_import_message and the channel endpoints are the only route.

The credential problem that exists on both paths

Front decides who an agent is. It does not store, rotate, or revoke anything on your behalf.

The N-credential math

Take a B2B support agent serving 12 customer workspaces with 15 Front teammates each. On the MCP path that is 180 user-scoped grants to hold, refresh, and revoke on offboarding. On the Core API path it is 12 admin-authorized tokens, each on a 60-minute access token and a six-month refresh clock that only rotates in its last 24 hours.

The credential count changes. The infrastructure requirement does not. Both paths hand you a secret and a lifecycle, and neither hands you a vault. This is the same structural problem described in secure token management for AI agents at scale.

What the Scalekit Front connectors handle

Scalekit's Front connector and Front MCP connector run the OAuth flow, encrypt the resulting credentials in a token vault, refresh them before expiry, and resolve the right one per identifier at call time. Tokens never enter the agent runtime or the model context.

Because both connectors share that layer, the MCP versus API decision becomes a tool-selection question rather than an auth-architecture question. The same identifier works across both.

Connecting an agent to Front with Scalekit

Create the connection in the Scalekit dashboard first, then authorize one teammate before writing any agent code. The connection_name in code must match the connection name in the dashboard character for character, which is the most common integration failure.

Install the SDK

pip install scalekit-sdk-python npm install @scalekit-sdk/node

Authorize a teammate and run a scoped tool

import os from scalekit import ScalekitClient scalekit = ScalekitClient( env_url=os.environ["SCALEKIT_ENVIRONMENT_URL"], client_id=os.environ["SCALEKIT_CLIENT_ID"], client_secret=os.environ["SCALEKIT_CLIENT_SECRET"], ) # Must match the connection name configured in the Scalekit dashboard CONNECTION_NAME = "frontmcp" IDENTIFIER = "rhea@acme.com" link = scalekit.actions.get_authorization_link( connection_name=CONNECTION_NAME, identifier=IDENTIFIER, ) print("Authorize Front:", link.link) input("Press Enter after the teammate completes the Front consent flow...") result = scalekit.actions.execute_tool( tool_input={ "query": "billing", "scope": "all_inboxes", "filters": {"status": "open"}, }, tool_name="frontmcp_search_conversations", identifier=IDENTIFIER, ) print(result.execution_id) print(result.data)

One parameter above is worth internalising: scope defaults to my_conversations. Unassigned conversations, which is most of what a triage agent cares about, only appear when you set all_inboxes.

Give a LangChain agent only the Front tools its user authorized

Before the code, the distinction that matters. The agent is not loading a Front tool catalog. list_scoped_tools runs underneath the LangChain adapter and returns the tools this teammate's connected account is authorized to call, each already bound to that account.

from langchain.agents import create_agent tools = scalekit.actions.langchain.get_tools( identifier=IDENTIFIER, connection_names=["frontmcp"], page_size=50, ) agent = create_agent( model="anthropic:claude-sonnet-4-5", tools=tools, system_prompt=( "You triage a Front inbox. Search with scope=all_inboxes to include " "unassigned conversations. Draft replies, never send them. Post an " "internal comment with your reasoning before you assign anything." ), ) response = agent.invoke({ "messages": [{ "role": "user", "content": "Find open conversations mentioning churn in the last 48 hours, " "comment on each with a recommended next step, and assign the " "riskiest one to the account owner.", }], }) print(response["messages"][-1].content)

For more on how LangChain tool calling works and where it needs augmentation, see LangChain Tool Calling: How It Works, Where It Stops, and How Scalekit Completes It.

Run the full tool loop from TypeScript

The same pattern in TypeScript against the Anthropic SDK, with the loop shown end to end.

import Anthropic from '@anthropic-ai/sdk'; import { ScalekitClient } from '@scalekit-sdk/node'; const scalekit = new ScalekitClient( process.env.SCALEKIT_ENVIRONMENT_URL!, process.env.SCALEKIT_CLIENT_ID!, process.env.SCALEKIT_CLIENT_SECRET!, ); const anthropic = new Anthropic(); // Must match the connection name configured in the Scalekit dashboard const CONNECTION_NAME = 'frontmcp'; const identifier = 'rhea@acme.com'; const scoped = await scalekit.tools.listScopedTools(identifier, { filter: { connectionNames: [CONNECTION_NAME] }, pageSize: 50, }); const tools = scoped.tools.map((tool) => ({ name: tool.name, description: tool.description, input_schema: tool.inputSchema as Anthropic.Tool['input_schema'], })); const messages: Anthropic.MessageParam[] = [ { role: 'user', content: 'Summarize the oldest open conversation in the Support inbox and comment with next steps.', }, ]; while (true) { const response = await anthropic.messages.create({ model: 'claude-sonnet-4-5', max_tokens: 2048, tools, messages, }); messages.push({ role: 'assistant', content: response.content }); if (response.stop_reason !== 'tool_use') { console.log(response.content); break; } const toolResults: Anthropic.ToolResultBlockParam[] = []; for (const block of response.content) { if (block.type !== 'tool_use') continue; const result = await scalekit.actions.executeTool({ toolName: block.name, toolInput: block.input as Record<string, unknown>, identifier, connector: CONNECTION_NAME, }); toolResults.push({ type: 'tool_result', tool_use_id: block.id, content: JSON.stringify(result.data), }); } messages.push({ role: 'user', content: toolResults }); }

Reach a Core API endpoint no tool covers

The 55 prebuilt tools on the front connector do not cover every endpoint, and the events and analytics surfaces are the usual gaps. The proxy call uses the same connected account, so the credential still never lands in agent code.

response = scalekit.actions.request( connection_name="front", # the Core API connector, not frontmcp identifier="acme-workspace", path="/events", method="GET", ) print(response.status_code, response.json())

Scoping Front tools with a Virtual MCP server

A standard MCP connection exposes every tool it has. A Front drafting copilot that needs four of them gets all of them, and pays for the rest in context on every single run.

One server definition, per-user session tokens

Virtual MCP servers let you declare exactly which connections and which tools an agent role sees. You create the server once and get a static mcp_server_url; before each run you mint a short-lived session token bound to one user.

from datetime import timedelta from scalekit.actions.models.mcp_config import McpConfigConnectionToolMapping vmcp = scalekit.actions.mcp.create_config( name="front-triage-agent", connection_tool_mappings=[ McpConfigConnectionToolMapping( connection_name="frontmcp", tools=[ "frontmcp_search_conversations", "frontmcp_read_conversation", "frontmcp_add_comment", "frontmcp_tag_conversation", ], ), ], ) token = scalekit.actions.mcp.create_session_token( mcp_config_id=vmcp.config.id, identifier=IDENTIFIER, expiry=timedelta(minutes=30), ).token mcp_server = { "url": vmcp.config.mcp_server_url, "headers": {"Authorization": f"Bearer {token}"}, }

Why this matters for multi-tool Front agents

The triage agent above cannot send a message, delete a draft, or move a conversation, because those tools are not on its server. Least privilege is enforced at the tool level rather than by prompt instruction.

The token cost is the second half. Roughly 40 tools at about 200 tokens each burns close to 8,000 tokens before the agent does any work; scoping to five or ten cuts that overhead by around 80 percent. Tool bloat is an accuracy problem and a cost problem, and surface reduction fixes both.

The multi-tenant property is the third. One server definition serves every user, and the per-run session token decides whose Front account the call lands in. There is no per-user server to deploy, host, or maintain.

Observability: what each Front tool call leaves behind

Front's own audit trail will show you a teammate archiving a conversation. It will not tell you that an agent did it, on whose behalf, or which run it belonged to.

Attribution on every call

Every execute_tool call through Scalekit is recorded with the identifier, the connected account, and an execution ID, and the auth logs separate failures by source and export to your SIEM. "What did this agent do in Front for this customer last Tuesday" becomes one query instead of a correlation exercise. For a full treatment of why this matters, see Agent Tool Observability: Your Agent Is Running. Is It Actually Working?

Where the trail breaks without it

The failure mode is quiet rather than loud. A revoked grant returns an empty result set, the agent treats empty context as valid state, and routing decisions run on no data with no exception anywhere in the chain.

Attribution at the tool-call layer is what turns that into a visible event. More on the pattern in agent tool observability and tool call failures in production.

Which one to build against

If a teammate is present and the work happens inside a conversation, build on the MCP server. It is the only Front surface that gives you per-user consent without admin rights, per-teammate rate limits, and a timeline in one call.

If the agent runs on a schedule, reacts to events, or touches anything above the conversation layer, build on the Core API and accept the admin-authorized, company-scoped token that comes with it. If it needs both, use both, and put the credential layer underneath rather than beside them.

The tool surface will keep moving while the MCP server is in beta. The credential lifecycle will not, and that is the part worth building on infrastructure you do not have to revisit.

Build your Front agent

Start with the connector docs: Front MCP connector, Front connector, or browse all connectors. Pricing is on the pricing page.

If you would rather start from a working shape, the support triage agent, support ticket automation agent, and customer escalation patterns all map onto a Front inbox with minimal changes.

Building something on Front and want a second pair of eyes on the auth design? Join the Scalekit Slack community, or talk to us for help today.

No items found.
Agent
Auth Quickstart
On this page
Share this article
Agent
Auth Quickstart

Acquire enterprise customers with
‍zero upfront cost.

Every feature unlocked. No hidden fees.