@kontext-dev/js-sdk 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +70 -0
- package/dist/adapters/ai/index.cjs +175 -0
- package/dist/adapters/ai/index.cjs.map +1 -0
- package/dist/adapters/ai/index.d.cts +51 -0
- package/dist/adapters/ai/index.d.ts +51 -0
- package/dist/adapters/ai/index.js +173 -0
- package/dist/adapters/ai/index.js.map +1 -0
- package/dist/adapters/cloudflare/index.cjs +598 -0
- package/dist/adapters/cloudflare/index.cjs.map +1 -0
- package/dist/adapters/cloudflare/index.d.cts +214 -0
- package/dist/adapters/cloudflare/index.d.ts +214 -0
- package/dist/adapters/cloudflare/index.js +594 -0
- package/dist/adapters/cloudflare/index.js.map +1 -0
- package/dist/adapters/cloudflare/react.cjs +156 -0
- package/dist/adapters/cloudflare/react.cjs.map +1 -0
- package/dist/adapters/cloudflare/react.d.cts +68 -0
- package/dist/adapters/cloudflare/react.d.ts +68 -0
- package/dist/adapters/cloudflare/react.js +152 -0
- package/dist/adapters/cloudflare/react.js.map +1 -0
- package/dist/adapters/react/index.cjs +146 -0
- package/dist/adapters/react/index.cjs.map +1 -0
- package/dist/adapters/react/index.d.cts +103 -0
- package/dist/adapters/react/index.d.ts +103 -0
- package/dist/adapters/react/index.js +142 -0
- package/dist/adapters/react/index.js.map +1 -0
- package/dist/client/index.cjs +2415 -0
- package/dist/client/index.cjs.map +1 -0
- package/dist/client/index.d.cts +125 -0
- package/dist/client/index.d.ts +125 -0
- package/dist/client/index.js +2412 -0
- package/dist/client/index.js.map +1 -0
- package/dist/errors.cjs +213 -0
- package/dist/errors.cjs.map +1 -0
- package/dist/errors.d.cts +161 -0
- package/dist/errors.d.ts +161 -0
- package/dist/errors.js +201 -0
- package/dist/errors.js.map +1 -0
- package/dist/index-D5hS5PGn.d.ts +54 -0
- package/dist/index-DcL4a5Vq.d.cts +54 -0
- package/dist/index.cjs +4046 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +15 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +4029 -0
- package/dist/index.js.map +1 -0
- package/dist/kontext-CgIBANFo.d.cts +308 -0
- package/dist/kontext-CgIBANFo.d.ts +308 -0
- package/dist/management/index.cjs +867 -0
- package/dist/management/index.cjs.map +1 -0
- package/dist/management/index.d.cts +467 -0
- package/dist/management/index.d.ts +467 -0
- package/dist/management/index.js +855 -0
- package/dist/management/index.js.map +1 -0
- package/dist/mcp/index.cjs +799 -0
- package/dist/mcp/index.cjs.map +1 -0
- package/dist/mcp/index.d.cts +231 -0
- package/dist/mcp/index.d.ts +231 -0
- package/dist/mcp/index.js +797 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/oauth/index.cjs +418 -0
- package/dist/oauth/index.cjs.map +1 -0
- package/dist/oauth/index.d.cts +235 -0
- package/dist/oauth/index.d.ts +235 -0
- package/dist/oauth/index.js +414 -0
- package/dist/oauth/index.js.map +1 -0
- package/dist/server/index.cjs +1634 -0
- package/dist/server/index.cjs.map +1 -0
- package/dist/server/index.d.cts +10 -0
- package/dist/server/index.d.ts +10 -0
- package/dist/server/index.js +1629 -0
- package/dist/server/index.js.map +1 -0
- package/dist/types-CzhnlJHW.d.cts +397 -0
- package/dist/types-CzhnlJHW.d.ts +397 -0
- package/dist/types-RIzHnRpk.d.cts +23 -0
- package/dist/types-RIzHnRpk.d.ts +23 -0
- package/dist/verifier-CoJmYiw3.d.cts +109 -0
- package/dist/verifier-CoJmYiw3.d.ts +109 -0
- package/dist/verify/index.cjs +319 -0
- package/dist/verify/index.cjs.map +1 -0
- package/dist/verify/index.d.cts +63 -0
- package/dist/verify/index.d.ts +63 -0
- package/dist/verify/index.js +315 -0
- package/dist/verify/index.js.map +1 -0
- package/package.json +221 -0
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
import * as _modelcontextprotocol_sdk_server_streamableHttp_js from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
3
|
+
import * as _modelcontextprotocol_sdk_server_auth_types_js from '@modelcontextprotocol/sdk/server/auth/types.js';
|
|
4
|
+
import * as _modelcontextprotocol_sdk_shared_auth_js from '@modelcontextprotocol/sdk/shared/auth.js';
|
|
5
|
+
import * as _modelcontextprotocol_sdk_server_auth_provider_js from '@modelcontextprotocol/sdk/server/auth/provider.js';
|
|
6
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Known integration short names.
|
|
10
|
+
*
|
|
11
|
+
* Custom integrations can be passed as arbitrary strings.
|
|
12
|
+
*/
|
|
13
|
+
type KnownIntegration = "github" | "gmail" | "google-calendar" | "google-drive" | "slack" | "linear" | "notion" | "jira" | "confluence" | "figma" | "stripe" | "shopify" | "salesforce" | "hubspot" | "asana" | "discord" | "twilio" | "sendgrid" | "openai" | "anthropic";
|
|
14
|
+
/**
|
|
15
|
+
* An integration name — either a well-known short name or a custom string.
|
|
16
|
+
*/
|
|
17
|
+
type IntegrationName = KnownIntegration | (string & {});
|
|
18
|
+
/**
|
|
19
|
+
* A credential returned by `kontext.require()`.
|
|
20
|
+
*
|
|
21
|
+
* Provides the access token and a pre-formatted authorization header.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* const github = await kontext.require("github", token);
|
|
26
|
+
* const res = await fetch("https://api.github.com/user", {
|
|
27
|
+
* headers: { Authorization: github.authorization },
|
|
28
|
+
* });
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
interface IntegrationCredential {
|
|
32
|
+
/** The raw access token for the integration */
|
|
33
|
+
accessToken: string;
|
|
34
|
+
/** Token type (usually "Bearer") */
|
|
35
|
+
tokenType: string;
|
|
36
|
+
/**
|
|
37
|
+
* Pre-formatted authorization header value.
|
|
38
|
+
* Typically `"Bearer <accessToken>"`, ready to use in HTTP headers.
|
|
39
|
+
*/
|
|
40
|
+
authorization: string;
|
|
41
|
+
/** Time in seconds until the token expires (undefined = no expiry info) */
|
|
42
|
+
expiresIn?: number;
|
|
43
|
+
/** Scopes granted by the integration */
|
|
44
|
+
scope?: string;
|
|
45
|
+
/** The integration name this credential was issued for */
|
|
46
|
+
integration: IntegrationName;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* A decrypted per-user credential map for internal MCP integrations.
|
|
50
|
+
*/
|
|
51
|
+
interface IntegrationResolvedCredentials {
|
|
52
|
+
/** The original integration identifier passed to requireCredentials() */
|
|
53
|
+
integration: IntegrationName;
|
|
54
|
+
/** Canonical integration UUID */
|
|
55
|
+
integrationId: string;
|
|
56
|
+
/** Credential key/value map resolved for the current user */
|
|
57
|
+
credentials: Record<string, string>;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Configuration for the `Kontext` class.
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```typescript
|
|
64
|
+
* const kontext = new Kontext({ clientId: "mcp_my-server" });
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
interface KontextOptions {
|
|
68
|
+
/** OAuth client ID from the Kontext dashboard. */
|
|
69
|
+
clientId: string;
|
|
70
|
+
/** Kontext API base URL. @default "https://api.kontext.dev" */
|
|
71
|
+
apiUrl?: string;
|
|
72
|
+
/** OAuth client secret. @default KONTEXT_CLIENT_SECRET env var */
|
|
73
|
+
clientSecret?: string;
|
|
74
|
+
/**
|
|
75
|
+
* Optional token issuer override(s) accepted during bearer token validation.
|
|
76
|
+
* Use this when your OAuth server issues tokens with an issuer different from
|
|
77
|
+
* the public metadata issuer.
|
|
78
|
+
*
|
|
79
|
+
* @default KONTEXT_TOKEN_ISSUER env var (comma-separated values supported)
|
|
80
|
+
*/
|
|
81
|
+
tokenIssuer?: string | string[];
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* A factory function that creates a fresh `McpServer` instance per session.
|
|
85
|
+
*
|
|
86
|
+
* Use this in production to support concurrent MCP sessions — `McpServer.connect()`
|
|
87
|
+
* is 1:1 per the MCP spec, so sharing a single instance across sessions will throw.
|
|
88
|
+
*/
|
|
89
|
+
type McpServerFactory = () => McpServer;
|
|
90
|
+
/**
|
|
91
|
+
* An `McpServer` instance (for single-session / local dev) or a factory
|
|
92
|
+
* function that creates one per session (for concurrent production use).
|
|
93
|
+
*/
|
|
94
|
+
type McpServerOrFactory = McpServer | McpServerFactory;
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Options for `kontext.middleware(server)`.
|
|
98
|
+
*/
|
|
99
|
+
interface MiddlewareOptions {
|
|
100
|
+
/** Path for the MCP transport endpoint. @default "/mcp" */
|
|
101
|
+
mcpPath?: string;
|
|
102
|
+
/** URL of this server (for resource metadata). Auto-detected from request if not set. */
|
|
103
|
+
resourceServerUrl?: string;
|
|
104
|
+
/**
|
|
105
|
+
* Skip OAuth metadata fetching and bearer auth entirely.
|
|
106
|
+
* Useful for local development and testing with the MCP Inspector.
|
|
107
|
+
*
|
|
108
|
+
* **Never use in production.**
|
|
109
|
+
*/
|
|
110
|
+
dangerouslyOmitAuth?: boolean;
|
|
111
|
+
/**
|
|
112
|
+
* Custom token verifier. Replaces the built-in `KontextTokenVerifier`.
|
|
113
|
+
*
|
|
114
|
+
* Use this to integrate custom session resolution (e.g. a gateway's
|
|
115
|
+
* internal verification API) while still using the middleware's
|
|
116
|
+
* transport, metadata, and session management.
|
|
117
|
+
*
|
|
118
|
+
* When provided, the middleware skips JWKS-based verification and
|
|
119
|
+
* delegates entirely to this verifier.
|
|
120
|
+
*/
|
|
121
|
+
verifier?: _modelcontextprotocol_sdk_server_auth_provider_js.OAuthTokenVerifier;
|
|
122
|
+
/**
|
|
123
|
+
* Transform OAuth metadata after fetching from the authorization server.
|
|
124
|
+
*
|
|
125
|
+
* Useful for URL rewriting (e.g. replacing internal Hydra URLs with
|
|
126
|
+
* public-facing URLs in a gateway setup).
|
|
127
|
+
*
|
|
128
|
+
* The transform runs before the middleware rewrites the `issuer` field.
|
|
129
|
+
*/
|
|
130
|
+
metadataTransform?: (metadata: _modelcontextprotocol_sdk_shared_auth_js.OAuthMetadata) => _modelcontextprotocol_sdk_shared_auth_js.OAuthMetadata;
|
|
131
|
+
/**
|
|
132
|
+
* Called after a new MCP session is initialized.
|
|
133
|
+
*
|
|
134
|
+
* When a custom `verifier` is provided, `authInfo` contains the
|
|
135
|
+
* result of that verifier (including `extra` fields). This allows
|
|
136
|
+
* the gateway to receive rich session context.
|
|
137
|
+
*
|
|
138
|
+
* The `transport` is provided so callers can manage session
|
|
139
|
+
* lifecycle (e.g. closing on revocation).
|
|
140
|
+
*/
|
|
141
|
+
onSessionInitialized?: (sessionId: string, authInfo?: _modelcontextprotocol_sdk_server_auth_types_js.AuthInfo, transport?: _modelcontextprotocol_sdk_server_streamableHttp_js.StreamableHTTPServerTransport) => void;
|
|
142
|
+
/** Called when an MCP session is closed. */
|
|
143
|
+
onSessionClosed?: (sessionId: string) => void;
|
|
144
|
+
/** Maximum request body size for MCP POST requests. Passed to express.json({ limit }). @default "1mb" */
|
|
145
|
+
bodyLimit?: string | number;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Kontext — the v3 server SDK entry point.
|
|
150
|
+
*
|
|
151
|
+
* Two methods:
|
|
152
|
+
* kontext.middleware(server) — Express middleware (auth + metadata + transport + sessions)
|
|
153
|
+
* kontext.require(integration, token) — RFC 8693 token exchange with caching
|
|
154
|
+
* kontext.requireCredentials(integration, token) — Resolve per-user internal credentials
|
|
155
|
+
*
|
|
156
|
+
* @example Factory pattern (recommended for production — supports concurrent sessions)
|
|
157
|
+
* ```typescript
|
|
158
|
+
* import { Kontext } from "@kontext-dev/js-sdk/server";
|
|
159
|
+
* import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
160
|
+
* import express from "express";
|
|
161
|
+
*
|
|
162
|
+
* const kontext = new Kontext({ clientId: "mcp_my-server" });
|
|
163
|
+
*
|
|
164
|
+
* function createServer() {
|
|
165
|
+
* const server = new McpServer({ name: "my-server", version: "1.0.0" });
|
|
166
|
+
* server.tool("list_repos", {}, async (args, { authInfo }) => {
|
|
167
|
+
* const github = await kontext.require("github", authInfo!.token);
|
|
168
|
+
* const res = await fetch("https://api.github.com/user/repos", {
|
|
169
|
+
* headers: { Authorization: github.authorization },
|
|
170
|
+
* });
|
|
171
|
+
* return { content: [{ type: "text", text: JSON.stringify(await res.json()) }] };
|
|
172
|
+
* });
|
|
173
|
+
* return server;
|
|
174
|
+
* }
|
|
175
|
+
*
|
|
176
|
+
* const app = express();
|
|
177
|
+
* app.use(kontext.middleware(createServer)); // /mcp endpoint + /.well-known/* metadata
|
|
178
|
+
* app.listen(3000);
|
|
179
|
+
* ```
|
|
180
|
+
*/
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* The v3 Kontext server SDK.
|
|
184
|
+
*
|
|
185
|
+
* Provides two methods:
|
|
186
|
+
* - `middleware(server)` — Express Router with auth metadata, bearer validation, and MCP transport.
|
|
187
|
+
* Accepts an `McpServer` instance (single-session) or a factory `() => McpServer` (concurrent sessions).
|
|
188
|
+
* - `require(integration, token)` — RFC 8693 token exchange with in-memory caching
|
|
189
|
+
* - `requireCredentials(integration, token)` — Resolve per-user credential maps for internal integrations
|
|
190
|
+
*/
|
|
191
|
+
declare class Kontext {
|
|
192
|
+
private static readonly shutdownInstances;
|
|
193
|
+
private static shutdownHandlersRegistered;
|
|
194
|
+
private readonly clientId;
|
|
195
|
+
private readonly clientSecret;
|
|
196
|
+
private readonly apiUrl;
|
|
197
|
+
private readonly tokenIssuers;
|
|
198
|
+
private oauthMetadata;
|
|
199
|
+
private metadataFetchedAt;
|
|
200
|
+
private metadataPromise;
|
|
201
|
+
private readonly credentialCache;
|
|
202
|
+
private readonly resolvedCredentialCache;
|
|
203
|
+
private readonly runtimeAuthCache;
|
|
204
|
+
private readonly runtimeVerifierIds;
|
|
205
|
+
private runtimeVerifierIdCounter;
|
|
206
|
+
private serviceToken;
|
|
207
|
+
private serviceTokenExp;
|
|
208
|
+
private serviceTokenPromise;
|
|
209
|
+
private readonly agentSessionIds;
|
|
210
|
+
private readonly pendingSessionDisconnects;
|
|
211
|
+
constructor(options: KontextOptions);
|
|
212
|
+
/**
|
|
213
|
+
* Cleanup method for runtimes that create/dispose SDK instances dynamically.
|
|
214
|
+
* Ensures this instance can be garbage-collected by removing static references.
|
|
215
|
+
*/
|
|
216
|
+
destroy(): Promise<void>;
|
|
217
|
+
private static ensureShutdownHandlers;
|
|
218
|
+
/**
|
|
219
|
+
* Express middleware: `.well-known` metadata + bearer auth + MCP transport + sessions.
|
|
220
|
+
*
|
|
221
|
+
* Must be mounted at the app root (not a sub-path) because RFC 9728 requires
|
|
222
|
+
* `/.well-known/oauth-protected-resource` at the root. Use `mcpPath` to set
|
|
223
|
+
* the transport endpoint path.
|
|
224
|
+
*
|
|
225
|
+
* @param server - An `McpServer` instance for single-session use, or a
|
|
226
|
+
* `() => McpServer` factory for concurrent sessions (recommended in production).
|
|
227
|
+
* `McpServer.connect()` is 1:1 per the MCP spec — passing a factory ensures
|
|
228
|
+
* each session gets its own instance.
|
|
229
|
+
*
|
|
230
|
+
* @example Factory pattern (recommended for concurrent sessions)
|
|
231
|
+
* ```typescript
|
|
232
|
+
* app.use(kontext.middleware(() => createServer()));
|
|
233
|
+
* ```
|
|
234
|
+
*
|
|
235
|
+
* @example Single instance (local dev / single session)
|
|
236
|
+
* ```typescript
|
|
237
|
+
* app.use(kontext.middleware(server));
|
|
238
|
+
* ```
|
|
239
|
+
*
|
|
240
|
+
* @example Custom path
|
|
241
|
+
* ```typescript
|
|
242
|
+
* app.use(kontext.middleware(createServer, { mcpPath: "/api/mcp" }));
|
|
243
|
+
* ```
|
|
244
|
+
*/
|
|
245
|
+
middleware(server: McpServerOrFactory, options?: MiddlewareOptions): Router;
|
|
246
|
+
/**
|
|
247
|
+
* Exchange a user's access token for an integration credential.
|
|
248
|
+
*
|
|
249
|
+
* @param integration - Integration name (e.g., "github")
|
|
250
|
+
* @param token - The user's Bearer token (from `authInfo.token`)
|
|
251
|
+
* @returns Integration credential with `accessToken` and `authorization` header
|
|
252
|
+
*
|
|
253
|
+
* @throws {IntegrationConnectionRequiredError} User hasn't connected this integration
|
|
254
|
+
* @throws {OAuthError} Token exchange failed
|
|
255
|
+
*/
|
|
256
|
+
require(integration: IntegrationName, token: string): Promise<IntegrationCredential>;
|
|
257
|
+
/**
|
|
258
|
+
* Resolve per-user credential key/value pairs for an internal MCP integration.
|
|
259
|
+
*
|
|
260
|
+
* @param integration - Integration UUID or name
|
|
261
|
+
* @param token - The user's Bearer token (from `authInfo.token`)
|
|
262
|
+
* @returns Decrypted credential map for the current user and integration
|
|
263
|
+
*
|
|
264
|
+
* @throws {IntegrationConnectionRequiredError} User has not provided required credentials
|
|
265
|
+
* @throws {OAuthError} Runtime credential resolution failed
|
|
266
|
+
*/
|
|
267
|
+
requireCredentials(integration: IntegrationName, token: string): Promise<IntegrationResolvedCredentials>;
|
|
268
|
+
private getGatewayAudiences;
|
|
269
|
+
private isGatewayScopedToken;
|
|
270
|
+
private extractTokenAudiences;
|
|
271
|
+
private resolveRuntimeIntegrationId;
|
|
272
|
+
private isUuid;
|
|
273
|
+
/**
|
|
274
|
+
* Fetch a browser-openable connect URL for a missing integration.
|
|
275
|
+
*
|
|
276
|
+
* Per the integration-interrupt-flow spec, the SDK:
|
|
277
|
+
* 1. Exchanges the user's token for a resource-scoped mcp-gateway JWT
|
|
278
|
+
* 2. Calls POST /mcp/integrations/:id/oauth/init with that JWT
|
|
279
|
+
* 3. Returns the `connectUrl` (intermediate endpoint with one-time token)
|
|
280
|
+
*
|
|
281
|
+
* The connect URL points to our own server (ticket pattern), which
|
|
282
|
+
* validates the ticket, sets a browser session cookie, then redirects
|
|
283
|
+
* to the actual OAuth provider.
|
|
284
|
+
*/
|
|
285
|
+
private fetchConnectUrl;
|
|
286
|
+
private getOAuthMetadata;
|
|
287
|
+
private applyMetadataTransform;
|
|
288
|
+
private cloneOAuthMetadata;
|
|
289
|
+
private fetchOAuthMetadata;
|
|
290
|
+
private resolveResourceServerUrl;
|
|
291
|
+
private getOrCreateRuntimeAuthContext;
|
|
292
|
+
private getRuntimeAuthCacheKey;
|
|
293
|
+
private respondMetadataInitError;
|
|
294
|
+
private evictExpiredCredentials;
|
|
295
|
+
private evictExpiredResolvedCredentials;
|
|
296
|
+
private trimCacheToFit;
|
|
297
|
+
private createTokenVerifier;
|
|
298
|
+
private getServiceToken;
|
|
299
|
+
private reportEvent;
|
|
300
|
+
private createAgentSession;
|
|
301
|
+
private disconnectAgentSessionByAgentSessionId;
|
|
302
|
+
private disconnectAgentSession;
|
|
303
|
+
private disconnectAllSessions;
|
|
304
|
+
private runBearerAuth;
|
|
305
|
+
private createMcpHandler;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
export { type IntegrationCredential as I, type KnownIntegration as K, type McpServerFactory as M, type IntegrationName as a, type IntegrationResolvedCredentials as b, Kontext as c, type KontextOptions as d, type McpServerOrFactory as e, type MiddlewareOptions as f };
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
import * as _modelcontextprotocol_sdk_server_streamableHttp_js from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
3
|
+
import * as _modelcontextprotocol_sdk_server_auth_types_js from '@modelcontextprotocol/sdk/server/auth/types.js';
|
|
4
|
+
import * as _modelcontextprotocol_sdk_shared_auth_js from '@modelcontextprotocol/sdk/shared/auth.js';
|
|
5
|
+
import * as _modelcontextprotocol_sdk_server_auth_provider_js from '@modelcontextprotocol/sdk/server/auth/provider.js';
|
|
6
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Known integration short names.
|
|
10
|
+
*
|
|
11
|
+
* Custom integrations can be passed as arbitrary strings.
|
|
12
|
+
*/
|
|
13
|
+
type KnownIntegration = "github" | "gmail" | "google-calendar" | "google-drive" | "slack" | "linear" | "notion" | "jira" | "confluence" | "figma" | "stripe" | "shopify" | "salesforce" | "hubspot" | "asana" | "discord" | "twilio" | "sendgrid" | "openai" | "anthropic";
|
|
14
|
+
/**
|
|
15
|
+
* An integration name — either a well-known short name or a custom string.
|
|
16
|
+
*/
|
|
17
|
+
type IntegrationName = KnownIntegration | (string & {});
|
|
18
|
+
/**
|
|
19
|
+
* A credential returned by `kontext.require()`.
|
|
20
|
+
*
|
|
21
|
+
* Provides the access token and a pre-formatted authorization header.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* const github = await kontext.require("github", token);
|
|
26
|
+
* const res = await fetch("https://api.github.com/user", {
|
|
27
|
+
* headers: { Authorization: github.authorization },
|
|
28
|
+
* });
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
interface IntegrationCredential {
|
|
32
|
+
/** The raw access token for the integration */
|
|
33
|
+
accessToken: string;
|
|
34
|
+
/** Token type (usually "Bearer") */
|
|
35
|
+
tokenType: string;
|
|
36
|
+
/**
|
|
37
|
+
* Pre-formatted authorization header value.
|
|
38
|
+
* Typically `"Bearer <accessToken>"`, ready to use in HTTP headers.
|
|
39
|
+
*/
|
|
40
|
+
authorization: string;
|
|
41
|
+
/** Time in seconds until the token expires (undefined = no expiry info) */
|
|
42
|
+
expiresIn?: number;
|
|
43
|
+
/** Scopes granted by the integration */
|
|
44
|
+
scope?: string;
|
|
45
|
+
/** The integration name this credential was issued for */
|
|
46
|
+
integration: IntegrationName;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* A decrypted per-user credential map for internal MCP integrations.
|
|
50
|
+
*/
|
|
51
|
+
interface IntegrationResolvedCredentials {
|
|
52
|
+
/** The original integration identifier passed to requireCredentials() */
|
|
53
|
+
integration: IntegrationName;
|
|
54
|
+
/** Canonical integration UUID */
|
|
55
|
+
integrationId: string;
|
|
56
|
+
/** Credential key/value map resolved for the current user */
|
|
57
|
+
credentials: Record<string, string>;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Configuration for the `Kontext` class.
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```typescript
|
|
64
|
+
* const kontext = new Kontext({ clientId: "mcp_my-server" });
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
interface KontextOptions {
|
|
68
|
+
/** OAuth client ID from the Kontext dashboard. */
|
|
69
|
+
clientId: string;
|
|
70
|
+
/** Kontext API base URL. @default "https://api.kontext.dev" */
|
|
71
|
+
apiUrl?: string;
|
|
72
|
+
/** OAuth client secret. @default KONTEXT_CLIENT_SECRET env var */
|
|
73
|
+
clientSecret?: string;
|
|
74
|
+
/**
|
|
75
|
+
* Optional token issuer override(s) accepted during bearer token validation.
|
|
76
|
+
* Use this when your OAuth server issues tokens with an issuer different from
|
|
77
|
+
* the public metadata issuer.
|
|
78
|
+
*
|
|
79
|
+
* @default KONTEXT_TOKEN_ISSUER env var (comma-separated values supported)
|
|
80
|
+
*/
|
|
81
|
+
tokenIssuer?: string | string[];
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* A factory function that creates a fresh `McpServer` instance per session.
|
|
85
|
+
*
|
|
86
|
+
* Use this in production to support concurrent MCP sessions — `McpServer.connect()`
|
|
87
|
+
* is 1:1 per the MCP spec, so sharing a single instance across sessions will throw.
|
|
88
|
+
*/
|
|
89
|
+
type McpServerFactory = () => McpServer;
|
|
90
|
+
/**
|
|
91
|
+
* An `McpServer` instance (for single-session / local dev) or a factory
|
|
92
|
+
* function that creates one per session (for concurrent production use).
|
|
93
|
+
*/
|
|
94
|
+
type McpServerOrFactory = McpServer | McpServerFactory;
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Options for `kontext.middleware(server)`.
|
|
98
|
+
*/
|
|
99
|
+
interface MiddlewareOptions {
|
|
100
|
+
/** Path for the MCP transport endpoint. @default "/mcp" */
|
|
101
|
+
mcpPath?: string;
|
|
102
|
+
/** URL of this server (for resource metadata). Auto-detected from request if not set. */
|
|
103
|
+
resourceServerUrl?: string;
|
|
104
|
+
/**
|
|
105
|
+
* Skip OAuth metadata fetching and bearer auth entirely.
|
|
106
|
+
* Useful for local development and testing with the MCP Inspector.
|
|
107
|
+
*
|
|
108
|
+
* **Never use in production.**
|
|
109
|
+
*/
|
|
110
|
+
dangerouslyOmitAuth?: boolean;
|
|
111
|
+
/**
|
|
112
|
+
* Custom token verifier. Replaces the built-in `KontextTokenVerifier`.
|
|
113
|
+
*
|
|
114
|
+
* Use this to integrate custom session resolution (e.g. a gateway's
|
|
115
|
+
* internal verification API) while still using the middleware's
|
|
116
|
+
* transport, metadata, and session management.
|
|
117
|
+
*
|
|
118
|
+
* When provided, the middleware skips JWKS-based verification and
|
|
119
|
+
* delegates entirely to this verifier.
|
|
120
|
+
*/
|
|
121
|
+
verifier?: _modelcontextprotocol_sdk_server_auth_provider_js.OAuthTokenVerifier;
|
|
122
|
+
/**
|
|
123
|
+
* Transform OAuth metadata after fetching from the authorization server.
|
|
124
|
+
*
|
|
125
|
+
* Useful for URL rewriting (e.g. replacing internal Hydra URLs with
|
|
126
|
+
* public-facing URLs in a gateway setup).
|
|
127
|
+
*
|
|
128
|
+
* The transform runs before the middleware rewrites the `issuer` field.
|
|
129
|
+
*/
|
|
130
|
+
metadataTransform?: (metadata: _modelcontextprotocol_sdk_shared_auth_js.OAuthMetadata) => _modelcontextprotocol_sdk_shared_auth_js.OAuthMetadata;
|
|
131
|
+
/**
|
|
132
|
+
* Called after a new MCP session is initialized.
|
|
133
|
+
*
|
|
134
|
+
* When a custom `verifier` is provided, `authInfo` contains the
|
|
135
|
+
* result of that verifier (including `extra` fields). This allows
|
|
136
|
+
* the gateway to receive rich session context.
|
|
137
|
+
*
|
|
138
|
+
* The `transport` is provided so callers can manage session
|
|
139
|
+
* lifecycle (e.g. closing on revocation).
|
|
140
|
+
*/
|
|
141
|
+
onSessionInitialized?: (sessionId: string, authInfo?: _modelcontextprotocol_sdk_server_auth_types_js.AuthInfo, transport?: _modelcontextprotocol_sdk_server_streamableHttp_js.StreamableHTTPServerTransport) => void;
|
|
142
|
+
/** Called when an MCP session is closed. */
|
|
143
|
+
onSessionClosed?: (sessionId: string) => void;
|
|
144
|
+
/** Maximum request body size for MCP POST requests. Passed to express.json({ limit }). @default "1mb" */
|
|
145
|
+
bodyLimit?: string | number;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Kontext — the v3 server SDK entry point.
|
|
150
|
+
*
|
|
151
|
+
* Two methods:
|
|
152
|
+
* kontext.middleware(server) — Express middleware (auth + metadata + transport + sessions)
|
|
153
|
+
* kontext.require(integration, token) — RFC 8693 token exchange with caching
|
|
154
|
+
* kontext.requireCredentials(integration, token) — Resolve per-user internal credentials
|
|
155
|
+
*
|
|
156
|
+
* @example Factory pattern (recommended for production — supports concurrent sessions)
|
|
157
|
+
* ```typescript
|
|
158
|
+
* import { Kontext } from "@kontext-dev/js-sdk/server";
|
|
159
|
+
* import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
160
|
+
* import express from "express";
|
|
161
|
+
*
|
|
162
|
+
* const kontext = new Kontext({ clientId: "mcp_my-server" });
|
|
163
|
+
*
|
|
164
|
+
* function createServer() {
|
|
165
|
+
* const server = new McpServer({ name: "my-server", version: "1.0.0" });
|
|
166
|
+
* server.tool("list_repos", {}, async (args, { authInfo }) => {
|
|
167
|
+
* const github = await kontext.require("github", authInfo!.token);
|
|
168
|
+
* const res = await fetch("https://api.github.com/user/repos", {
|
|
169
|
+
* headers: { Authorization: github.authorization },
|
|
170
|
+
* });
|
|
171
|
+
* return { content: [{ type: "text", text: JSON.stringify(await res.json()) }] };
|
|
172
|
+
* });
|
|
173
|
+
* return server;
|
|
174
|
+
* }
|
|
175
|
+
*
|
|
176
|
+
* const app = express();
|
|
177
|
+
* app.use(kontext.middleware(createServer)); // /mcp endpoint + /.well-known/* metadata
|
|
178
|
+
* app.listen(3000);
|
|
179
|
+
* ```
|
|
180
|
+
*/
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* The v3 Kontext server SDK.
|
|
184
|
+
*
|
|
185
|
+
* Provides two methods:
|
|
186
|
+
* - `middleware(server)` — Express Router with auth metadata, bearer validation, and MCP transport.
|
|
187
|
+
* Accepts an `McpServer` instance (single-session) or a factory `() => McpServer` (concurrent sessions).
|
|
188
|
+
* - `require(integration, token)` — RFC 8693 token exchange with in-memory caching
|
|
189
|
+
* - `requireCredentials(integration, token)` — Resolve per-user credential maps for internal integrations
|
|
190
|
+
*/
|
|
191
|
+
declare class Kontext {
|
|
192
|
+
private static readonly shutdownInstances;
|
|
193
|
+
private static shutdownHandlersRegistered;
|
|
194
|
+
private readonly clientId;
|
|
195
|
+
private readonly clientSecret;
|
|
196
|
+
private readonly apiUrl;
|
|
197
|
+
private readonly tokenIssuers;
|
|
198
|
+
private oauthMetadata;
|
|
199
|
+
private metadataFetchedAt;
|
|
200
|
+
private metadataPromise;
|
|
201
|
+
private readonly credentialCache;
|
|
202
|
+
private readonly resolvedCredentialCache;
|
|
203
|
+
private readonly runtimeAuthCache;
|
|
204
|
+
private readonly runtimeVerifierIds;
|
|
205
|
+
private runtimeVerifierIdCounter;
|
|
206
|
+
private serviceToken;
|
|
207
|
+
private serviceTokenExp;
|
|
208
|
+
private serviceTokenPromise;
|
|
209
|
+
private readonly agentSessionIds;
|
|
210
|
+
private readonly pendingSessionDisconnects;
|
|
211
|
+
constructor(options: KontextOptions);
|
|
212
|
+
/**
|
|
213
|
+
* Cleanup method for runtimes that create/dispose SDK instances dynamically.
|
|
214
|
+
* Ensures this instance can be garbage-collected by removing static references.
|
|
215
|
+
*/
|
|
216
|
+
destroy(): Promise<void>;
|
|
217
|
+
private static ensureShutdownHandlers;
|
|
218
|
+
/**
|
|
219
|
+
* Express middleware: `.well-known` metadata + bearer auth + MCP transport + sessions.
|
|
220
|
+
*
|
|
221
|
+
* Must be mounted at the app root (not a sub-path) because RFC 9728 requires
|
|
222
|
+
* `/.well-known/oauth-protected-resource` at the root. Use `mcpPath` to set
|
|
223
|
+
* the transport endpoint path.
|
|
224
|
+
*
|
|
225
|
+
* @param server - An `McpServer` instance for single-session use, or a
|
|
226
|
+
* `() => McpServer` factory for concurrent sessions (recommended in production).
|
|
227
|
+
* `McpServer.connect()` is 1:1 per the MCP spec — passing a factory ensures
|
|
228
|
+
* each session gets its own instance.
|
|
229
|
+
*
|
|
230
|
+
* @example Factory pattern (recommended for concurrent sessions)
|
|
231
|
+
* ```typescript
|
|
232
|
+
* app.use(kontext.middleware(() => createServer()));
|
|
233
|
+
* ```
|
|
234
|
+
*
|
|
235
|
+
* @example Single instance (local dev / single session)
|
|
236
|
+
* ```typescript
|
|
237
|
+
* app.use(kontext.middleware(server));
|
|
238
|
+
* ```
|
|
239
|
+
*
|
|
240
|
+
* @example Custom path
|
|
241
|
+
* ```typescript
|
|
242
|
+
* app.use(kontext.middleware(createServer, { mcpPath: "/api/mcp" }));
|
|
243
|
+
* ```
|
|
244
|
+
*/
|
|
245
|
+
middleware(server: McpServerOrFactory, options?: MiddlewareOptions): Router;
|
|
246
|
+
/**
|
|
247
|
+
* Exchange a user's access token for an integration credential.
|
|
248
|
+
*
|
|
249
|
+
* @param integration - Integration name (e.g., "github")
|
|
250
|
+
* @param token - The user's Bearer token (from `authInfo.token`)
|
|
251
|
+
* @returns Integration credential with `accessToken` and `authorization` header
|
|
252
|
+
*
|
|
253
|
+
* @throws {IntegrationConnectionRequiredError} User hasn't connected this integration
|
|
254
|
+
* @throws {OAuthError} Token exchange failed
|
|
255
|
+
*/
|
|
256
|
+
require(integration: IntegrationName, token: string): Promise<IntegrationCredential>;
|
|
257
|
+
/**
|
|
258
|
+
* Resolve per-user credential key/value pairs for an internal MCP integration.
|
|
259
|
+
*
|
|
260
|
+
* @param integration - Integration UUID or name
|
|
261
|
+
* @param token - The user's Bearer token (from `authInfo.token`)
|
|
262
|
+
* @returns Decrypted credential map for the current user and integration
|
|
263
|
+
*
|
|
264
|
+
* @throws {IntegrationConnectionRequiredError} User has not provided required credentials
|
|
265
|
+
* @throws {OAuthError} Runtime credential resolution failed
|
|
266
|
+
*/
|
|
267
|
+
requireCredentials(integration: IntegrationName, token: string): Promise<IntegrationResolvedCredentials>;
|
|
268
|
+
private getGatewayAudiences;
|
|
269
|
+
private isGatewayScopedToken;
|
|
270
|
+
private extractTokenAudiences;
|
|
271
|
+
private resolveRuntimeIntegrationId;
|
|
272
|
+
private isUuid;
|
|
273
|
+
/**
|
|
274
|
+
* Fetch a browser-openable connect URL for a missing integration.
|
|
275
|
+
*
|
|
276
|
+
* Per the integration-interrupt-flow spec, the SDK:
|
|
277
|
+
* 1. Exchanges the user's token for a resource-scoped mcp-gateway JWT
|
|
278
|
+
* 2. Calls POST /mcp/integrations/:id/oauth/init with that JWT
|
|
279
|
+
* 3. Returns the `connectUrl` (intermediate endpoint with one-time token)
|
|
280
|
+
*
|
|
281
|
+
* The connect URL points to our own server (ticket pattern), which
|
|
282
|
+
* validates the ticket, sets a browser session cookie, then redirects
|
|
283
|
+
* to the actual OAuth provider.
|
|
284
|
+
*/
|
|
285
|
+
private fetchConnectUrl;
|
|
286
|
+
private getOAuthMetadata;
|
|
287
|
+
private applyMetadataTransform;
|
|
288
|
+
private cloneOAuthMetadata;
|
|
289
|
+
private fetchOAuthMetadata;
|
|
290
|
+
private resolveResourceServerUrl;
|
|
291
|
+
private getOrCreateRuntimeAuthContext;
|
|
292
|
+
private getRuntimeAuthCacheKey;
|
|
293
|
+
private respondMetadataInitError;
|
|
294
|
+
private evictExpiredCredentials;
|
|
295
|
+
private evictExpiredResolvedCredentials;
|
|
296
|
+
private trimCacheToFit;
|
|
297
|
+
private createTokenVerifier;
|
|
298
|
+
private getServiceToken;
|
|
299
|
+
private reportEvent;
|
|
300
|
+
private createAgentSession;
|
|
301
|
+
private disconnectAgentSessionByAgentSessionId;
|
|
302
|
+
private disconnectAgentSession;
|
|
303
|
+
private disconnectAllSessions;
|
|
304
|
+
private runBearerAuth;
|
|
305
|
+
private createMcpHandler;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
export { type IntegrationCredential as I, type KnownIntegration as K, type McpServerFactory as M, type IntegrationName as a, type IntegrationResolvedCredentials as b, Kontext as c, type KontextOptions as d, type McpServerOrFactory as e, type MiddlewareOptions as f };
|