Unified MCP Server
Authentication
There are three authentication options;
1. Private LLM API Authentication for 1 Connection:
Use this option when your application connects directly to the Unified MCP Server or it gives the LLM API the Unified MCP Server remote URL.
This token is NOT safe to give out publically as it is a Unified.to workspace API key and will grant access to all of your connections and Unified.to account.
connection | An end-customer’s connection ID from Unified |
token | Exactly the same as a Unified.to workspace API key |
2. Private Workspace-only Authentication:
Use this option to engage with data in your workspace such as connections, webhooks, API calls, and issues/tickets. This data is configuration data and not your end-customer's data from connections.
token | Exactly the same as a Unified.to workspace API key |
An AI agent without an account can get a workspace API key itself with Agent Signup.
3. Enterprise-managed Authentication:
Use this option when an enterprise end-customer's own identity provider should decide which of their users reach the MCP server, and with what access — instead of you provisioning and handing out Unified.to credentials.
The enterprise's IdP mints an identity assertion (an ID-JAG) for the end user. Your application exchanges that assertion for a Unified.to access token, then uses the token as a bearer credential against the MCP server.
Enterprise-managed authentication is enabled per workspace. Contact Unified.to to turn it on.
Exchanging the assertion
POST /oauth/token as an RFC 7523 jwt-bearer grant:
grant_type | urn:ietf:params:oauth:grant-type:jwt-bearer |
assertion | The ID-JAG minted by the enterprise IdP |
scope | Optional, space-delimited. Unknown scopes are dropped rather than rejected |
The assertion's resource claim is required and decides which API the issued token is good for. To get a token for the MCP server, set it to this server's resource identifier — read that value from resource in the protected-resource metadata rather than hard-coding it, since it follows the hostname you connect to.
A successful exchange returns a standard OAuth token response whose access_token is prefixed ema_:
{
"access_token": "ema_...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "crm.read crm.write"
}
Send it as Authorization: bearer ema_..., with or without a connection parameter:
?connection=<id> | That one connection's tools, narrowed to the token's scopes |
no connection | The workspace's integration data tools, narrowed to the token's scopes. The Core Unified API management tools are not available to an enterprise-managed token |
Tokens are bound to one resource
An enterprise-managed token is not portable between the REST API and the MCP server. A token minted for the MCP server is rejected by the REST API, and one minted for the REST API is rejected by the MCP server. Mint a separate token per resource.
Scopes
* | Everything |
<category>.read | Read access to one data category, eg. crm.read |
<category>.write | Write access to one data category, eg. ats.write |
<category> is a unified data category — crm, ats, hris, accounting, ticketing, commerce, and so on. Categories that expose no unified data objects (passthrough, auth, saml, scim, metadata) carry no scope and are not reachable with an enterprise-managed token; that includes the raw provider tools added by include_external_tools.
Scopes filter the tool list, not just the call: tools/list advertises a tool only when the token's scopes permit calling it, so a tool that would be refused is never offered. A call outside the granted scopes returns 403.
Discovery
/.well-known/oauth-protected-resource/mcp | The MCP server as an OAuth protected resource (RFC 9728) |
/.well-known/oauth-protected-resource | The REST API as an OAuth protected resource |
/.well-known/oauth-authorization-server | The authorization server (RFC 8414) |
An unauthenticated request to /mcp returns 401 with a WWW-Authenticate header naming the protected-resource metadata URL, so a client that auto-discovers authentication can find the rest on its own.
Notes
You can provide the token either as a token URL parameter (eg. ?token={token}) or in the Authorization header as a bearer token (eg. Authorization: bearer {token})
All other parameters must be sent as URL parameters.
Prefer the Authorization header. Authenticating with ?token= still works, but it is deprecated: those responses carry a Deprecation: true header. Enterprise-managed tokens (option 3) advertise header authentication only in their discovery metadata.