Skip to main content
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.
// 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:
KONTEXT_CLIENT_SECRET=your_secret_here
Or pass it directly:
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.
KONTEXT_TOKEN_ISSUER=https://auth.example.com/
Supports multiple issuers (comma-separated in the env var, or an array in code):
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:
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:
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 — Full middleware configuration, session hooks, and custom verifiers.
  • Server Types — Type reference for Kontext, KontextOptions, and MiddlewareOptions.