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

# Client SDK

> Use the Kontext client SDK to run agents with short-lived, scoped credentials managed by the Kontext identity control plane.

Kontext is the identity control plane for AI agents. The client SDK is the developer path to that control plane: authenticate users, discover tools, and execute actions with credentials scoped at runtime and audited centrally.

## Install

```bash theme={"system"}
npm install @kontext-dev/js-sdk
```

## Quick start

```typescript theme={"system"}
import { createKontextClient } from "@kontext-dev/js-sdk/client";

const client = createKontextClient({
  clientId: "your-client-id",
  redirectUri: "http://localhost:3000/callback",
  url: "https://my-server.com/mcp",
  onAuthRequired: (url) => {
    window.location.href = url.toString();
  },
});

await client.connect();
const tools = await client.tools.list();
if (tools.length === 0) throw new Error("No tools available");
const result = await client.tools.execute(tools[0].id, {});
```

`createKontextClient` is the main entry point. It returns a `KontextClient` that handles authentication, tool discovery, and tool execution.

## Two modes

The client operates in one of two modes depending on whether you pass a `url`.

### Single-endpoint mode

Pass `url` to connect directly to a specific MCP server:

```typescript theme={"system"}
const client = createKontextClient({
  clientId: "your-client-id",
  redirectUri: "http://localhost:3000/callback",
  url: "https://my-server.com/mcp",
  onAuthRequired: (url) => {
    window.location.href = url.toString();
  },
});
```

Use this when your application talks to one MCP server and you know its endpoint.

### Hybrid mode

Omit `url` to use the Kontext gateway, which aggregates tools from multiple integrations:

```typescript theme={"system"}
const client = createKontextClient({
  clientId: "your-client-id",
  redirectUri: "http://localhost:3000/callback",
  onAuthRequired: (url) => {
    window.location.href = url.toString();
  },
});
```

In hybrid mode, the client routes tool calls through the gateway and can also connect to integrations directly. Tool IDs can come from gateway listings or internal integration normalization, so always use the IDs returned by `client.tools.list()`.

## Configuration reference

| Option                  | Type                                                                          | Required | Description                                                                               |
| ----------------------- | ----------------------------------------------------------------------------- | -------- | ----------------------------------------------------------------------------------------- |
| `clientId`              | `string`                                                                      | Yes      | Your application's client ID from the Kontext dashboard.                                  |
| `redirectUri`           | `string`                                                                      | Yes      | Where OAuth redirects after authorization. Must match your dashboard config.              |
| `url`                   | `string`                                                                      | No       | MCP server endpoint. When set, enables single-endpoint mode.                              |
| `serverUrl`             | `string`                                                                      | No       | Kontext API base URL. Defaults to `https://api.kontext.security`.                         |
| `storage`               | `KontextStorage`                                                              | No       | Token persistence backend. Defaults to `MemoryStorage` (in-memory).                       |
| `sessionKey`            | `string`                                                                      | No       | Namespace for storage keys. Use this to isolate tokens per user.                          |
| `onAuthRequired`        | `(url: URL) => string \| URL \| void \| Promise<string \| URL \| void>`       | Yes      | Called when the user needs to authenticate. See [Authentication](/client/authentication). |
| `onIntegrationRequired` | `(url: string, info: { id: string; name?: string }) => void \| Promise<void>` | No       | Called when an integration needs to be connected by the user.                             |
| `onStateChange`         | `(state: ClientState) => void`                                                | No       | Called on every state transition.                                                         |

## Callbacks

### onAuthRequired

Fires when the client needs the user to log in. You receive a `URL` pointing to the OAuth authorization page. Return the callback URL (as a string or URL) to complete the flow inline, or return `void` to handle the callback separately via `client.auth.handleCallback()`.

### onIntegrationRequired

Fires when a tool call fails because the user has not connected the underlying integration. You receive the connect URL and integration metadata. Open this URL so the user can authorize the integration.

### onStateChange

Fires on every state transition. Useful for driving loading indicators and error UI.

## Client state

The client tracks a `state` property that follows this lifecycle:

```
idle -> connecting -> ready
                  \-> needs_auth -> (after sign-in) -> connecting -> ready
                  \-> failed
```

| State        | Meaning                                           |
| ------------ | ------------------------------------------------- |
| `idle`       | Client created, not yet connected.                |
| `connecting` | Connection in progress.                           |
| `ready`      | Connected and authenticated. Tools are available. |
| `needs_auth` | Authentication required before proceeding.        |
| `failed`     | Connection failed due to a non-auth error.        |

## Event listeners

Subscribe to state changes and errors with `client.on()`. The function returns an unsubscribe callback.

```typescript theme={"system"}
const unsubState = client.on("stateChange", (state) => {
  console.log("Client state:", state);
});

const unsubError = client.on("error", (error) => {
  console.error("Client error:", error.message);
});

// Later, clean up:
unsubState();
unsubError();
```

Both `on("stateChange")` and the `onStateChange` config callback fire on every transition. Use whichever pattern fits your application -- `on()` is better when you need to add and remove listeners dynamically.

## Next steps

* [Tools](/client/tools) -- Discover and execute MCP tools.
* [Authentication](/client/authentication) -- OAuth sign-in, callbacks, and session management.
* [Storage](/client/storage) -- Persist tokens with custom storage backends.
* [Client Types](/sdks/typescript/client) -- Full type reference for `KontextClient`, `KontextClientConfig`, and `KontextTool`.
