> ## Documentation Index
> Fetch the complete documentation index at: https://docs.omni.co/llms.txt
> Use this file to discover all available pages before exploring further.

# createEmbedMcpToken reference - Omni Embed

> Parameters, return value, and error codes for createEmbedMcpToken in the Omni embed SDK.

Reference for `createEmbedMcpToken` in the `@omni-co/embed` SDK. See [Embed user MCP tokens](https://docs.omni.co/embed/customization/ai-chat/your-agent-mcp.md) for setup steps.

## Parameters

`createEmbedMcpToken` accepts the same identity and role parameters as a signed embed URL, plus the parameters that tell the SDK where to send the request. Each identity parameter works the same as the [embed URL parameter](https://docs.omni.co/embed/setup/url-parameters.md) with the same name.

A token updates the embed user the same way an embed URL does, meaning Omni removes groups, attributes, roles, and entity settings that the token doesn't include for every session. See [How sessions update embed users](https://docs.omni.co/embed/setup/url-parameters.md#user-updates) for the full list.

| Parameter | Required? | Description |
| - | - | - |
| [`externalId`](https://docs.omni.co/embed/setup/url-parameters/externalId) |  **Yes** | Identifies the user. Using the same value as your embed URLs makes the token and the embedded iframe one Omni user, and each session replaces the other's permissions. See [How sessions update embed users](https://docs.omni.co/embed/setup/url-parameters.md#user-updates) for more information. |
| [`name`](https://docs.omni.co/embed/setup/url-parameters/name) |  **Yes** | The user's display name |
| `secret` |  **Yes** | An active [embed secret](https://docs.omni.co/embed/admin/secrets.md) |
| `host` or `organizationName` |  **Yes** | Your embed host, such as `myorg.embed-omniapp.co`, or the organization name the SDK builds it from |
| [`connectionRoles`](https://docs.omni.co/embed/setup/url-parameters/connectionRoles) or [`modelRoles`](https://docs.omni.co/embed/setup/url-parameters/modelRoles) |  **Yes** | What the user can query, and with which role |
| `organizationShortId` |  **No** | Required only on a [custom domain](https://docs.omni.co/embed/customization/vanity-domains.md), where the SDK can't derive it from the host |
| [`userAttributes`](https://docs.omni.co/embed/setup/url-parameters/userAttributes) |  **No** | Attribute values for row-level filtering |
| [`email`](https://docs.omni.co/embed/setup/url-parameters/email), [`entity`](https://docs.omni.co/embed/setup/url-parameters/entity), [`groups`](https://docs.omni.co/embed/setup/url-parameters/groups) |  **No** | Identity and grouping, as for an iframe |
| [`entityAiCreditLimit`](https://docs.omni.co/embed/setup/url-parameters/entityAiCreditLimit), the `entityFolder*` parameters, and [`preserveEntityFolderContentRole`](https://docs.omni.co/embed/setup/url-parameters/preserveEntityFolderContentRole) |  **No** | Entity settings, as for an iframe. See the [parameters reference](https://docs.omni.co/embed/setup/url-parameters.md). |

Parameters that only shape an iframe, such as `contentPath`, `theme`, `uiSettings`, `linkAccess`, and `mode`, aren't accepted.

**Required parameters only**

Example `createEmbedMcpToken` call with only the required parameters, for a non-custom domain:

```typescript wrap theme={null}
import { createEmbedMcpToken } from '@omni-co/embed'

// `user` is the signed-in user, from your app's own session
const { accessToken, expiresAt } = await createEmbedMcpToken({
    externalId: user.id,
    name: user.name,
    connectionRoles: {
    'c0f12353-4817-4398-bcc0-d501e6dd2f64': 'RESTRICTED_QUERIER',
    },
    host: 'myorg.embed-omniapp.co',
    secret: process.env.OMNI_EMBED_SECRET!,
})
```

**Custom domain (organizationShortId)**

Example `createEmbedMcpToken` call for a custom domain, which requires including `organizationShortId`:

```typescript wrap highlight={11} theme={null}
import { createEmbedMcpToken } from '@omni-co/embed'

// `user` is the signed-in user, from your app's own session
const { accessToken, expiresAt } = await createEmbedMcpToken({
    externalId: user.id,
    name: user.name,
    connectionRoles: {
    'c0f12353-4817-4398-bcc0-d501e6dd2f64': 'RESTRICTED_QUERIER',
    },
    host: 'analytics.blobsrus.com',
    organizationShortId: 'blobsrus',
    secret: process.env.OMNI_EMBED_SECRET!,
})
```

## Return value

| Field | Description |
| - | - |
| `accessToken` | The token to send as `Authorization: Bearer <accessToken>` |
| `expiresAt` | The time the token expires, as a `Date`. It can stop working earlier if a newer token is minted for the user or the session ends. |
| `resource` | The MCP endpoint the token is for, such as `https://<your-omni-org>.embed-omniapp.co/mcp` |
| `scope` | The OAuth scope Omni granted |

## Error codes

`createEmbedMcpToken` can throw two types of errors: a plain `Error` and `EmbedMcpTokenError`.

### Plain errors

The SDK checks your parameters before it sends a request to Omni. It throws a plain `Error` if:

* `externalId`, `name`, or `secret` is missing
* You pass both `host` and `organizationName`, or neither of them
* You don't pass `connectionRoles` or `modelRoles`
* You use a custom domain and don't pass `organizationShortId`

### EmbedMcpTokenError

An `EmbedMcpTokenError` means that Omni refused the request. The error's `code` property contains the reason, which is one of the values in the following table.

If you [send a direct request](https://docs.omni.co/embed/customization/ai-chat/your-agent-mcp.md#direct-mint) instead of using the SDK, the reason is in the response's `error_reason` property, or in the `error` property if `error_reason` is missing.

| Code | Cause | What to do |
| - | - | - |
| `feature_not_enabled` | Embed MCP tokens aren't enabled for your organization | Reach out to Omni support to have the feature enabled |
| `org_not_enabled` | The **Embed** feature or the **MCP server** setting is turned off for your organization | Reach out to Omni support to have **Embed** enabled. Enable **MCP server** in [**AI Hub > MCP**](https://docs.omni.co/ai/settings/mcp.md#mcp-server). |
| `assertion_rejected` | The `secret` you passed doesn't match any active embed secret in your organization | Check the secret in **Settings > Embed > Admin**. If it was rotated or deleted, use a current secret. |
| `assertion_not_for_this_org` | The `host`, `organizationName`, or `organizationShortId` you passed doesn't belong to the organization that owns the secret | Check that the host belongs to your organization. If you also embed Omni, match the host your embed URLs use. On a custom domain, pass `organizationShortId`. |
| `assertion_expired` | Your server's clock is too far behind or ahead of Omni's | Sync your server's clock |
| `assertion_invalid` | A parameter failed validation, for example an `externalId` that is too long | Fix the parameter named in the error message |
| `assertion_replayed` | The same signed assertion was sent twice | Call `createEmbedMcpToken` again instead of resending a previous request |
| `claims_invalid` | Omni rejected one of the identity or role parameters. The error message includes the parameter name and the reason, for example `connectionRoles or modelRoles is required`. | Fix the parameter named in the error message |
| `rate_limited` | Too many token requests for this user in a short window | Wait `retryAfterSeconds` seconds and reuse the cached token |
| `request_failed` | The SDK couldn't reach Omni before its timeout (`status` is 0), or Omni returned a response the SDK didn't recognize | Retry later |
| `server_error` | An error on Omni's side | Retry later. If it continues, reach out to Omni support. |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.