Skip to main content
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

npm install @kontext-dev/js-sdk

Quick start

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:
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:
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

OptionTypeRequiredDescription
clientIdstringYesYour application’s client ID from the Kontext dashboard.
redirectUristringYesWhere OAuth redirects after authorization. Must match your dashboard config.
urlstringNoMCP server endpoint. When set, enables single-endpoint mode.
serverUrlstringNoKontext API base URL. Defaults to https://api.kontext.dev.
storageKontextStorageNoToken persistence backend. Defaults to MemoryStorage (in-memory).
sessionKeystringNoNamespace for storage keys. Use this to isolate tokens per user.
onAuthRequired(url: URL) => string | URL | void | Promise<string | URL | void>YesCalled when the user needs to authenticate. See Authentication.
onIntegrationRequired(url: string, info: { id: string; name?: string }) => void | Promise<void>NoCalled when an integration needs to be connected by the user.
onStateChange(state: ClientState) => voidNoCalled 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
StateMeaning
idleClient created, not yet connected.
connectingConnection in progress.
readyConnected and authenticated. Tools are available.
needs_authAuthentication required before proceeding.
failedConnection failed due to a non-auth error.

Event listeners

Subscribe to state changes and errors with client.on(). The function returns an unsubscribe callback.
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 — Discover and execute MCP tools.
  • Authentication — OAuth sign-in, callbacks, and session management.
  • Storage — Persist tokens with custom storage backends.
  • Client Types — Full type reference for KontextClient, KontextClientConfig, and KontextTool.