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

# Connect an MCP with a setup link

> Programmatically create a draft MCP connection, invite a third party to authenticate through a setup link, and get notified via a callback webhook.

This flow lets you build an MCP onboarding experience **on top of the Platform API**: create a connection in draft, hand a secure link to a client or third party so they can authenticate with their own credentials (without a Nekt account), receive a webhook when they finish, then activate the connection.

It mirrors the in-app [MCPs](/mcps/overview) flow end to end over the API, and it is the same shape as [Configure a source with a setup link](/platform-api/sources/setup-link) — a different resource, and a different link prefix (`/lcl/` instead of `/scl/`).

<Tip>
  The case this exists for: one connection per end client, each with their own credentials. Create as many connections of the same connector as you have clients — each has its own slug, its own credentials, and its own permissions.
</Tip>

## Overview

```mermaid theme={null}
sequenceDiagram
    participant Client as Your app
    participant API as Nekt API
    participant ThirdParty as Third party
    participant Hook as Your callback URL

    Client->>API: GET /live-connectors/ (pick a connector)
    Client->>API: POST /live-connections/ (callback_webhook)
    API-->>Client: Draft connection
    Client->>API: POST /live-connections/{slug}/setup-tokens/
    API-->>Client: { token, expires_at }
    Client->>ThirdParty: Share https://app.nekt.ai/lcl/{token}
    ThirdParty->>API: Authenticate / fill in the config (via the link)
    API->>Hook: POST callback_webhook (live_connection.setup_filled)
    Client->>API: PATCH /live-connections/{slug}/ (active=true)
    API-->>Client: Connection in service
```

## Prerequisites

* An [API key](/platform-api/introduction#create-an-api-key) for authentication.
* MCPs are available on all **paid plans**.

## Step 1: Pick a connector

List the connectors available to your workspace. Expand the current version to get the JSON Schema that a connection for it is configured against — that is what tells you which fields the third party will be asked for.

```bash theme={null}
curl --request GET \
  --url "https://api.nekt.ai/api/v1/live-connectors/?expand[]=current_version&include[]=current_version.config_template" \
  --header "x-api-key: YOUR_API_KEY"
```

## Step 2: Create a draft connection with a callback webhook

The connection is created as a draft, pinned to the connector's current version.

Optionally attach a **`callback_webhook`**: Nekt POSTs to it once the third party submits the setup form. Use the optional custom header to authenticate the call on your side.

```bash theme={null}
curl --request POST \
  --url https://api.nekt.ai/api/v1/live-connections/ \
  --header "x-api-key: YOUR_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "connector": "CONNECTOR_ID_OR_SLUG",
    "slug": "hubspot-acme",
    "description": "ACME'\''s HubSpot",
    "callback_webhook": {
      "url": "https://your-app.example.com/hooks/nekt",
      "header_name": "X-Webhook-Secret",
      "header_value": "your-shared-secret"
    }
  }'
```

| Field              | Type   | Required | Description                                                                                                                            |
| ------------------ | ------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `connector`        | string | Yes      | The connector this connection is for.                                                                                                  |
| `slug`             | string | No       | Stable identifier, generated when omitted. It is also the namespace the connection's tools are exposed under, so keep it recognisable. |
| `description`      | string | No       | Read by the agent to choose between connections of the same type ("HubSpot for marketing" vs "HubSpot for sales").                     |
| `available_tools`  | array  | No       | Which of the connector's tools this connection exposes. Defaults to all of them.                                                       |
| `callback_webhook` | object | No       | See below.                                                                                                                             |

### `callback_webhook` object

| Field          | Type   | Required | Description                                                                                         |
| -------------- | ------ | -------- | --------------------------------------------------------------------------------------------------- |
| `url`          | string | Yes      | HTTPS URL Nekt POSTs to on setup completion. Must be a public `https://` endpoint.                  |
| `header_name`  | string | No       | Optional custom header name to send with the callback.                                              |
| `header_value` | string | No       | Value for the custom header. Required if `header_name` is set. Stored encrypted and never returned. |

<Note>
  `callback_webhook` is **write-only**. Responses never echo it back; they expose a read-only boolean `has_callback_webhook` so you can confirm one is configured. To remove a configured webhook, send `"callback_webhook": null` on an update.
</Note>

<Warning>
  For security, the URL must use `https` and resolve to a public host. URLs pointing at `localhost`, loopback, private (RFC 1918), or link-local addresses are rejected.
</Warning>

## Step 3: Create a setup token

Generate a time-limited token scoped to this connection, then build the link as `https://app.nekt.ai/lcl/{token}` and share it with the third party.

```bash theme={null}
curl --request POST \
  --url https://api.nekt.ai/api/v1/live-connections/{slug}/setup-tokens/ \
  --header "x-api-key: YOUR_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{ "expires_in_seconds": 86400 }'
```

```json theme={null}
{
  "id": "0d2c1b47-2902-4c47-8b30-0e7c3fd72609",
  "token": "Qm9vR2k...redactedOnList",
  "expires_at": "2026-06-18T12:00:00Z",
  "connector_config_fields": null,
  "created_at": "2026-06-17T12:00:00Z"
}
```

| Field                     | Type                     | Required | Description                                                                                                                                                |
| ------------------------- | ------------------------ | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `expires_in_seconds`      | integer                  | No       | Token lifetime. Defaults to 24 hours (`86400`).                                                                                                            |
| `connector_config_fields` | array, object or boolean | No       | Restricts which configuration fields the link exposes. Omit for the whole config template. See [Restricting the link](#restricting-what-the-link-exposes). |

<Note>
  The full `token` is returned only on creation. When listing tokens it is redacted. To revoke a link, delete the token: `DELETE /api/v1/live-connections/{slug}/setup-tokens/{id}/`.
</Note>

## Step 4: The third party authenticates

The recipient opens `https://app.nekt.ai/lcl/{token}` and enters the credentials (or authenticates via OAuth for connectors that support it). No Nekt account is required, and the link is scoped strictly to this connection.

When they submit, Nekt POSTs to your `callback_webhook` (if configured):

```http theme={null}
POST https://your-app.example.com/hooks/nekt
Content-Type: application/json
X-Webhook-Secret: your-shared-secret

{
  "event": "live_connection.setup_filled",
  "live_connection": {
    "id": "d2c1b472-902c-477a-b300-e7c3fd72609b",
    "slug": "hubspot-acme",
    "connector_slug": "hubspot",
    "description": "ACME's HubSpot",
    "draft": true,
    "active": false,
    "config_completed": true,
    "missing_required_fields": []
  }
}
```

| Field                     | Type    | Description                                                                          |
| ------------------------- | ------- | ------------------------------------------------------------------------------------ |
| `config_completed`        | boolean | `true` when all required configuration fields are filled.                            |
| `missing_required_fields` | array   | Dot-paths of required fields still missing. Empty when `config_completed` is `true`. |

<Warning>
  Read `config_completed`, not `draft`. The connection stays `draft` until **you** activate it in the next step, so `draft` never answers "did my client finish?". A partially filled form produces `config_completed: false` with the remaining fields named — send another link to collect them.
</Warning>

## Step 5: Activate the connection

Activating clears `draft` and puts the connection in service: its tools become available to your agents through the Gateway.

```bash theme={null}
curl --request PATCH \
  --url https://api.nekt.ai/api/v1/live-connections/{slug}/ \
  --header "x-api-key: YOUR_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{ "active": true }'
```

<Note>
  Setup links stop working once the connection is active. Any unused link for it is invalidated at that moment, and a link can be used again only if the connection later goes into an error state and needs re-authentication.
</Note>

## Restricting what the link exposes

By default a setup link exposes the connector's whole configuration template. `connector_config_fields` narrows it: the setup page renders only the named fields, and anything else the recipient sends back is **ignored rather than written** — a hidden field keeps its stored value.

```bash theme={null}
curl --request POST \
  --url https://api.nekt.ai/api/v1/live-connections/{slug}/setup-tokens/ \
  --header "x-api-key: YOUR_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{ "connector_config_fields": ["api_key"] }'
```

| Value                       | Meaning                                                    |
| --------------------------- | ---------------------------------------------------------- |
| omitted / `null`            | No restriction — the whole template.                       |
| `["api_key", "domain"]`     | Those fields, nothing else.                                |
| `{"auth": {"token": true}}` | Nested: only `auth.token`, and only `token` within `auth`. |
| `true` / `false`            | Everything / nothing, at any level.                        |

A typical use: your systems already know the account id and region, so you send them as `config` when you create the connection and restrict the link to the one secret only your client has.

<Note>
  Naming a field the connector's template does not declare is rejected with `400` when the link is created, listing every unknown path at once — rather than producing a link whose page is silently empty.
</Note>

## Choosing which tools the connection exposes

A connection is created exposing every tool of the connector. Send `available_tools` at creation, or replace the set later — the payload is the full desired set, so anything missing from the list stops being exposed.

```bash theme={null}
curl --request PATCH \
  --url https://api.nekt.ai/api/v1/live-connections/{slug}/tools/ \
  --header "x-api-key: YOUR_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{ "tools": ["search_objects", "get_object"] }'
```

`GET` the same endpoint to list the connector's tools with an `is_write` flag on each, so you can enable write-capable tools deliberately.

<Tip>
  The exact endpoints and request/response shapes are available in the OpenAPI schema at [api.nekt.ai/api/schema/](https://api.nekt.ai/api/schema/).
</Tip>
