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

# Set up machine-to-machine MCP access

> Set up secure machine-to-machine MCP access from an internal AI gateway or backend workload to ClosedLoop AI using OAuth client credentials.

Use a service client when an internal AI gateway, automated agent, or backend workload must connect to ClosedLoop AI without a person authorizing it in a browser. The gateway exchanges a client ID and secret for short-lived, read-only access tokens.

## Before you begin

You need:

* A workspace owner or admin account
* A gateway that supports HTTP MCP and the OAuth `client_credentials` flow
* A secret manager for the client ID and secret

## Set up access

<Steps>
  <Step title="Choose your regional endpoints">
    Use every URL from the same row:

    | Workspace region | MCP URL                        | Token URL                            |
    | ---------------- | ------------------------------ | ------------------------------------ |
    | US               | `https://mcp.closedloop.sh`    | `https://mcp.closedloop.sh/token`    |
    | EU               | `https://eu.mcp.closedloop.sh` | `https://eu.mcp.closedloop.sh/token` |

    Credentials created for one region do not work in the other region.
  </Step>

  <Step title="Create a service client">
    1. In ClosedLoop AI, open **Settings → MCP access**.
    2. Click **Create service client**.
    3. Enter a name that identifies the gateway or workload using it.
    4. Copy the client ID and client secret into your secret manager.

    <Warning>The client secret is shown only once. If you lose it, rotate the credential and save the new secret.</Warning>
  </Step>

  <Step title="Configure your gateway">
    Set these values in your gateway:

    | Field          | Value                           |
    | -------------- | ------------------------------- |
    | Transport      | HTTP                            |
    | Authentication | OAuth                           |
    | OAuth flow     | `client_credentials`            |
    | MCP URL        | The regional MCP URL above      |
    | Token URL      | The regional token URL above    |
    | Client ID      | The saved service-client ID     |
    | Client secret  | The saved service-client secret |
    | Scope          | `mcp:read`                      |

    Use `client_secret_basic` when your gateway lets you choose the client authentication method. ClosedLoop AI also supports `client_secret_post`.

    If your gateway sends an OAuth `resource` value, set it to the exact regional MCP URL. Gateways that omit `resource` are supported.
  </Step>

  <Step title="Test the connection">
    Ask the gateway to list the available tools, then call a read-only tool such as `get_overview`.

    A successful connection does not open a browser. The gateway receives a one-hour token with the `mcp:read` scope and must fetch a new one when it expires.
  </Step>
</Steps>

## LiteLLM example

Store the service-client values as `CLOSEDLOOP_MCP_CLIENT_ID` and `CLOSEDLOOP_MCP_CLIENT_SECRET`, then add the matching regional configuration to `config.yaml`:

```yaml theme={null}
mcp_servers:
  closedloop_ai:
    url: "https://eu.mcp.closedloop.sh"
    transport: http
    auth_type: oauth2
    oauth2_flow: client_credentials
    client_id: os.environ/CLOSEDLOOP_MCP_CLIENT_ID
    client_secret: os.environ/CLOSEDLOOP_MCP_CLIENT_SECRET
    token_url: "https://eu.mcp.closedloop.sh/token"
    scopes: ["mcp:read"]
```

For a US workspace, change both URLs to `https://mcp.closedloop.sh` and `https://mcp.closedloop.sh/token`.

LiteLLM [fetches, caches, and renews access tokens automatically](https://docs.litellm.ai/docs/mcp_oauth#machine-to-machine-m2m-auth). To verify the setup, open the MCP entry in LiteLLM, list its tools, and call `get_overview`.

## Rotate or revoke credentials

* Access tokens expire after one hour. Service-client secrets expire after 180 days.
* ClosedLoop AI notifies workspace owners and admins in **Settings → MCP access** 30 and 7 days before a secret expires.
* When you rotate a credential, its existing secret remains valid for at most 24 hours. Update the gateway, verify the new secret, then revoke the old credential.
* Revoking a credential immediately invalidates its issued access tokens. Revoking a service client immediately invalidates all its credentials and tokens.

Create a separate service client for each gateway or workload so access can be rotated, audited, and revoked independently.

## Troubleshooting

| Error or symptom            | What to check                                                                                |
| --------------------------- | -------------------------------------------------------------------------------------------- |
| `invalid_client`            | Confirm the client ID and secret are current and belong to the same region as the token URL. |
| `invalid_scope`             | Request only `mcp:read`.                                                                     |
| `invalid_target`            | Match the OAuth `resource` value exactly to the regional MCP URL, or omit it.                |
| `Invalid or expired token`  | Do not use a regular API key. Let the gateway fetch a new token from the regional token URL. |
| A browser opens             | Configure `client_credentials`, not the authorization-code flow.                             |
| Write tools are unavailable | Service-client access is intentionally read-only.                                            |

<CardGroup cols={2}>
  <Card title="MCP Overview" icon="plug" href="/docs/mcp-server/overview">
    Set up interactive clients and learn how MCP access works.
  </Card>

  <Card title="Core tools reference" icon="wrench" href="/docs/mcp-server/tools">
    Browse core tools and their parameters.
  </Card>
</CardGroup>
