> For the complete documentation index, see [llms.txt](https://docs.elimity.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.elimity.com/mcp-reference-manual/step-by-step-deployment-guide.md).

# Step-by-step deployment guide

{% hint style="info" %}
This guide is only relevant for customers deploying the Elimity Insights MCP server on-prem. For our SaaS customers we can perform most of this work behind the scenes.
{% endhint %}

## 1. Setting up an authorization server

The first step in deploying the Elimity Insights MCP server is setting up an OAuth2 authorization server. This server is needed for two reasons:

1. To authenticate requests from MCP clients (e.g. Claude, ChatGPT) to the MCP server (via the [authorization code flow](https://oauth.net/2/grant-types/authorization-code/)).
2. To authenticate requests from the MCP server to Elimity Insights (via the [token exchange flow](https://oauth.net/2/token-exchange/)).

The diagram below shows how these two flows fit into the full request path:

```mermaid
sequenceDiagram
    participant C as MCP-Client
    participant CI as MCP-Client-idp
    participant S as MCP-Server
    participant SI as MCP-Server-idp
    participant EI as Elimity-Insights

    C->>CI: 1. SSO Dance
    CI->>S: 2. SSO Dance
    S->>C: 3. SSO Dance
    C->>S: 4. HTTP Request with access token
    S->>SI: 5. Exchange access token
    SI->>S: 6. New access token for Elimity Insights
    S->>EI: 7. HTTP request with exchanged token

```

In theory these two tasks could each be handled by a different authorization server, but in practice using one single authorization server for both is often the most simple solution. More specifically, we recommend [Auth0](https://auth0.com/) as they have good support for both flows but any OAuth2 authorization server meeting these requirements should work:

* The authorization code flow for a client that authenticates with a client secret
* Resource indicators ([RFC 8707](https://www.rfc-editor.org/rfc/rfc8707)), so that a token requested for the MCP server URL gets exactly that URL as its audience
* JWT access tokens, with signing keys published at a JWKS endpoint
* Token exchange ([RFC 8693](https://www.rfc-editor.org/rfc/rfc8693)) on behalf of the user

In this guide we will use Auth0 as an example when describing setup steps for the authorization server.

**Note:** The authorization server used for MCP is independent from whichever identity provider Elimity Insights uses for its own web application logins (configured via `oidcIssuer`). This is illustrated below.

```mermaid
graph LR
  ElimityIDP["Your identity provider (SAML, OIDC, ...)"] --> |Users log in to the web application| ElimityInsights[Elimity Insights]
  MCPIDP["MCP identity provider"] --> |MCP clients authenticate| ElimityInsights[Elimity Insights]
  
```

### 1.1 Setting up an application for the MCP client

As mentioned above, the MCP client authenticates to our MCP server by walking through an OAuth2 authorization code flow at the authorization server. To do this, the MCP client usually needs a client ID and client secret, which typically requires creating an application at the authorization server first. In the case of Auth0 we recommend registering a regular web application as described in [their official documentation](https://auth0.com/docs/get-started/auth0-overview/create-applications/regular-web-apps). Here are some specific attention points:

1. Enable [the Resource Parameter Compatibility profile](https://auth0.com/ai/docs/mcp/guides/resource-param-compatibility-profile) in your Auth0 tenant
2. Make sure you [create a new API](https://auth0.com/docs/get-started/auth0-overview/set-up-apis) for the MCP server first
3. Use the MCP server URL as identifier for the new API you create, including `https://` and the `/mcp` path (e.g. `https://mcp.elimity.example.com/mcp`). If you don't have this URL yet, deploy the MCP server first
4. Make sure the new application has 'User-Delegated API Access' to this API

In general make sure the application allows the `authorization_code` grant type and supports authentication with a client secret. Also take care to configure the correct callback URL, which depends on your MCP client. The table below lists some unauthoritative examples:

| MCP client | Callback URL                                        |
| ---------- | --------------------------------------------------- |
| ChatGPT    | `https://chatgpt.com/connector/oauth/{callback_id}` |
| Claude     | `https://claude.ai/api/mcp/auth_callback`           |

Securely note down the newly created application's client ID and secret. You'll enter them in the MCP client in step 1.2.

### 1.2 Setting up the MCP client

With the client ID and secret from step 1.1 you can now set up the MCP client. The exact setup steps are client-specific, please consult your AI tool's official documentation for detailed information. As an example we mention some attention points when performing this setup in a Claude organization (based [their official documentation](https://support.claude.com/en/articles/11175166-get-started-with-custom-connectors-using-remote-mcp#h_3d1a65aded)):

1. Use the MCP server URL as the connector URL, e.g. `https://mcp.example.elimity.com/mcp`&#x20;
2. Use the 'Advanced settings' to enter your aforementioned client ID and secret
3. Leave 'register one automatically' unchecked

### 1.3 Setting up an application for the MCP server

The final setup step related to MCP authorization is making sure the MCP server can exchange the token it receives from the MCP client for a different token to authenticate itself against Elimity Insights. Here we'll also need a client ID and secret and thus typically a new application at the authorization server. In the case of Auth0, we recommend setting up an API and a custom client as described in [their official documentation](https://auth0.com/docs/secure/call-apis-on-users-behalf/on-behalf-of-token-exchange#prerequisites). Again we list some special attention points:

1. Make sure you create a new API for Elimity Insights first. Its identifier is the value you'll use for `tokenExchangeAudience` below and for `mcpJwtValidation.audience` in Elimity Insights
2. Create the new 'Custom API client' application from the API for the MCP server you created in step 1.1. This link can't be changed afterwards
3. You need to grant this application 'User-Delegated API Access' for the newly created API from the first point
4. Enable 'On-Behalf-Of Token Exchange' in the application's settings

More generally you should make sure the application allows the `urn:ietf:params:oauth:grant-type:token-exchange` grant type and supports authentication with a client secret. Of course the application should also recognise the tokens issued for the (other) application from step 1.1, which might require complex configuration if you're using two different authorization servers.

Securely note down the newly created application's client ID and secret. These go into the MCP server configuration below, not into the MCP client.

## 2. Configuring the MCP server

Having performed the necessary authorization setup we can now start configuring the MCP server itself. To do this, mount a JSON configuration file at `/app/config/config.json` with the properties listed below. The following snippet provides a good starting point:

```json
{
  "authorizationServers": ["https://example.eu.auth0.com"],
  "baseUrl": "https://mcp.elimity.example.com",
  "insightsBaseUrl": "https://elimity.example.com",
  "jwtValidationAudience": "https://mcp.elimity.example.com/mcp",
  "jwtValidationIssuer": "https://example.eu.auth0.com/",
  "jwtValidationJwksUri": "https://example.eu.auth0.com/.well-known/jwks.json",
  "tokenExchangeAudience": "https://example-mcp.com",
  "tokenExchangeClientId": "example-client-id",
  "tokenExchangeClientSecret": "example-client-secret",
  "tokenExchangeDomain": "example.eu.auth0.com"
}
```

The table below describes each supported configuration option in more detail:

| Configuration Option        | Value Type      | Decription                                                                                                                                                                                                                                         |
| --------------------------- | --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `authorizationServers`      | `array[string]` | Authorization server(s) trusted to issue access tokens for the MCP server.                                                                                                                                                                         |
| `baseUrl`                   | `string`        | Public base URL of this MCP server, without the `/mcp` path (e.g. `https://mcp.elimity.example.com`). The MCP endpoint is served at `<baseUrl>/mcp`, and that endpoint URL is the OAuth resource identifier that client tokens must be issued for. |
| `insightsBaseUrl`           | `string`        | Base URL of the Elimity Insights instance this MCP server calls on behalf of the user.                                                                                                                                                             |
| `jwtValidationAudience`     | `string`        | <p>Expected <code>aud</code></p><p>claim on incoming access tokens. Must match the API identifier configured for the MCP client application.</p>                                                                                                   |
| `jwtValidationIssuer`       | `string`        | Expected `iss` claim on incoming access tokens. Must match your authorization server's issuer URL.                                                                                                                                                 |
| `jwtValidationJwksUri`      | `string`        | JWKS endpoint used to fetch the public keys for verifying incoming access token signatures.                                                                                                                                                        |
| `tokenExchangeAudience`     | `string`        | Audience requested when exchanging the incoming token for a new one to call Elimity Insights.                                                                                                                                                      |
| `tokenExchangeClientId`     | `string`        | Client ID of the application this MCP server uses, created in [step 1.3](#id-1.3-setting-up-an-application-for-the-mcp-server), to authenticate itself when performing the token exchange.                                                         |
| `tokenExchangeClientSecret` | `string`        | Client secret paired with `tokenExchangeClientId` for the token exchange request, created in [step 1.3](#id-1.3-setting-up-an-application-for-the-mcp-server).                                                                                     |
| `tokenExchangeDomain`       | `string`        | Authorization server domain the MCP server sends token exchange requests to.                                                                                                                                                                       |

**Note:** The values configured here must correspond to the `mcpJwtValidation`  settings on the [Elimity Insights server](/reference-manual/server-configuration.md). `tokenExchangeAudience` must match Insights' `mcpJwtValidation.audience`, and Insights’ `mcpJwtValidation.issuer` must be the issuer URL of the authorization server at `tokenExchangeDomain`, exactly as it appears in the `iss` claim of the exchanged token. For Auth0 this is `https://<tokenExchangeDomain>/`, including the trailing slash (e.g. `https://example.eu.auth0.com/` for `example.eu.auth0.com`).&#x20;

This is how Insights validates and accepts the token the MCP server presents on the user's behalf after the token exchange.

## 3. Deploying the MCP server

Having configured the MCP server we can now doploy it under the URL you decided on at the start. ince we distribute the MCP server as a Docker image, our recommendation for deployment is to use a CaaS solution like Google Cloud Run or Azure Container Apps. Some attention points:

* The server listens on port 8000
* The MCP endpoint must be reachable over public HTTPS, since MCP clients connect to it from the internet. If that's not an option, use a tunnel (see below)
* The configuration file contains a client secret, so store it in a secret store (e.g. Google Secret Manager) and mount it from there at `/app/config/config.json`
* Deploy one MCP server per Elimity Insights tenant

### Keeping the MCP server inside your network

On-prem, the MCP server often can't be exposed to the internet. In that case you can make it reachable through a tunnel: a connector inside your network that opens an outbound connection and the MCP client reaches the server through the tunnel's public hostname. Some AI tools offer built-in tunneling for MCP servers, general-purpose tunnels such as [ngrok](https://ngrok.com/docs/start) or [Cloudflare Tunnel](https://developers.cloudflare.com/tunnel/) work with any MCP client.

When you use a tunnel, the tunnel's hostname is your MCP server URL. Use it as `baseUrl` , as the identifier of the API in [step 1.1](#id-1.1-setting-up-an-application-for-the-mcp-client) (with `/mcp`), and as the connector URL in [step 1.2](#id-1.2-setting-up-the-mcp-client). The tunnel doesn't replace authentication: the authorization setup still applies.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.elimity.com/mcp-reference-manual/step-by-step-deployment-guide.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
