---
name: unified-mcp-connection
description: >-
  Give an LLM or AI agent tool access to one end-customer's SaaS account
  (CRM, ATS, HRIS, accounting, ticketing, …) through the Unified.to MCP server
  in connection mode: build the connection-scoped MCP URL, pick the right
  authentication (workspace key, signed user token, or enterprise-managed
  token), limit tools with permissions / tools / hide_sensitive, and wire it
  into the Anthropic, OpenAI, Gemini, Cohere or Groq APIs, Claude.ai, Claude
  Desktop or Cursor. Use when a coding task builds an AI feature or agent on
  top of a customer's connected data, or when connection-specific tools such
  as `list_candidates` or `list_crm_contacts` should be called through MCP.
license: MIT
metadata:
  category: mcp
  mcp_url: https://mcp-api.unified.to/mcp
  docs: https://docs.unified.to/mcp/overview
  docs_index: https://docs.unified.to/llms.txt
---

# Use the Unified.to MCP server for a connection

In **connection mode** the Unified MCP server exposes one end-customer
connection's integration-specific tools — for a HubSpot connection, tools to
list and create CRM contacts, deals and companies; for Greenhouse, jobs,
candidates and applications. Which tools appear depends on what the
integration supports and which permissions the connection was authorized with.
Each tool call counts as one API request on the Unified.to plan.

Managing the workspace itself (listing connections, webhooks, logs) is
**Core mode** — see the `unified-mcp-core` skill
(https://docs.unified.to/skills/unified-mcp-core/SKILL.md).

Source of truth: https://docs.unified.to/mcp/overview, /mcp/authentication,
/mcp/server-options and /mcp/installation. When in doubt, check them (or
`search_docs` on the Core MCP server) instead of guessing.

## Step 1: Gather the inputs

1. **Connection ID** — created when the end-user authorized an integration
   (see the `unified-quickstart` skill). Usually stored against the app's
   user/account. If the Core MCP server is connected,
   `list_unified_connections` (filter by `external_xref` or `categories`)
   finds it.
2. **Region** — the host must match the workspace's region:

   | Region | Endpoint                            |
   | ------ | ----------------------------------- |
   | US     | `https://mcp-api.unified.to/mcp`    |
   | EU     | `https://mcp-api-eu.unified.to/mcp` |
   | AU     | `https://api-au.unified.to/mcp`     |

   Streamable HTTP at `/mcp` is the only transport; `/sse` returns `410`.
3. **Who holds the URL** — the developer's backend, or the end-customer (or a
   third-party LLM client acting for them). This decides authentication.

## Step 2: Choose authentication

| Option                          | URL / headers                                                                   | When                                                                 |
| ------------------------------- | ------------------------------------------------------------------------------- | -------------------------------------------------------------------- |
| **Workspace key + connection**  | `…/mcp?connection=<connection_id>` with `Authorization: Bearer <workspace key>` | The developer's own server calls the LLM API. **Never** expose it — the key grants the whole account |
| **Signed user token**           | `…/mcp?token=<connection_id>-<nonce>-<signature>`                               | The URL is given to an end-customer or pasted into Claude.ai / Cursor. Grants only that connection |
| **Enterprise-managed (`ema_`)** | `Authorization: Bearer ema_…`, optional `?connection=`                          | An enterprise customer's IdP decides who gets access. Enabled per workspace by Unified.to |

Get a signed user token URL from Core MCP `get_unified_connection_mcp_url`
with `mode: "user"`, or from the Unified API. Rules:

- Put credentials in the `Authorization` header, not `?token=`, wherever the
  client allows it (`?token=` is deprecated). The signed user-mode URL is the
  exception — it is designed to be pasted as-is.
- All other options are URL query parameters.
- Keep the workspace key server-side in an env var (`UNIFIED_API_KEY`); never
  send it to a browser, log it, or commit it.

**Enterprise-managed tokens:** exchange the IdP's ID-JAG at `POST /oauth/token`
(`grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer`, `assertion`,
optional `scope` such as `crm.read ats.write` or `*`). The assertion's
`resource` claim must be the MCP server's resource identifier — read it from
`/.well-known/oauth-protected-resource/mcp` rather than hard-coding it. A token
minted for MCP is rejected by the REST API and vice versa. Scopes filter the
tool list; passthrough, auth, saml, scim and metadata tools (including
`include_external_tools`) are unreachable, and Core management tools are never
available to an `ema_` token.

## Step 3: Limit the tools

Most models degrade badly with many tools (some cap at 10–20). Always narrow
the set with URL parameters:

| Parameter                | Effect                                                                                     |
| ------------------------ | ------------------------------------------------------------------------------------------ |
| `permissions`            | Comma list of Unified scopes, e.g. `crm_contact_read,crm_deal_read`                        |
| `tools`                  | Comma list of tool IDs (wildcards allowed via `get_unified_connection_mcp_url`), e.g. `list_*` |
| `hide_sensitive=true`    | Strips PII (names, emails, phones, …) from results before the model sees them             |
| `defer_tools`            | `all` or tool IDs the client should load lazily                                            |
| `aliases`                | `word:alias1,alias2;word2:alias3`, e.g. `employee:user,person` for better matching         |
| `include_external_tools` | Also expose the vendor's raw API as tools (more power, more tools)                         |
| `disable_events=true`    | Don't offer MCP Events (`events/*`, change notifications) on this server                   |

Start read-only (`*_read` permissions) unless the feature must write, and add
`hide_sensitive=true` when the use case doesn't need personal data. To see
exactly what a URL exposes, call `tools/list` over MCP or `GET /tools` (below).

The server also offers **MCP Events** (`events/list`, `events/poll`,
`events/subscribe`): event types such as `crm_contact.created`, delivered by
poll or as Standard Webhooks–signed POSTs to an `https` URL. Clients that
support the extension use them automatically; see
https://docs.unified.to/mcp/overview#events-webhooks-for-agents.

## Step 4: Wire it into the client

### Anthropic Messages API (MCP connector — no tool loop needed)

```typescript
const response = await anthropic.beta.messages.create({
    model: 'claude-opus-5-5',
    max_tokens: 1024,
    messages: [{ role: 'user', content: 'List open jobs and summarize the newest candidates' }],
    mcp_servers: [
        {
            type: 'url',
            url: `https://mcp-api.unified.to/mcp?connection=${connectionId}&permissions=ats_job_read,ats_candidate_read`,
            name: 'unified',
            authorization_token: process.env.UNIFIED_API_KEY, // sent as Authorization: Bearer
        },
    ],
    tools: [{ type: 'mcp_toolset', mcp_server_name: 'unified' }],
    betas: ['mcp-client-2025-11-20'],
});
```

Every `mcp_servers` entry must be referenced by an `mcp_toolset`. Allowlist
tools there with `default_config: { enabled: false }` plus `configs`. The
response contains `mcp_tool_use` / `mcp_tool_result` blocks followed by the
answer. Not available on Bedrock or Vertex — use the tool loop below there.

### OpenAI Responses API (remote MCP)

```python
resp = client.responses.create(
    model="gpt-4.1",
    tools=[{
        "type": "mcp",
        "server_label": "unified",
        "server_url": f"https://mcp-api.unified.to/mcp?connection={connection_id}",
        "headers": {"Authorization": f"Bearer {os.environ['UNIFIED_API_KEY']}"},
        "require_approval": "never",
    }],
    input="list the candidates and analyse their resumes",
)
```

### Any model, your own tool loop (`/tools` endpoints)

For Gemini, Cohere, Grok, Groq, Bedrock/Vertex, or whenever your code must
log or approve each call:

1. `GET https://mcp-api.unified.to/tools?connection=<id>&type=<anthropic|openai|gemini|cohere|grok|groq>`
   (plus `permissions` / `tools` / `aliases`) with the `Authorization` header
   → tool definitions shaped for that provider.
2. Pass them as the model's `tools` / function declarations.
3. For each tool call the model returns, `POST /tools/{id}/call` with the same
   connection/auth query and the arguments object as the JSON body. The result
   is `{ content: [{ type: 'text', text }], structuredContent }`.
4. Return the result as the provider's tool-result message and loop.

Tool calls are rate-limited per workspace before they run — handle HTTP `429`
with backoff.

### End-user clients (signed user token only)

- **Claude.ai**: Settings → Connectors (custom) → URL
  `https://mcp-api.unified.to/mcp?token=<connectionID>-<nonce>-<signature>`.
- **Cursor**: `.cursor/mcp.json` → `{ "mcpServers": { "<app-name>": { "url": "<signed URL>" } } }`.
- **Claude Desktop** (stdio): `npx -y mcp-remote <signed URL>` as the command.
- **Claude Code**: `claude mcp add --transport http <app-name> "<signed URL>"`.

Never hand an end-customer a URL or config that contains the workspace API key.

## Step 5: Verify

1. List the tools (`tools/list`, `GET /tools`, or your client's `/mcp` view)
   and check only the intended ones appear.
2. Make one read call against a **Sandbox** connection first.
3. If Core MCP is available, confirm the calls with `list_unified_apicalls`
   (`connection_id`, `type: "mcp"`).

Troubleshooting: "not found" → wrong region host or connection ID. `401` →
bad/rotated key, or the connection's credentials expired (end-user must
re-authorize). `403` → scope not granted (connection permissions or `ema_`
token scopes). Missing tool → integration doesn't support it, or
`permissions`/`tools` filtered it out. `410` → still on `/sse`. For more see
https://docs.unified.to/skills/unified-debug-webhooks-connections/SKILL.md.

## Related skills

- Core (workspace) MCP: https://docs.unified.to/skills/unified-mcp-core/SKILL.md
- Getting connections in the first place: https://docs.unified.to/skills/unified-quickstart/SKILL.md
- Category data models (to explain tool results): the `unified-crm`, `unified-ats-jobboard`, `unified-hris`, … skills listed at https://docs.unified.to/skills
