> ## 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.

# Production

> Deployment checklist for running Kontext MCP applications in production.

This checklist covers the settings you need to verify before deploying your Kontext MCP server to production.

## Use a factory function

Always pass a factory function to `kontext.middleware()`. Each MCP session needs its own `McpServer` instance -- the MCP spec requires a 1:1 relationship between server and transport. A single shared instance will fail under concurrent connections.

```typescript theme={"system"}
// Correct
app.use(kontext.middleware(() => createServer()));

// Will break with multiple sessions
app.use(kontext.middleware(server));
```

## Set the client secret

Token exchange with `kontext.require()` uses a client secret for server-side operations, session tracking, and telemetry. The secret is optional -- the SDK falls back to public client mode without it -- but recommended for production. Set it via environment variable:

```bash theme={"system"}
KONTEXT_CLIENT_SECRET=your_secret_here
```

Or pass it directly:

```typescript theme={"system"}
const kontext = new Kontext({
  clientId: "mcp_your-server",
  clientSecret: process.env.KONTEXT_CLIENT_SECRET,
});
```

## Configure token issuers

If your OAuth server issues tokens with an issuer different from the public metadata, configure `tokenIssuer` so the built-in verifier accepts them.

```bash theme={"system"}
KONTEXT_TOKEN_ISSUER=https://auth.example.com/
```

Supports multiple issuers (comma-separated in the env var, or an array in code):

```typescript theme={"system"}
const kontext = new Kontext({
  clientId: "mcp_your-server",
  tokenIssuer: ["https://auth.example.com/", "https://auth-internal.example.com/"],
});
```

## Set `resourceServerUrl` behind a proxy

When your application runs behind a reverse proxy or load balancer, the SDK cannot detect the public URL from the request. Set `resourceServerUrl` to your public endpoint:

```typescript theme={"system"}
app.use(
  kontext.middleware(() => createServer(), {
    resourceServerUrl: "https://mcp.example.com/mcp",
  })
);
```

Without this, the OAuth protected resource metadata will contain incorrect URLs.

## Session management

The SDK tracks MCP sessions automatically:

* **Stale cleanup**: Sessions inactive for 1 hour are closed and removed.
* **Cleanup interval**: Runs every 5 minutes.

No configuration needed. The cleanup timer is `unref`'d so it does not prevent process exit.

## Graceful shutdown

The SDK registers `SIGINT` and `SIGTERM` handlers that disconnect all active sessions on shutdown. This happens automatically for every `Kontext` instance.

For serverless environments or cases where you create and dispose SDK instances dynamically, call `destroy()` to clean up:

```typescript theme={"system"}
const kontext = new Kontext({ clientId: "mcp_your-server" });

// ... use the SDK ...

// Clean up sessions, caches, and static references
await kontext.destroy();
```

`destroy()` disconnects all sessions, clears credential caches, and removes the instance from the global shutdown handler set so it can be garbage collected.

## Next steps

* [Middleware](/server/middleware) -- Full middleware configuration, session hooks, and custom verifiers.
* [Server Types](/sdks/typescript/server) -- Type reference for `Kontext`, `KontextOptions`, and `MiddlewareOptions`.
