@buildbase/sdk 0.0.51 → 0.0.54
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/AGENTS.md +24 -8
- package/CHANGELOG.md +102 -0
- package/README.md +283 -33
- package/dist/css/styles.css +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1248 -76
- package/dist/index.mjs +1 -1
- package/dist/mcp/index.cjs +1 -0
- package/dist/mcp/index.d.ts +1956 -0
- package/dist/mcp/index.mjs +1 -0
- package/dist/react/chunks/{SettingsDialog-DitAiAqr.cjs → SettingsDialog-B28WJsAr.cjs} +1 -1
- package/dist/react/chunks/{SettingsDialog-uVKFxlal.mjs → SettingsDialog-blhppbNm.mjs} +1 -1
- package/dist/react/chunks/{SubscriptionDialog-P0GlXEyn.mjs → SubscriptionDialog-BTWVX3cH.mjs} +1 -1
- package/dist/react/chunks/{SubscriptionDialog-Cg-qYVKr.cjs → SubscriptionDialog-QKmwvJU1.cjs} +1 -1
- package/dist/react/chunks/ar-1Z1MOGAP.mjs +2 -0
- package/dist/react/chunks/ar-VGzBv3AZ.cjs +2 -0
- package/dist/react/chunks/de-BjdDg60Y.cjs +2 -0
- package/dist/react/chunks/de-CXUItplO.mjs +2 -0
- package/dist/react/chunks/es-BBPsSZUp.cjs +2 -0
- package/dist/react/chunks/es-BTbzVutz.mjs +2 -0
- package/dist/react/chunks/fr-Cax48X_S.cjs +2 -0
- package/dist/react/chunks/fr-DPMeOQu3.mjs +2 -0
- package/dist/react/chunks/hi-BJqvpG6d.cjs +2 -0
- package/dist/react/chunks/hi-JfJx-LV7.mjs +2 -0
- package/dist/react/chunks/ja-CDGtLzTk.mjs +2 -0
- package/dist/react/chunks/ja-DvVyj5xX.cjs +2 -0
- package/dist/react/chunks/react-6QJCOE-D.cjs +2 -0
- package/dist/react/chunks/react-CC6T7Zky.mjs +2 -0
- package/dist/react/chunks/zh-BAcqxkxk.cjs +2 -0
- package/dist/react/chunks/zh-BNZ2Ooe8.mjs +2 -0
- package/dist/react/index.cjs +1 -1
- package/dist/react/index.d.ts +98 -43
- package/dist/react/index.mjs +1 -1
- package/package.json +20 -5
- package/dist/react/chunks/ar-SrPOJXdL.mjs +0 -2
- package/dist/react/chunks/ar-a3aRbPCs.cjs +0 -2
- package/dist/react/chunks/de-DE3_z7r0.cjs +0 -2
- package/dist/react/chunks/de-xnPl61SS.mjs +0 -2
- package/dist/react/chunks/es-C_xcyGtp.cjs +0 -2
- package/dist/react/chunks/es-CyuBtosP.mjs +0 -2
- package/dist/react/chunks/fr-BMu7Bk4k.cjs +0 -2
- package/dist/react/chunks/fr-CxuDLZ27.mjs +0 -2
- package/dist/react/chunks/hi-CQ215yc9.cjs +0 -2
- package/dist/react/chunks/hi-CpuvyorS.mjs +0 -2
- package/dist/react/chunks/ja-DIJ_xCIi.mjs +0 -2
- package/dist/react/chunks/ja-DK6Buuws.cjs +0 -2
- package/dist/react/chunks/react-C2ikFWBG.cjs +0 -2
- package/dist/react/chunks/react-CCukNQ4q.mjs +0 -2
- package/dist/react/chunks/zh-CYQwZiBL.mjs +0 -2
- package/dist/react/chunks/zh-Dt-apS2s.cjs +0 -2
|
@@ -0,0 +1,1956 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
/** An Agent Skill (Agent Skills Discovery RFC v0.2.0) published by this app. */
|
|
4
|
+
interface AgentSkill {
|
|
5
|
+
/** Stable slug, e.g. `imejis-api`. */
|
|
6
|
+
name: string;
|
|
7
|
+
/** One-line human/agent-readable summary. */
|
|
8
|
+
description: string;
|
|
9
|
+
/** Full markdown content of the SKILL.md served for this skill. */
|
|
10
|
+
content: string;
|
|
11
|
+
/**
|
|
12
|
+
* Path the SKILL.md is served from. Defaults to
|
|
13
|
+
* `/.well-known/agent-skills/<name>/SKILL.md`.
|
|
14
|
+
*/
|
|
15
|
+
path?: string;
|
|
16
|
+
/** Skill artifact kind. Defaults to `skill-md`. */
|
|
17
|
+
type?: 'skill-md' | 'archive';
|
|
18
|
+
}
|
|
19
|
+
/** One API described in an API Catalog (RFC 9727 / RFC 9264 linkset). */
|
|
20
|
+
interface ApiCatalogApi {
|
|
21
|
+
/** Anchor URL identifying the API, e.g. `https://api.imejis.io`. */
|
|
22
|
+
anchor: string;
|
|
23
|
+
/** OpenAPI / machine-readable description URL (link rel `service-desc`). */
|
|
24
|
+
serviceDesc?: string;
|
|
25
|
+
/** Human documentation URL (link rel `service-doc`). */
|
|
26
|
+
serviceDoc?: string;
|
|
27
|
+
/** Health / status endpoint URL (link rel `status`). */
|
|
28
|
+
status?: string;
|
|
29
|
+
/** Optional human title for the API. */
|
|
30
|
+
title?: string;
|
|
31
|
+
}
|
|
32
|
+
/** MCP Server Card (SEP-1649 v1.0), advertising a live MCP server. */
|
|
33
|
+
interface McpServerCard {
|
|
34
|
+
/** Server name. */
|
|
35
|
+
name: string;
|
|
36
|
+
/** Server version. */
|
|
37
|
+
version: string;
|
|
38
|
+
/** MCP transport endpoint URL the agent connects to. */
|
|
39
|
+
endpoint: string;
|
|
40
|
+
/** Transport type. Defaults to `"streamable-http"`. */
|
|
41
|
+
transport?: string;
|
|
42
|
+
/** MCP protocol version the server speaks. Defaults to `"2025-06-18"`. */
|
|
43
|
+
protocolVersion?: string;
|
|
44
|
+
/**
|
|
45
|
+
* Capability flags. Booleans per SEP-1649 v1.0; a legacy object value
|
|
46
|
+
* (e.g. `{ tools: {} }`) is normalized to booleans by presence.
|
|
47
|
+
*/
|
|
48
|
+
capabilities?: Record<string, unknown>;
|
|
49
|
+
/** Optional human description. */
|
|
50
|
+
description?: string;
|
|
51
|
+
/** Documentation URL. */
|
|
52
|
+
documentationUrl?: string;
|
|
53
|
+
}
|
|
54
|
+
/** One OAuth scope an app declares in its scope catalog. */
|
|
55
|
+
interface AppScope {
|
|
56
|
+
/** Scope name, e.g. `designs:read`. */
|
|
57
|
+
name: string;
|
|
58
|
+
/** Human-readable description, shown on the consent screen. */
|
|
59
|
+
description: string;
|
|
60
|
+
}
|
|
61
|
+
/** One skill advertised on the A2A Agent Card. */
|
|
62
|
+
interface A2ACardSkill {
|
|
63
|
+
id: string;
|
|
64
|
+
name: string;
|
|
65
|
+
description: string;
|
|
66
|
+
tags?: string[];
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Overrides for the A2A Agent Card (`/.well-known/agent-card.json`). Every
|
|
70
|
+
* field is optional — the card is fully derived from `site` + `skills` by
|
|
71
|
+
* default. See {@link buildA2AAgentCard}.
|
|
72
|
+
*/
|
|
73
|
+
interface A2ACardConfig {
|
|
74
|
+
name?: string;
|
|
75
|
+
version?: string;
|
|
76
|
+
description?: string;
|
|
77
|
+
/** The endpoint agents connect to. Defaults to `siteUrl`. */
|
|
78
|
+
serviceUrl?: string;
|
|
79
|
+
/** Transport protocol advertised for `serviceUrl`. Defaults to `'http'`. */
|
|
80
|
+
transportProtocol?: string;
|
|
81
|
+
/** A2A capability flags. Defaults to `{ streaming: false, pushNotifications: false }`. */
|
|
82
|
+
capabilities?: Record<string, unknown>;
|
|
83
|
+
/** Skills; defaults to a mapping of `config.skills` (or a generic site skill). */
|
|
84
|
+
skills?: A2ACardSkill[];
|
|
85
|
+
}
|
|
86
|
+
/** One robots.txt policy group (a `User-agent:` block). */
|
|
87
|
+
interface RobotsPolicy {
|
|
88
|
+
/** User-agent(s) this group applies to, e.g. `'*'` or `'GPTBot'`. */
|
|
89
|
+
userAgent: string | string[];
|
|
90
|
+
/** Paths to allow, e.g. `['/']`. */
|
|
91
|
+
allow?: string[];
|
|
92
|
+
/** Paths to disallow, e.g. `['/api/']`. */
|
|
93
|
+
disallow?: string[];
|
|
94
|
+
/** Optional `Crawl-delay` (non-standard but widely honored). */
|
|
95
|
+
crawlDelay?: number;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Content Signals (https://contentsignals.org) — declares how crawlers may use
|
|
99
|
+
* this site's content. Each flag renders as `<signal>=yes|no`; omitted flags
|
|
100
|
+
* are not emitted (unset = no preference expressed).
|
|
101
|
+
*/
|
|
102
|
+
interface ContentSignals {
|
|
103
|
+
/** May content be indexed for search? → `search=yes|no`. */
|
|
104
|
+
search?: boolean;
|
|
105
|
+
/** May content be used as AI input (RAG, grounding)? → `ai-input=yes|no`. */
|
|
106
|
+
aiInput?: boolean;
|
|
107
|
+
/** May content be used for AI training? → `ai-train=yes|no`. */
|
|
108
|
+
aiTrain?: boolean;
|
|
109
|
+
}
|
|
110
|
+
/** Configuration for `buildRobotsTxt`. Every field is optional. */
|
|
111
|
+
interface RobotsConfig {
|
|
112
|
+
/** Policy groups. Defaults to `[{ userAgent: '*', allow: ['/'] }]`. */
|
|
113
|
+
policies?: RobotsPolicy[];
|
|
114
|
+
/**
|
|
115
|
+
* Stance toward known AI crawlers ({@link AI_BOT_USER_AGENTS}): `'allow'`
|
|
116
|
+
* (default — an explicit `Allow: /` group per bot, so readiness checkers see
|
|
117
|
+
* AI bots addressed), `'deny'` (a `Disallow: /` group per bot), or explicit
|
|
118
|
+
* per-bot policies for finer control.
|
|
119
|
+
*/
|
|
120
|
+
aiBots?: 'allow' | 'deny' | RobotsPolicy[];
|
|
121
|
+
/** Content-Signal directive attached to the `User-agent: *` group. */
|
|
122
|
+
contentSignals?: ContentSignals;
|
|
123
|
+
/**
|
|
124
|
+
* Sitemap URLs. Defaults to `${siteUrl}/sitemap.xml` when `config.sitemap`
|
|
125
|
+
* is set; pass `[]` to emit no `Sitemap:` line.
|
|
126
|
+
*/
|
|
127
|
+
sitemaps?: string[];
|
|
128
|
+
}
|
|
129
|
+
/** One URL entry for the generated sitemap.xml. */
|
|
130
|
+
interface SitemapUrl {
|
|
131
|
+
/** Absolute URL, or a path resolved against `siteUrl`. */
|
|
132
|
+
loc: string;
|
|
133
|
+
/** ISO-8601 last-modified date. */
|
|
134
|
+
lastmod?: string;
|
|
135
|
+
changefreq?: 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never';
|
|
136
|
+
/** 0.0–1.0. */
|
|
137
|
+
priority?: number;
|
|
138
|
+
}
|
|
139
|
+
/** Configuration for the agent-readiness discovery layer. */
|
|
140
|
+
interface AgentReadyConfig {
|
|
141
|
+
/** BuildBase server base URL, e.g. `https://api.buildbase.app` (no trailing slash needed). */
|
|
142
|
+
serverUrl: string;
|
|
143
|
+
/** The org id (24-hex) whose agent-readiness config to serve. */
|
|
144
|
+
orgId: string;
|
|
145
|
+
/**
|
|
146
|
+
* This app's public origin, e.g. `https://imejis.io`. Used to build absolute
|
|
147
|
+
* URLs in the Agent Card and to match RFC 9728 resource paths.
|
|
148
|
+
*/
|
|
149
|
+
siteUrl: string;
|
|
150
|
+
/** Static metadata for the Agent Card (`/.well-known/agent.json`). */
|
|
151
|
+
site: {
|
|
152
|
+
name: string;
|
|
153
|
+
description?: string;
|
|
154
|
+
/** Absolute URL to human/agent documentation. */
|
|
155
|
+
documentationUrl?: string;
|
|
156
|
+
/** Support/contact email surfaced on the Agent Card. */
|
|
157
|
+
contactEmail?: string;
|
|
158
|
+
/** Provider block; defaults to `{ name: site.name, url: siteUrl }`. */
|
|
159
|
+
provider?: {
|
|
160
|
+
name: string;
|
|
161
|
+
url: string;
|
|
162
|
+
};
|
|
163
|
+
};
|
|
164
|
+
/** Agent Skills to publish. Omit to skip the Agent Skills documents. */
|
|
165
|
+
skills?: AgentSkill[];
|
|
166
|
+
/**
|
|
167
|
+
* The app's OAuth scope catalog — the source of truth for `scopes_supported`
|
|
168
|
+
* in this app's RFC 9728 protected-resource metadata (served from your own
|
|
169
|
+
* origin). Declare real, per-app scopes here (`designs:read`,
|
|
170
|
+
* `render:execute`, …) instead of placeholders. A `protectedResources` entry
|
|
171
|
+
* without its own `scopes` list inherits every catalog scope name. Scopes are
|
|
172
|
+
* app-owned: the shared BuildBase authorization server stays scope-agnostic.
|
|
173
|
+
*/
|
|
174
|
+
scopes?: AppScope[];
|
|
175
|
+
/** security.txt fields (RFC 9116). Omit to skip serving security.txt. */
|
|
176
|
+
security?: {
|
|
177
|
+
/** Contact URI(s) — email (`mailto:`) or URL. */
|
|
178
|
+
contact: string | string[];
|
|
179
|
+
/** ISO-8601 expiry; strongly recommended by RFC 9116. */
|
|
180
|
+
expires?: string;
|
|
181
|
+
/** Security policy URL. */
|
|
182
|
+
policy?: string;
|
|
183
|
+
};
|
|
184
|
+
/**
|
|
185
|
+
* API Catalog entries (RFC 9727), served at `/.well-known/api-catalog` as
|
|
186
|
+
* `application/linkset+json`. Omit to skip.
|
|
187
|
+
*/
|
|
188
|
+
apiCatalog?: ApiCatalogApi[];
|
|
189
|
+
/**
|
|
190
|
+
* MCP Server Card (SEP-1649), served at `/.well-known/mcp/server-card.json`.
|
|
191
|
+
* Only set this when you actually run an MCP server — the card advertises a
|
|
192
|
+
* live transport endpoint. Omit to skip.
|
|
193
|
+
*/
|
|
194
|
+
mcpServerCard?: McpServerCard;
|
|
195
|
+
/**
|
|
196
|
+
* Raw `/auth.md` content (agent registration/auth instructions). If omitted,
|
|
197
|
+
* `buildAuthMd` generates one from the OAuth metadata + site config.
|
|
198
|
+
*/
|
|
199
|
+
authMd?: string;
|
|
200
|
+
/**
|
|
201
|
+
* Local `/llms.txt` content. Takes precedence over the org-authored llms.txt
|
|
202
|
+
* from the platform bundle — use when the app owns richer llms.txt content.
|
|
203
|
+
*/
|
|
204
|
+
llmsTxt?: string;
|
|
205
|
+
/**
|
|
206
|
+
* Local `/llms-full.txt` content (llmstxt.org expanded document). Omit to
|
|
207
|
+
* skip serving it (or serve your own static file, which then wins).
|
|
208
|
+
*/
|
|
209
|
+
llmsFullTxt?: string;
|
|
210
|
+
/**
|
|
211
|
+
* A2A Agent Card served at `/.well-known/agent-card.json`. Served by
|
|
212
|
+
* DEFAULT, derived from `site` + `skills`, so readiness scanners find a
|
|
213
|
+
* valid card with zero config. Pass `false` to disable, or an object to
|
|
214
|
+
* override any derived field.
|
|
215
|
+
*/
|
|
216
|
+
a2aCard?: false | A2ACardConfig;
|
|
217
|
+
/**
|
|
218
|
+
* Web Bot Auth key directory (IETF WebBotAuth) served at
|
|
219
|
+
* `/.well-known/http-message-signatures-directory`. Only for apps whose own
|
|
220
|
+
* outbound bot/agent signs its requests — publish the JWKS public keys here
|
|
221
|
+
* so receiving sites can verify the signatures. Omitted = not served.
|
|
222
|
+
*/
|
|
223
|
+
webBotAuth?: {
|
|
224
|
+
keys: Array<Record<string, unknown>>;
|
|
225
|
+
};
|
|
226
|
+
/**
|
|
227
|
+
* Extra literal documents served by {@link resolveAgentPath}, keyed by exact
|
|
228
|
+
* request path. The escape hatch for anything the SDK has no builder for —
|
|
229
|
+
* commerce discovery (x402, UCP, ACP, MPP), `/openapi.json`, future
|
|
230
|
+
* `.well-known` documents. A string value infers its content type from the
|
|
231
|
+
* path extension. Extra paths take precedence over built-in documents, so
|
|
232
|
+
* they can also override any SDK-generated document.
|
|
233
|
+
*/
|
|
234
|
+
extraPaths?: Record<string, string | {
|
|
235
|
+
body: string;
|
|
236
|
+
contentType?: string;
|
|
237
|
+
status?: number;
|
|
238
|
+
cacheControl?: string;
|
|
239
|
+
}>;
|
|
240
|
+
/** robots.txt generation (`buildRobotsTxt`). Omitted = sane defaults. */
|
|
241
|
+
robots?: RobotsConfig;
|
|
242
|
+
/**
|
|
243
|
+
* URLs for a minimal generated sitemap.xml (`buildSitemap`). Omit when the
|
|
244
|
+
* app already generates sitemaps (e.g. next-sitemap) — the builder then
|
|
245
|
+
* returns null and your own files win.
|
|
246
|
+
*/
|
|
247
|
+
sitemap?: {
|
|
248
|
+
urls: Array<string | SitemapUrl>;
|
|
249
|
+
};
|
|
250
|
+
/**
|
|
251
|
+
* RFC 9728 protected resources this app serves, defined locally (app-owned).
|
|
252
|
+
* When set, the SDK builds the `/.well-known/oauth-protected-resource`
|
|
253
|
+
* document from this config — `authorization_servers` is derived from
|
|
254
|
+
* `serverUrl`/`orgId` (the BuildBase issuer). Takes precedence over the
|
|
255
|
+
* platform bundle. Omit to fall back to the org-configured bundle.
|
|
256
|
+
*/
|
|
257
|
+
protectedResources?: Array<{
|
|
258
|
+
/** The protected API's resource URI. Defaults to `siteUrl`. */
|
|
259
|
+
resource?: string;
|
|
260
|
+
/** Scopes this resource accepts (`scopes_supported`). */
|
|
261
|
+
scopes?: string[];
|
|
262
|
+
/** Human documentation URL (`resource_documentation`). */
|
|
263
|
+
documentationUrl?: string;
|
|
264
|
+
/** Bearer methods (`bearer_methods_supported`). Defaults to `['header']`. */
|
|
265
|
+
bearerMethods?: string[];
|
|
266
|
+
}>;
|
|
267
|
+
/** TTL (seconds) for cached platform fetches. Default 300 (5 min). */
|
|
268
|
+
cacheTtlSeconds?: number;
|
|
269
|
+
/**
|
|
270
|
+
* Timeout (ms) for platform fetches. Fail-soft on timeout, so a hung or slow
|
|
271
|
+
* BuildBase server can't hang discovery routes forever. Default 5000; set `0`
|
|
272
|
+
* to disable.
|
|
273
|
+
*/
|
|
274
|
+
fetchTimeoutMs?: number;
|
|
275
|
+
/** Injectable fetch, mainly for testing. Defaults to the global `fetch`. */
|
|
276
|
+
fetch?: typeof fetch;
|
|
277
|
+
}
|
|
278
|
+
/** A rendered discovery document ready to become an HTTP response. */
|
|
279
|
+
interface DiscoveryDocument {
|
|
280
|
+
status: number;
|
|
281
|
+
contentType: string;
|
|
282
|
+
body: string;
|
|
283
|
+
cacheControl: string;
|
|
284
|
+
/** Value for a `Vary` response header, when the body is negotiated. */
|
|
285
|
+
vary?: string;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Built-in MCP tools mapping BuildBase capabilities to agent-callable tools.
|
|
290
|
+
*
|
|
291
|
+
* Authorization model: the agent acts as an authenticated app user — it knows
|
|
292
|
+
* your app, not BuildBase. Built-in tools therefore carry NO BuildBase-specific
|
|
293
|
+
* scope requirement; they're available whenever your `auth.verify` accepts the
|
|
294
|
+
* token and your app chose to expose them. Every call runs under the acting
|
|
295
|
+
* user's own BuildBase session, so the server enforces that user's permissions
|
|
296
|
+
* — an agent can never exceed what its user could do. Want per-scope gating on
|
|
297
|
+
* top? Set `requiredScopes` on your own custom tools — the handler enforces it.
|
|
298
|
+
*
|
|
299
|
+
* The read-vs-write boundary is YOUR choice via `builtinTools`: the default is
|
|
300
|
+
* `'readonly'` (reads only — least privilege). Opt in to `'all'` to also expose
|
|
301
|
+
* writes AND destructive/billing ops (workspace delete, subscription cancel,
|
|
302
|
+
* credit purchase — still gated by the user's own permissions), `false` to
|
|
303
|
+
* expose no built-ins, or `{ include, exclude }` to hand-pick specific tools.
|
|
304
|
+
*
|
|
305
|
+
* Every workspace-scoped tool accepts an optional `workspaceId` and falls back
|
|
306
|
+
* to the workspace pinned on the verified token (`McpAuthInfo.workspaceId`).
|
|
307
|
+
*/
|
|
308
|
+
|
|
309
|
+
/** Every built-in tool, keyed by name. */
|
|
310
|
+
declare const builtinMcpTools: ReadonlyMap<string, McpToolDefinition<any>>;
|
|
311
|
+
/** The name of a built-in BuildBase MCP tool. */
|
|
312
|
+
type BuiltinMcpToolName = 'list_workspaces' | 'get_workspace' | 'get_user_profile' | 'list_workspace_users' | 'get_subscription' | 'get_plans' | 'get_plan_versions' | 'get_public_plans' | 'get_plan_version' | 'list_invoices' | 'get_invoice' | 'get_quota_usage' | 'get_all_quota_usage' | 'get_usage_logs' | 'get_credit_balance' | 'list_credit_transactions' | 'get_credit_packages' | 'get_credit_buckets' | 'get_expiring_credits' | 'get_public_credit_packages' | 'check_feature_flag' | 'check_permission' | 'resolve_permissions' | 'get_settings' | 'record_usage' | 'record_usage_batch' | 'consume_credits' | 'send_notification' | 'create_workspace' | 'update_workspace' | 'delete_workspace' | 'invite_workspace_user' | 'remove_workspace_user' | 'update_workspace_user_role' | 'update_user_profile' | 'update_feature_flag' | 'create_subscription_checkout' | 'update_subscription' | 'cancel_subscription' | 'resume_subscription' | 'get_billing_portal_url' | 'purchase_credits';
|
|
313
|
+
/** Resolve a `builtinTools` config value to the tools it selects. */
|
|
314
|
+
declare function selectBuiltinTools(selection: 'all' | 'readonly' | false | {
|
|
315
|
+
include?: BuiltinMcpToolName[];
|
|
316
|
+
exclude?: BuiltinMcpToolName[];
|
|
317
|
+
}): McpToolDefinition<any>[];
|
|
318
|
+
|
|
319
|
+
interface IDocument {
|
|
320
|
+
_id: string;
|
|
321
|
+
/** Optional; some APIs only return _id. Prefer _id for identity. */
|
|
322
|
+
id?: string;
|
|
323
|
+
createdAt: string;
|
|
324
|
+
updatedAt: string;
|
|
325
|
+
deleted: boolean;
|
|
326
|
+
}
|
|
327
|
+
interface IUser extends IDocument {
|
|
328
|
+
_id: string;
|
|
329
|
+
name: string;
|
|
330
|
+
email: string;
|
|
331
|
+
/** Profile image URL. Often omitted or empty from API. */
|
|
332
|
+
image?: string;
|
|
333
|
+
role: string;
|
|
334
|
+
/** ISO country code. May be omitted. */
|
|
335
|
+
country?: string;
|
|
336
|
+
/** IANA timezone. May be omitted. */
|
|
337
|
+
timezone?: string;
|
|
338
|
+
/** Language code. May be omitted. */
|
|
339
|
+
language?: string;
|
|
340
|
+
/** Currency code. May be omitted. */
|
|
341
|
+
currency?: string;
|
|
342
|
+
attributes?: Record<string, string | number | boolean>;
|
|
343
|
+
}
|
|
344
|
+
type BillingInterval = 'monthly' | 'yearly' | 'quarterly';
|
|
345
|
+
/** Subscription status constants */
|
|
346
|
+
declare const SubscriptionStatus: {
|
|
347
|
+
readonly Active: "active";
|
|
348
|
+
readonly Trialing: "trialing";
|
|
349
|
+
readonly Canceled: "canceled";
|
|
350
|
+
readonly PastDue: "past_due";
|
|
351
|
+
readonly Paused: "paused";
|
|
352
|
+
readonly Incomplete: "incomplete";
|
|
353
|
+
readonly Unpaid: "unpaid";
|
|
354
|
+
};
|
|
355
|
+
type SubscriptionStatusType = (typeof SubscriptionStatus)[keyof typeof SubscriptionStatus];
|
|
356
|
+
interface ISubscription {
|
|
357
|
+
_id: string;
|
|
358
|
+
subscriptionStatus: SubscriptionStatusType;
|
|
359
|
+
/** Stripe Subscription ID (e.g. 'sub_...'). Present when linked to Stripe. */
|
|
360
|
+
subscriptionId?: string;
|
|
361
|
+
stripePriceId?: string;
|
|
362
|
+
stripeCurrentPeriodEnd?: string;
|
|
363
|
+
/** When the current monthly usage period ends (quotas reset on this date). */
|
|
364
|
+
usageCurrentPeriodEnd?: string;
|
|
365
|
+
cancelAtPeriodEnd: boolean;
|
|
366
|
+
billingInterval?: BillingInterval;
|
|
367
|
+
/** Trial start date (ISO string). Set when subscription is in trial. */
|
|
368
|
+
trialStart?: string;
|
|
369
|
+
/** Trial end date (ISO string). Set when subscription is in trial. */
|
|
370
|
+
trialEnd?: string;
|
|
371
|
+
/** When the subscription was canceled (ISO string). Soft-delete marker. */
|
|
372
|
+
canceledAt?: string;
|
|
373
|
+
/** Dunning state: 'none', 'notified', 'warning', 'final', 'suspended'. */
|
|
374
|
+
dunningState?: string;
|
|
375
|
+
/** Whether this subscription uses per-seat pricing. */
|
|
376
|
+
seatPricingEnabled?: boolean;
|
|
377
|
+
/** Current billable seat count. */
|
|
378
|
+
currentSeatCount?: number;
|
|
379
|
+
createdAt: string;
|
|
380
|
+
updatedAt: string;
|
|
381
|
+
plan?: {
|
|
382
|
+
_id: string;
|
|
383
|
+
name: string;
|
|
384
|
+
slug: string;
|
|
385
|
+
description?: string;
|
|
386
|
+
/** Stripe currency code (e.g. 'usd', 'inr', 'eur'). */
|
|
387
|
+
currency?: string;
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
interface ISubscriptionItem {
|
|
391
|
+
_id: string;
|
|
392
|
+
type: 'feature' | 'limit' | 'quota';
|
|
393
|
+
name: string;
|
|
394
|
+
slug: string;
|
|
395
|
+
description?: string;
|
|
396
|
+
category: string;
|
|
397
|
+
}
|
|
398
|
+
/** Per-interval quota value (plan-group/versions and public plans schema). */
|
|
399
|
+
interface IQuotaIntervalValue {
|
|
400
|
+
included: number;
|
|
401
|
+
/** Overage price in cents. Omitted in public plans; use pricingVariant.quotaOverages for display. */
|
|
402
|
+
overage?: number;
|
|
403
|
+
/** Stripe price ID for overage. Omitted in public plans; use pricingVariant.quotaOveragePriceIds. */
|
|
404
|
+
priceId?: string;
|
|
405
|
+
/** Unit size for overage pricing (e.g. 1000 = price per 1000 units). */
|
|
406
|
+
unitSize?: number;
|
|
407
|
+
}
|
|
408
|
+
/** Quota defined per billing interval (new plan-group/versions schema) */
|
|
409
|
+
interface IQuotaByInterval {
|
|
410
|
+
/** Whether over-usage beyond included is allowed (billed as overage). When false, usage is hard-capped at included amount. Default true. */
|
|
411
|
+
allowOverage?: boolean;
|
|
412
|
+
monthly?: IQuotaIntervalValue;
|
|
413
|
+
yearly?: IQuotaIntervalValue;
|
|
414
|
+
quarterly?: IQuotaIntervalValue;
|
|
415
|
+
}
|
|
416
|
+
/** Base pricing per interval. Values are often in cents (Stripe); convert for display. */
|
|
417
|
+
interface IBasePricing {
|
|
418
|
+
monthly: number;
|
|
419
|
+
yearly: number;
|
|
420
|
+
quarterly: number;
|
|
421
|
+
}
|
|
422
|
+
/** Stripe price IDs per billing interval (for a single currency variant). */
|
|
423
|
+
interface IStripePricesByInterval {
|
|
424
|
+
monthlyPriceId?: string;
|
|
425
|
+
yearlyPriceId?: string;
|
|
426
|
+
quarterlyPriceId?: string;
|
|
427
|
+
monthly?: string;
|
|
428
|
+
yearly?: string;
|
|
429
|
+
}
|
|
430
|
+
/** Overage amounts in cents per interval, keyed by quota slug. Used in pricing variants. */
|
|
431
|
+
type IQuotaOveragesByInterval = Record<string, {
|
|
432
|
+
monthly?: number;
|
|
433
|
+
yearly?: number;
|
|
434
|
+
quarterly?: number;
|
|
435
|
+
}>;
|
|
436
|
+
/** Overage Stripe price IDs per interval, keyed by quota slug. Used in pricing variants. */
|
|
437
|
+
type IQuotaOveragePriceIdsByInterval = Record<string, {
|
|
438
|
+
monthly?: string;
|
|
439
|
+
yearly?: string;
|
|
440
|
+
quarterly?: string;
|
|
441
|
+
}>;
|
|
442
|
+
/**
|
|
443
|
+
* Multi-currency pricing variant at plan version level.
|
|
444
|
+
* Each plan version can have multiple variants (e.g. usd, eur, inr, sgd).
|
|
445
|
+
*/
|
|
446
|
+
interface IPricingVariant {
|
|
447
|
+
_id: string;
|
|
448
|
+
currency: string;
|
|
449
|
+
basePricing: IBasePricing;
|
|
450
|
+
stripePrices: IStripePricesByInterval;
|
|
451
|
+
/** Per-seat pricing config. When enabled, a second recurring item is on the subscription. */
|
|
452
|
+
seatPricing?: {
|
|
453
|
+
enabled: boolean;
|
|
454
|
+
includedSeats: number;
|
|
455
|
+
/** Maximum seats allowed. 0 or undefined = unlimited. */
|
|
456
|
+
maxSeats?: number;
|
|
457
|
+
perSeat: IBasePricing;
|
|
458
|
+
};
|
|
459
|
+
/** Stripe Price IDs for the per-seat recurring price. */
|
|
460
|
+
seatStripePrices?: IStripePricesByInterval;
|
|
461
|
+
/** Overage cents per quota slug per interval. */
|
|
462
|
+
quotaOverages?: IQuotaOveragesByInterval;
|
|
463
|
+
/** Stripe price IDs for overage per quota slug per interval. */
|
|
464
|
+
quotaOveragePriceIds?: IQuotaOveragePriceIdsByInterval;
|
|
465
|
+
}
|
|
466
|
+
interface IPlanVersion {
|
|
467
|
+
_id: string;
|
|
468
|
+
version: number;
|
|
469
|
+
name: string;
|
|
470
|
+
status: 'draft' | 'published';
|
|
471
|
+
features?: Record<string, boolean>;
|
|
472
|
+
limits?: Record<string, number>;
|
|
473
|
+
/** Per-interval quotas (included, unitSize; overage from pricingVariant.quotaOverages). */
|
|
474
|
+
quotas?: Record<string, IQuotaByInterval>;
|
|
475
|
+
/** Multi-currency pricing. Each variant has currency, basePricing, stripePrices, quotaOverages. */
|
|
476
|
+
pricingVariants?: IPricingVariant[];
|
|
477
|
+
subscriptionItems?: ISubscriptionItem[];
|
|
478
|
+
/** Trial configuration. When enabled, users can start a free trial of this plan. */
|
|
479
|
+
trial?: {
|
|
480
|
+
enabled: boolean;
|
|
481
|
+
durationDays: number;
|
|
482
|
+
requireCard: boolean;
|
|
483
|
+
};
|
|
484
|
+
/** Credit grant configuration. When enabled, credits are granted to workspaces on this plan. */
|
|
485
|
+
creditGrant?: {
|
|
486
|
+
enabled: boolean;
|
|
487
|
+
/** Linked credit package (populated with name, slug, creditAmount). */
|
|
488
|
+
creditPackage?: {
|
|
489
|
+
_id: string;
|
|
490
|
+
name: string;
|
|
491
|
+
slug: string;
|
|
492
|
+
creditAmount: number;
|
|
493
|
+
} | string;
|
|
494
|
+
/** How unused plan credits are handled on renewal: 'reset' = expire old, 'topup' = add to existing. */
|
|
495
|
+
mode: 'reset' | 'topup';
|
|
496
|
+
/** true = credits given fresh every month, false = one-time lifetime grant (default). */
|
|
497
|
+
renewOnPeriod?: boolean;
|
|
498
|
+
};
|
|
499
|
+
isCurrent?: boolean;
|
|
500
|
+
isLegacy?: boolean;
|
|
501
|
+
archived?: boolean;
|
|
502
|
+
deleted?: boolean;
|
|
503
|
+
createdAt?: string;
|
|
504
|
+
updatedAt?: string;
|
|
505
|
+
id?: string;
|
|
506
|
+
stripeProductId?: string;
|
|
507
|
+
}
|
|
508
|
+
/** Plan version summary (e.g. plan.latestVersion from subscription API) with subscriptionItems as IDs. */
|
|
509
|
+
interface IPlanVersionSummary extends Omit<IPlanVersion, 'subscriptionItems'> {
|
|
510
|
+
subscriptionItems?: string[];
|
|
511
|
+
}
|
|
512
|
+
interface IPlan {
|
|
513
|
+
_id: string;
|
|
514
|
+
name: string;
|
|
515
|
+
slug: string;
|
|
516
|
+
description?: string;
|
|
517
|
+
/** Stripe currency code (e.g. 'usd', 'inr', 'eur'). Used for pricing display. */
|
|
518
|
+
currency?: string;
|
|
519
|
+
/** Freemium plan: $0 base pricing, no seat billing, no trial. */
|
|
520
|
+
isFreemium?: boolean;
|
|
521
|
+
latestVersion?: IPlanVersionSummary;
|
|
522
|
+
archived?: boolean;
|
|
523
|
+
deleted?: boolean;
|
|
524
|
+
createdAt?: string;
|
|
525
|
+
updatedAt?: string;
|
|
526
|
+
id?: string;
|
|
527
|
+
}
|
|
528
|
+
interface IPlanGroupLatestVersion {
|
|
529
|
+
_id: string;
|
|
530
|
+
version: number;
|
|
531
|
+
planVersionIds: string[];
|
|
532
|
+
requiredItems: string[];
|
|
533
|
+
status: 'draft' | 'published';
|
|
534
|
+
isCurrent?: boolean;
|
|
535
|
+
isLegacy?: boolean;
|
|
536
|
+
archived?: boolean;
|
|
537
|
+
deleted?: boolean;
|
|
538
|
+
createdAt?: string;
|
|
539
|
+
updatedAt?: string;
|
|
540
|
+
description?: string;
|
|
541
|
+
}
|
|
542
|
+
interface IPlanGroup {
|
|
543
|
+
_id: string;
|
|
544
|
+
name: string;
|
|
545
|
+
slug: string;
|
|
546
|
+
description?: string;
|
|
547
|
+
latestVersion?: IPlanGroupLatestVersion;
|
|
548
|
+
archived?: boolean;
|
|
549
|
+
deleted?: boolean;
|
|
550
|
+
createdAt?: string;
|
|
551
|
+
updatedAt?: string;
|
|
552
|
+
id?: string;
|
|
553
|
+
}
|
|
554
|
+
interface IPlanGroupVersion {
|
|
555
|
+
_id: string;
|
|
556
|
+
version: number;
|
|
557
|
+
description?: string;
|
|
558
|
+
group?: {
|
|
559
|
+
_id: string;
|
|
560
|
+
name: string;
|
|
561
|
+
description?: string;
|
|
562
|
+
};
|
|
563
|
+
planVersionIds: IPlanVersionWithPlan[] | string[];
|
|
564
|
+
requiredItems?: string[];
|
|
565
|
+
status?: 'draft' | 'published';
|
|
566
|
+
isCurrent?: boolean;
|
|
567
|
+
isLegacy?: boolean;
|
|
568
|
+
archived?: boolean;
|
|
569
|
+
deleted?: boolean;
|
|
570
|
+
createdAt?: string;
|
|
571
|
+
updatedAt?: string;
|
|
572
|
+
id?: string;
|
|
573
|
+
}
|
|
574
|
+
interface ISubscriptionResponse {
|
|
575
|
+
subscription: ISubscription | null;
|
|
576
|
+
planVersion: IPlanVersion | null;
|
|
577
|
+
plan: IPlan | null;
|
|
578
|
+
group: IPlanGroup | null;
|
|
579
|
+
groupVersion: IPlanGroupVersion | null;
|
|
580
|
+
}
|
|
581
|
+
/** Plan version with nested plan info (name, slug, currency for display). */
|
|
582
|
+
interface IPlanVersionWithPlan extends IPlanVersion {
|
|
583
|
+
plan: IPlan;
|
|
584
|
+
}
|
|
585
|
+
/**
|
|
586
|
+
* Plan group version with full plan versions (for GET .../plan-group/versions).
|
|
587
|
+
* Each plan has plan, subscriptionItems, quotas (per-interval), pricingVariants.
|
|
588
|
+
*/
|
|
589
|
+
interface IPlanGroupVersionWithPlans {
|
|
590
|
+
_id: string;
|
|
591
|
+
version: number;
|
|
592
|
+
description?: string;
|
|
593
|
+
/** Full plan versions with nested plan (name, slug, currency). */
|
|
594
|
+
plans: IPlanVersionWithPlan[];
|
|
595
|
+
isCurrent?: boolean;
|
|
596
|
+
whatsNew?: {
|
|
597
|
+
newPlans: IPlanVersionWithPlan[];
|
|
598
|
+
updatedPlans: IPlanVersionWithPlan[];
|
|
599
|
+
removedPlans: IPlanVersionWithPlan[];
|
|
600
|
+
};
|
|
601
|
+
}
|
|
602
|
+
interface IPlanGroupInfo {
|
|
603
|
+
_id: string;
|
|
604
|
+
name: string;
|
|
605
|
+
slug: string;
|
|
606
|
+
description?: string;
|
|
607
|
+
}
|
|
608
|
+
/** Response from GET workspaces/:id/subscription/plan-group (and by version). */
|
|
609
|
+
interface IPlanGroupResponse {
|
|
610
|
+
/** Plan group with latestVersion, archived, deleted, timestamps. May be null in some API responses. */
|
|
611
|
+
group: IPlanGroup | null;
|
|
612
|
+
/** Current group version with populated planVersionIds (or IDs). */
|
|
613
|
+
groupVersion: IPlanGroupVersion;
|
|
614
|
+
/** Full plan versions for display (subscriptionItems, pricingVariants, quotas). */
|
|
615
|
+
plans: IPlanVersionWithPlan[];
|
|
616
|
+
}
|
|
617
|
+
/**
|
|
618
|
+
* Response from GET workspaces/:workspaceId/subscription/plan-group/versions.
|
|
619
|
+
* Group summary plus current and available group versions; each version has plans with
|
|
620
|
+
* per-interval quotas and pricingVariants.
|
|
621
|
+
*/
|
|
622
|
+
interface IPlanGroupVersionsResponse {
|
|
623
|
+
/** Plan group summary (_id, name, slug). */
|
|
624
|
+
group: IPlanGroupInfo;
|
|
625
|
+
/** Current group version (user's version when subscribed, or latest published when not). */
|
|
626
|
+
currentVersion: IPlanGroupVersionWithPlans;
|
|
627
|
+
/** Newer versions when user has subscription; empty when no subscription. */
|
|
628
|
+
availableVersions: IPlanGroupVersionWithPlans[];
|
|
629
|
+
}
|
|
630
|
+
/**
|
|
631
|
+
* Optional Stripe-level overrides forwarded to the checkout session.
|
|
632
|
+
* Use this to pass affiliate/referral tracking data or other Stripe parameters
|
|
633
|
+
* that should be set on the checkout session or resulting subscription.
|
|
634
|
+
*/
|
|
635
|
+
interface ICheckoutStripeOptions {
|
|
636
|
+
/** Custom metadata merged into the Stripe checkout session metadata. */
|
|
637
|
+
metadata?: Record<string, string>;
|
|
638
|
+
/**
|
|
639
|
+
* Stripe `client_reference_id` — most affiliate platforms (Rewardful,
|
|
640
|
+
* FirstPromoter, PartnerStack, etc.) read this field to attribute conversions.
|
|
641
|
+
*/
|
|
642
|
+
clientReferenceId?: string;
|
|
643
|
+
/** Custom metadata merged into `subscription_data.metadata` on the Stripe session. */
|
|
644
|
+
subscriptionMetadata?: Record<string, string>;
|
|
645
|
+
}
|
|
646
|
+
/** Request body for POST .../workspaces/:id/subscription/checkout. */
|
|
647
|
+
interface ICheckoutSessionRequest {
|
|
648
|
+
planVersionId: string;
|
|
649
|
+
billingInterval?: BillingInterval;
|
|
650
|
+
currency?: string;
|
|
651
|
+
successUrl?: string;
|
|
652
|
+
cancelUrl?: string;
|
|
653
|
+
/** Stripe-level overrides for affiliate tracking, referral IDs, etc. */
|
|
654
|
+
stripeOptions?: ICheckoutStripeOptions;
|
|
655
|
+
}
|
|
656
|
+
interface ICheckoutSessionResponse {
|
|
657
|
+
/** Response type discriminator. Added for centralized checkout flow. */
|
|
658
|
+
type?: 'checkout' | 'trial_started' | 'existing';
|
|
659
|
+
success: boolean;
|
|
660
|
+
checkoutUrl: string;
|
|
661
|
+
sessionId: string;
|
|
662
|
+
message: string;
|
|
663
|
+
planVersion?: {
|
|
664
|
+
_id: string;
|
|
665
|
+
version: number;
|
|
666
|
+
name: string;
|
|
667
|
+
};
|
|
668
|
+
}
|
|
669
|
+
/** No-card trial started server-side; no redirect needed. */
|
|
670
|
+
interface ICheckoutTrialResult {
|
|
671
|
+
type: 'trial_started';
|
|
672
|
+
success: boolean;
|
|
673
|
+
checkoutUrl: null;
|
|
674
|
+
sessionId: null;
|
|
675
|
+
subscription: ISubscription;
|
|
676
|
+
message: string;
|
|
677
|
+
}
|
|
678
|
+
/** Workspace already has a matching active subscription. */
|
|
679
|
+
interface ICheckoutExistingResult {
|
|
680
|
+
type: 'existing';
|
|
681
|
+
success: boolean;
|
|
682
|
+
checkoutUrl: null;
|
|
683
|
+
sessionId: null;
|
|
684
|
+
message: string;
|
|
685
|
+
existingSubscription?: {
|
|
686
|
+
_id: string;
|
|
687
|
+
subscriptionStatus: string;
|
|
688
|
+
stripePriceId?: string;
|
|
689
|
+
};
|
|
690
|
+
}
|
|
691
|
+
/**
|
|
692
|
+
* Discriminated union for POST /subscription/checkout responses.
|
|
693
|
+
* - `checkout`: Stripe checkout session created, redirect user to checkoutUrl
|
|
694
|
+
* - `trial_started`: No-card trial started server-side, no redirect needed
|
|
695
|
+
* - `existing`: Workspace already has a matching subscription
|
|
696
|
+
*/
|
|
697
|
+
type CheckoutResult = (ICheckoutSessionResponse & {
|
|
698
|
+
type: 'checkout';
|
|
699
|
+
}) | ICheckoutTrialResult | ICheckoutExistingResult;
|
|
700
|
+
/** Request body for PATCH .../workspaces/:id/subscription. Only these fields are allowed. */
|
|
701
|
+
interface ISubscriptionUpdateRequest {
|
|
702
|
+
planVersionId: string;
|
|
703
|
+
billingInterval?: BillingInterval;
|
|
704
|
+
successUrl?: string;
|
|
705
|
+
cancelUrl?: string;
|
|
706
|
+
}
|
|
707
|
+
interface ISubscriptionUpdateResponse {
|
|
708
|
+
_id: string;
|
|
709
|
+
subscriptionStatus: string;
|
|
710
|
+
workspace: string;
|
|
711
|
+
planVersion: string;
|
|
712
|
+
plan: string;
|
|
713
|
+
planGroup?: string;
|
|
714
|
+
planGroupVersion?: string;
|
|
715
|
+
cancelAtPeriodEnd: boolean;
|
|
716
|
+
createdAt: string;
|
|
717
|
+
updatedAt: string;
|
|
718
|
+
}
|
|
719
|
+
interface IPublicPlanItemCategory {
|
|
720
|
+
name: string;
|
|
721
|
+
slug: string;
|
|
722
|
+
}
|
|
723
|
+
interface IPublicPlanItem {
|
|
724
|
+
_id: string;
|
|
725
|
+
name: string;
|
|
726
|
+
slug: string;
|
|
727
|
+
description?: string;
|
|
728
|
+
type: 'feature' | 'limit' | 'quota';
|
|
729
|
+
category: IPublicPlanItemCategory;
|
|
730
|
+
}
|
|
731
|
+
/**
|
|
732
|
+
* Public plan version (e.g. from GET /api/v1/public/:orgId/plans/:slug).
|
|
733
|
+
* Each plan has _id, name (plan display name), version, status, pricingVariants, quotas, features, limits.
|
|
734
|
+
* Pricing is in cents (see response.notes).
|
|
735
|
+
*/
|
|
736
|
+
interface IPublicPlanVersion {
|
|
737
|
+
_id: string;
|
|
738
|
+
/** Plan display name (e.g. "Pro", "Base Plan"). */
|
|
739
|
+
name: string;
|
|
740
|
+
/** Whether this is a free ($0) plan with no seat billing or trial. */
|
|
741
|
+
isFreemium: boolean;
|
|
742
|
+
version: number;
|
|
743
|
+
status: 'draft' | 'published';
|
|
744
|
+
/** Multi-currency pricing. Use getBasePriceCents(plan, currency, interval) and getQuotaDisplayWithVariant for display. */
|
|
745
|
+
pricingVariants?: IPricingVariant[];
|
|
746
|
+
/** Keyed by item slug. Per-interval: included, unitSize; overage from pricingVariant.quotaOverages. */
|
|
747
|
+
quotas: Record<string, IQuotaByInterval>;
|
|
748
|
+
features: Record<string, boolean>;
|
|
749
|
+
limits: Record<string, number>;
|
|
750
|
+
/** Trial config. Only present when the plan has trials enabled. */
|
|
751
|
+
trial?: {
|
|
752
|
+
enabled: boolean;
|
|
753
|
+
durationDays: number;
|
|
754
|
+
requireCard: boolean;
|
|
755
|
+
};
|
|
756
|
+
/** Credit grant config. Only present when the plan grants credits. */
|
|
757
|
+
creditGrant?: {
|
|
758
|
+
enabled: boolean;
|
|
759
|
+
creditAmount: number | null;
|
|
760
|
+
packageName: string | null;
|
|
761
|
+
mode: 'reset' | 'topup';
|
|
762
|
+
/** true = credits given fresh every month, false = one-time lifetime grant. */
|
|
763
|
+
renewOnPeriod: boolean;
|
|
764
|
+
};
|
|
765
|
+
}
|
|
766
|
+
interface IPublicPlansResponse {
|
|
767
|
+
items: IPublicPlanItem[];
|
|
768
|
+
plans: IPublicPlanVersion[];
|
|
769
|
+
/** Optional note from API (e.g. "Pricing is in cents. Please convert to dollars for display."). */
|
|
770
|
+
notes?: string;
|
|
771
|
+
}
|
|
772
|
+
type InvoiceStatus = 'draft' | 'open' | 'paid' | 'uncollectible' | 'void';
|
|
773
|
+
interface IInvoice {
|
|
774
|
+
id: string;
|
|
775
|
+
amount_due: number;
|
|
776
|
+
number: string | null;
|
|
777
|
+
amount_paid: number;
|
|
778
|
+
currency: string;
|
|
779
|
+
status: InvoiceStatus;
|
|
780
|
+
created: number;
|
|
781
|
+
due_date: number | null;
|
|
782
|
+
hosted_invoice_url: string;
|
|
783
|
+
invoice_pdf: string | null;
|
|
784
|
+
description: string | null;
|
|
785
|
+
subscription: string;
|
|
786
|
+
}
|
|
787
|
+
interface IInvoiceListResponse {
|
|
788
|
+
invoices: IInvoice[];
|
|
789
|
+
has_more: boolean;
|
|
790
|
+
}
|
|
791
|
+
interface IInvoiceResponse {
|
|
792
|
+
invoice: IInvoice;
|
|
793
|
+
}
|
|
794
|
+
/** Request body for POST .../workspaces/:id/subscription/usage */
|
|
795
|
+
interface IRecordUsageRequest {
|
|
796
|
+
quotaSlug: string;
|
|
797
|
+
quantity: number;
|
|
798
|
+
metadata?: Record<string, unknown>;
|
|
799
|
+
source?: string;
|
|
800
|
+
idempotencyKey?: string;
|
|
801
|
+
}
|
|
802
|
+
/** Response from POST .../workspaces/:id/subscription/usage */
|
|
803
|
+
interface IRecordUsageResponse {
|
|
804
|
+
used: number;
|
|
805
|
+
consumed: number;
|
|
806
|
+
included: number;
|
|
807
|
+
available: number;
|
|
808
|
+
overage: number;
|
|
809
|
+
billedAsync: boolean;
|
|
810
|
+
}
|
|
811
|
+
/** Single quota usage status (shared between status and all endpoints). */
|
|
812
|
+
interface IQuotaUsageStatus {
|
|
813
|
+
consumed: number;
|
|
814
|
+
included: number;
|
|
815
|
+
available: number;
|
|
816
|
+
overage: number;
|
|
817
|
+
hasOverage: boolean;
|
|
818
|
+
/** Whether over-usage is allowed (billed as overage). When false, usage is hard-capped. Default true. */
|
|
819
|
+
allowOverage?: boolean;
|
|
820
|
+
}
|
|
821
|
+
/** Response from GET .../workspaces/:id/subscription/usage/status?quotaSlug=X */
|
|
822
|
+
interface IQuotaUsageStatusResponse extends IQuotaUsageStatus {
|
|
823
|
+
quotaSlug: string;
|
|
824
|
+
}
|
|
825
|
+
/** Response from GET .../workspaces/:id/subscription/usage/all */
|
|
826
|
+
interface IAllQuotaUsageResponse {
|
|
827
|
+
quotas: Record<string, IQuotaUsageStatus>;
|
|
828
|
+
}
|
|
829
|
+
/** Single usage log entry from GET .../usage/logs */
|
|
830
|
+
interface IUsageLogEntry {
|
|
831
|
+
_id: string;
|
|
832
|
+
quotaSlug: string;
|
|
833
|
+
quantity: number;
|
|
834
|
+
source?: string;
|
|
835
|
+
workspace: string;
|
|
836
|
+
createdAt: string;
|
|
837
|
+
updatedAt: string;
|
|
838
|
+
}
|
|
839
|
+
/** Query parameters for GET .../workspaces/:id/subscription/usage/logs */
|
|
840
|
+
interface IUsageLogsQuery {
|
|
841
|
+
quotaSlug?: string;
|
|
842
|
+
from?: string;
|
|
843
|
+
to?: string;
|
|
844
|
+
source?: string;
|
|
845
|
+
page?: number;
|
|
846
|
+
limit?: number;
|
|
847
|
+
}
|
|
848
|
+
/** Paginated response from GET .../workspaces/:id/subscription/usage/logs */
|
|
849
|
+
interface IUsageLogsResponse {
|
|
850
|
+
docs: IUsageLogEntry[];
|
|
851
|
+
totalDocs: number;
|
|
852
|
+
limit: number;
|
|
853
|
+
page: number;
|
|
854
|
+
totalPages: number;
|
|
855
|
+
hasNextPage: boolean;
|
|
856
|
+
hasPrevPage: boolean;
|
|
857
|
+
}
|
|
858
|
+
/** Credit bucket source (how credits entered the workspace) */
|
|
859
|
+
declare const CreditBucketSource: {
|
|
860
|
+
readonly PlanGrant: "plan_grant";
|
|
861
|
+
readonly CreditPackPurchase: "credit_pack_purchase";
|
|
862
|
+
readonly AdminGrant: "admin_grant";
|
|
863
|
+
readonly Refund: "refund";
|
|
864
|
+
};
|
|
865
|
+
type CreditBucketSourceType = (typeof CreditBucketSource)[keyof typeof CreditBucketSource];
|
|
866
|
+
/** Credit bucket status */
|
|
867
|
+
declare const CreditBucketStatus: {
|
|
868
|
+
readonly Pending: "pending";
|
|
869
|
+
readonly Active: "active";
|
|
870
|
+
readonly Expired: "expired";
|
|
871
|
+
readonly Consumed: "consumed";
|
|
872
|
+
};
|
|
873
|
+
type CreditBucketStatusType = (typeof CreditBucketStatus)[keyof typeof CreditBucketStatus];
|
|
874
|
+
/** Credit transaction type */
|
|
875
|
+
declare const CreditTransactionType: {
|
|
876
|
+
readonly PlanGrant: "plan_grant";
|
|
877
|
+
readonly PackPurchased: "pack_purchased";
|
|
878
|
+
readonly Consumed: "consumed";
|
|
879
|
+
readonly Expired: "expired";
|
|
880
|
+
readonly AdminGrant: "admin_grant";
|
|
881
|
+
readonly AdminRevoke: "admin_revoke";
|
|
882
|
+
readonly Refund: "refund";
|
|
883
|
+
};
|
|
884
|
+
type CreditTransactionTypeValue = (typeof CreditTransactionType)[keyof typeof CreditTransactionType];
|
|
885
|
+
/** Credit balance for a workspace */
|
|
886
|
+
interface ICreditBalance {
|
|
887
|
+
available: number;
|
|
888
|
+
totalGranted: number;
|
|
889
|
+
totalConsumed: number;
|
|
890
|
+
totalExpired: number;
|
|
891
|
+
totalRefunded: number;
|
|
892
|
+
}
|
|
893
|
+
/** Pricing variant for a credit package */
|
|
894
|
+
interface ICreditPackagePricingVariant {
|
|
895
|
+
currency: string;
|
|
896
|
+
/** Price in smallest currency unit (cents) */
|
|
897
|
+
amount: number;
|
|
898
|
+
stripePriceId?: string;
|
|
899
|
+
}
|
|
900
|
+
/** Admin-defined purchasable credit package */
|
|
901
|
+
interface ICreditPackage extends IDocument {
|
|
902
|
+
name: string;
|
|
903
|
+
slug: string;
|
|
904
|
+
description?: string;
|
|
905
|
+
creditAmount: number;
|
|
906
|
+
pricingVariants: ICreditPackagePricingVariant[];
|
|
907
|
+
validityDays?: number;
|
|
908
|
+
isActive: boolean;
|
|
909
|
+
sortOrder: number;
|
|
910
|
+
archived: boolean;
|
|
911
|
+
}
|
|
912
|
+
/** A single credit transaction (user-facing event history) */
|
|
913
|
+
interface ICreditTransaction extends IDocument {
|
|
914
|
+
workspace: string;
|
|
915
|
+
type: CreditTransactionTypeValue;
|
|
916
|
+
/** Positive for grants, negative for consume/expire/revoke */
|
|
917
|
+
amount: number;
|
|
918
|
+
balanceAfter: number;
|
|
919
|
+
description?: string;
|
|
920
|
+
bucket?: string;
|
|
921
|
+
creditPackage?: string;
|
|
922
|
+
actor?: string;
|
|
923
|
+
metadata?: Record<string, any>;
|
|
924
|
+
}
|
|
925
|
+
/** A credit bucket (per-grant allocation with expiry) */
|
|
926
|
+
interface ICreditBucket extends IDocument {
|
|
927
|
+
workspace: string;
|
|
928
|
+
source: CreditBucketSourceType;
|
|
929
|
+
status: CreditBucketStatusType;
|
|
930
|
+
creditAmount: number;
|
|
931
|
+
remaining: number;
|
|
932
|
+
expiresAt?: string;
|
|
933
|
+
activatedAt?: string;
|
|
934
|
+
creditPackage?: string | ICreditPackage;
|
|
935
|
+
grantedBy?: string;
|
|
936
|
+
metadata?: Record<string, any>;
|
|
937
|
+
}
|
|
938
|
+
/** Request body for POST .../credits/consume */
|
|
939
|
+
interface IConsumeCreditsRequest {
|
|
940
|
+
amount: number;
|
|
941
|
+
description?: string;
|
|
942
|
+
idempotencyKey?: string;
|
|
943
|
+
metadata?: Record<string, any>;
|
|
944
|
+
}
|
|
945
|
+
/** Response from POST .../credits/consume */
|
|
946
|
+
interface IConsumeCreditsResponse {
|
|
947
|
+
success: boolean;
|
|
948
|
+
consumed: number;
|
|
949
|
+
balanceAfter: number;
|
|
950
|
+
}
|
|
951
|
+
/** Request body for POST .../credits/purchase */
|
|
952
|
+
interface ICreditPurchaseRequest {
|
|
953
|
+
creditPackageId: string;
|
|
954
|
+
currency?: string;
|
|
955
|
+
successUrl: string;
|
|
956
|
+
cancelUrl: string;
|
|
957
|
+
}
|
|
958
|
+
/** Response from POST .../credits/purchase */
|
|
959
|
+
interface ICreditPurchaseResponse {
|
|
960
|
+
sessionId: string;
|
|
961
|
+
url: string;
|
|
962
|
+
}
|
|
963
|
+
/** Query params for GET .../credits/transactions */
|
|
964
|
+
interface ICreditTransactionsQuery {
|
|
965
|
+
type?: CreditTransactionTypeValue;
|
|
966
|
+
page?: number;
|
|
967
|
+
limit?: number;
|
|
968
|
+
}
|
|
969
|
+
/** Paginated response from GET .../credits/transactions */
|
|
970
|
+
interface ICreditTransactionsResponse {
|
|
971
|
+
docs: ICreditTransaction[];
|
|
972
|
+
totalDocs: number;
|
|
973
|
+
limit: number;
|
|
974
|
+
page: number;
|
|
975
|
+
totalPages: number;
|
|
976
|
+
hasNextPage: boolean;
|
|
977
|
+
hasPrevPage: boolean;
|
|
978
|
+
}
|
|
979
|
+
/** Query params for GET .../credits/buckets */
|
|
980
|
+
interface ICreditBucketsQuery {
|
|
981
|
+
status?: CreditBucketStatusType;
|
|
982
|
+
source?: CreditBucketSourceType;
|
|
983
|
+
page?: number;
|
|
984
|
+
limit?: number;
|
|
985
|
+
}
|
|
986
|
+
/** Paginated response from GET .../credits/buckets */
|
|
987
|
+
interface ICreditBucketsResponse {
|
|
988
|
+
docs: ICreditBucket[];
|
|
989
|
+
totalDocs: number;
|
|
990
|
+
limit: number;
|
|
991
|
+
page: number;
|
|
992
|
+
totalPages: number;
|
|
993
|
+
hasNextPage: boolean;
|
|
994
|
+
hasPrevPage: boolean;
|
|
995
|
+
}
|
|
996
|
+
/** Response from GET .../credits/expiring */
|
|
997
|
+
interface IExpiringCreditsResponse {
|
|
998
|
+
days: number;
|
|
999
|
+
expiringCredits: number;
|
|
1000
|
+
buckets: ICreditBucket[];
|
|
1001
|
+
}
|
|
1002
|
+
/** Public credit package (from public endpoint, no auth) */
|
|
1003
|
+
interface IPublicCreditPackage {
|
|
1004
|
+
_id: string;
|
|
1005
|
+
name: string;
|
|
1006
|
+
slug: string;
|
|
1007
|
+
description: string;
|
|
1008
|
+
creditAmount: number;
|
|
1009
|
+
pricingVariants: ICreditPackagePricingVariant[];
|
|
1010
|
+
validityDays: number | null;
|
|
1011
|
+
sortOrder: number;
|
|
1012
|
+
}
|
|
1013
|
+
/** Response from GET /:orgId/credit-packages (public, no auth) */
|
|
1014
|
+
interface IPublicCreditPackagesResponse {
|
|
1015
|
+
packages: IPublicCreditPackage[];
|
|
1016
|
+
notes?: string;
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
interface IWorkspace {
|
|
1020
|
+
_id: string;
|
|
1021
|
+
name: string;
|
|
1022
|
+
image?: string;
|
|
1023
|
+
workspaceId: string;
|
|
1024
|
+
users: IUser[];
|
|
1025
|
+
roles: string[];
|
|
1026
|
+
createdBy: string | IUser;
|
|
1027
|
+
features: Record<string, boolean>;
|
|
1028
|
+
/**
|
|
1029
|
+
* Quota usage tracking: { [quotaSlug]: number } – how much of each quota has been used.
|
|
1030
|
+
*/
|
|
1031
|
+
quotas?: Record<string, number>;
|
|
1032
|
+
/**
|
|
1033
|
+
* Subscription limits snapshot: { [limitSlug]: number | null } – synced from subscription plan.
|
|
1034
|
+
* Limits are maximum values (e.g. max-users, max-workspaces). Updated when subscription is assigned/updated.
|
|
1035
|
+
*/
|
|
1036
|
+
limits?: Record<string, number | null>;
|
|
1037
|
+
subscription?: ISubscription | string | null;
|
|
1038
|
+
/** Stripe Customer ID for this workspace. */
|
|
1039
|
+
stripeCustomerId?: string;
|
|
1040
|
+
/**
|
|
1041
|
+
* Billing currency locked for this workspace (set on first subscription).
|
|
1042
|
+
* Stripe allows one currency per customer; all future subscriptions must use this currency.
|
|
1043
|
+
* When set, subscription UI only shows/uses this currency.
|
|
1044
|
+
*/
|
|
1045
|
+
billingCurrency?: string | null;
|
|
1046
|
+
/** Per-workspace permission overrides. Takes priority over org-level settings.permissions. */
|
|
1047
|
+
permissions?: Record<string, string[]>;
|
|
1048
|
+
/** Set when workspace first uses a trial. Blocks trial from being used again on the same workspace. */
|
|
1049
|
+
trialUsedAt?: string | null;
|
|
1050
|
+
}
|
|
1051
|
+
interface IWorkspaceFeature {
|
|
1052
|
+
_id: string;
|
|
1053
|
+
name: string;
|
|
1054
|
+
description: string;
|
|
1055
|
+
userManaged: boolean;
|
|
1056
|
+
defaultValue: boolean;
|
|
1057
|
+
slug: string;
|
|
1058
|
+
category: string;
|
|
1059
|
+
createdAt: Date;
|
|
1060
|
+
updatedAt: Date;
|
|
1061
|
+
}
|
|
1062
|
+
interface IWorkspaceUser {
|
|
1063
|
+
_id: string;
|
|
1064
|
+
workspace: string | IWorkspace;
|
|
1065
|
+
user: string | IUser;
|
|
1066
|
+
role: string;
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
type WorkspaceMode = 'personal' | 'platform';
|
|
1070
|
+
interface ISettings {
|
|
1071
|
+
workspace: {
|
|
1072
|
+
roles: string[];
|
|
1073
|
+
defaultRole: string;
|
|
1074
|
+
maxWorkspaces: number;
|
|
1075
|
+
maxWorkspaceUsers: number;
|
|
1076
|
+
/** Workspace mode: 'personal' (solo) or 'platform' (multi-user, default) */
|
|
1077
|
+
mode: WorkspaceMode;
|
|
1078
|
+
/** Whether users can create workspaces. false = disabled, 'owner-only' = restricted */
|
|
1079
|
+
canCreateWorkspace: boolean | 'owner-only';
|
|
1080
|
+
/** Whether members can invite others. false = disabled, 'admin-only' = restricted */
|
|
1081
|
+
canInviteMembers: boolean | 'admin-only';
|
|
1082
|
+
/** Custom role→permission mapping. Overrides SDK defaults when provided by backend. */
|
|
1083
|
+
permissions?: Record<string, string[]>;
|
|
1084
|
+
/** Show workspace switcher in the UI */
|
|
1085
|
+
showSwitcher: boolean;
|
|
1086
|
+
/** Max workspaces a user can own. 0 = unlimited */
|
|
1087
|
+
maxWorkspacesPerUser: number;
|
|
1088
|
+
/** Auto-create workspace on first login */
|
|
1089
|
+
autoCreateFirst: boolean;
|
|
1090
|
+
};
|
|
1091
|
+
[key: string]: any;
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
/** Data passed to a notification template for merge tag replacement. */
|
|
1095
|
+
interface NotificationData {
|
|
1096
|
+
/** Push notification title. Falls back to the event name if not provided. */
|
|
1097
|
+
title?: string;
|
|
1098
|
+
/** Primary message — used in email body and as push notification body. */
|
|
1099
|
+
message?: string;
|
|
1100
|
+
/** Custom icon URL for the push notification. Falls back to the org icon. */
|
|
1101
|
+
icon?: string;
|
|
1102
|
+
/** Large image URL displayed in the push notification body. */
|
|
1103
|
+
image?: string;
|
|
1104
|
+
/** Small monochrome icon for the status bar (Android/ChromeOS). */
|
|
1105
|
+
badge?: string;
|
|
1106
|
+
/** URL to open when the user clicks the push notification. Also available as {{url}} in email template. */
|
|
1107
|
+
url?: string;
|
|
1108
|
+
/** Tag to group/replace notifications. New notification with same tag replaces the previous one instead of stacking. */
|
|
1109
|
+
tag?: string;
|
|
1110
|
+
/** Action buttons displayed on the notification (max 2). */
|
|
1111
|
+
actions?: Array<{
|
|
1112
|
+
action: string;
|
|
1113
|
+
title: string;
|
|
1114
|
+
icon?: string;
|
|
1115
|
+
}>;
|
|
1116
|
+
/** Show notification without sound or vibration. */
|
|
1117
|
+
silent?: boolean;
|
|
1118
|
+
/** Keep notification visible until user interacts (no auto-dismiss). Useful for critical alerts. */
|
|
1119
|
+
requireInteraction?: boolean;
|
|
1120
|
+
/** Vibrate/sound again when replacing a notification with the same tag. Only works with `tag`. */
|
|
1121
|
+
renotify?: boolean;
|
|
1122
|
+
/** Custom timestamp (ms since epoch) displayed on the notification. */
|
|
1123
|
+
timestamp?: number;
|
|
1124
|
+
/** Text direction for title/body. */
|
|
1125
|
+
dir?: 'ltr' | 'rtl' | 'auto';
|
|
1126
|
+
/** Time-to-live in seconds. Push service discards the message if not delivered within this time. Default: 86400 (24h). */
|
|
1127
|
+
ttl?: number;
|
|
1128
|
+
/** Delivery urgency hint. Affects battery/delivery priority on mobile. */
|
|
1129
|
+
urgency?: 'very-low' | 'low' | 'normal' | 'high';
|
|
1130
|
+
/** ISO 8601 date string. Delays delivery until the specified time. */
|
|
1131
|
+
scheduledAt?: string;
|
|
1132
|
+
/**
|
|
1133
|
+
* Which channels to send on. Overrides the event's default channel config.
|
|
1134
|
+
* Omit to use the event's configured channels.
|
|
1135
|
+
*
|
|
1136
|
+
* @example
|
|
1137
|
+
* ```ts
|
|
1138
|
+
* // Only push, no email
|
|
1139
|
+
* { channels: { push: true } }
|
|
1140
|
+
*
|
|
1141
|
+
* // Only email, no push
|
|
1142
|
+
* { channels: { email: true } }
|
|
1143
|
+
* ```
|
|
1144
|
+
*/
|
|
1145
|
+
channels?: {
|
|
1146
|
+
email?: boolean;
|
|
1147
|
+
push?: boolean;
|
|
1148
|
+
};
|
|
1149
|
+
/** Any additional merge tags available as {{key}} in the email template. */
|
|
1150
|
+
[key: string]: any;
|
|
1151
|
+
}
|
|
1152
|
+
/** Result of sending a notification. */
|
|
1153
|
+
interface NotificationResult {
|
|
1154
|
+
sent: boolean;
|
|
1155
|
+
/** Which channels were actually used. false = blocked by settings or missing template. */
|
|
1156
|
+
channels: {
|
|
1157
|
+
email: boolean;
|
|
1158
|
+
push: boolean;
|
|
1159
|
+
};
|
|
1160
|
+
/** Number of users notified. 1 for single user, N for whole workspace. */
|
|
1161
|
+
notifiedCount?: number;
|
|
1162
|
+
/** Reason if not sent (e.g., 'event_disabled'). Only present when sent=false. */
|
|
1163
|
+
reason?: string;
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
interface WorkspaceActions {
|
|
1167
|
+
list(): Promise<IWorkspace[]>;
|
|
1168
|
+
get(workspaceId: string): Promise<IWorkspace>;
|
|
1169
|
+
create(data: {
|
|
1170
|
+
name: string;
|
|
1171
|
+
image?: string;
|
|
1172
|
+
}): Promise<IWorkspace>;
|
|
1173
|
+
update(workspaceId: string, data: Partial<IWorkspace>): Promise<IWorkspace>;
|
|
1174
|
+
delete(workspaceId: string): Promise<{
|
|
1175
|
+
success: boolean;
|
|
1176
|
+
}>;
|
|
1177
|
+
}
|
|
1178
|
+
interface UserActions {
|
|
1179
|
+
list(workspaceId: string): Promise<IWorkspaceUser[]>;
|
|
1180
|
+
invite(workspaceId: string, email: string, role: string): Promise<{
|
|
1181
|
+
userId: string;
|
|
1182
|
+
workspace: IWorkspace;
|
|
1183
|
+
message: string;
|
|
1184
|
+
}>;
|
|
1185
|
+
remove(workspaceId: string, userId: string): Promise<{
|
|
1186
|
+
userId: string;
|
|
1187
|
+
workspace: IWorkspace;
|
|
1188
|
+
message: string;
|
|
1189
|
+
}>;
|
|
1190
|
+
updateRole(workspaceId: string, userId: string, role: string): Promise<{
|
|
1191
|
+
userId: string;
|
|
1192
|
+
workspace: IWorkspace;
|
|
1193
|
+
message: string;
|
|
1194
|
+
}>;
|
|
1195
|
+
getProfile(): Promise<IUser>;
|
|
1196
|
+
updateProfile(data: Partial<IUser>): Promise<IUser>;
|
|
1197
|
+
}
|
|
1198
|
+
interface SubscriptionActions {
|
|
1199
|
+
get(workspaceId: string): Promise<ISubscriptionResponse>;
|
|
1200
|
+
checkout(workspaceId: string, request: ICheckoutSessionRequest): Promise<CheckoutResult | ICheckoutSessionResponse>;
|
|
1201
|
+
update(workspaceId: string, request: ISubscriptionUpdateRequest): Promise<ISubscriptionUpdateResponse | ICheckoutSessionResponse>;
|
|
1202
|
+
cancel(workspaceId: string): Promise<ISubscriptionResponse>;
|
|
1203
|
+
resume(workspaceId: string): Promise<ISubscriptionResponse>;
|
|
1204
|
+
getBillingPortalUrl(workspaceId: string, returnUrl?: string): Promise<{
|
|
1205
|
+
url: string;
|
|
1206
|
+
}>;
|
|
1207
|
+
}
|
|
1208
|
+
interface PlanActions {
|
|
1209
|
+
getGroup(workspaceId: string): Promise<IPlanGroupResponse>;
|
|
1210
|
+
getVersions(workspaceId: string): Promise<IPlanGroupVersionsResponse>;
|
|
1211
|
+
/** No auth required */
|
|
1212
|
+
getPublic(slug: string): Promise<IPublicPlansResponse>;
|
|
1213
|
+
/** No auth required */
|
|
1214
|
+
getVersion(groupVersionId: string): Promise<IPlanGroupVersion>;
|
|
1215
|
+
}
|
|
1216
|
+
interface InvoiceActions {
|
|
1217
|
+
list(workspaceId: string, limit?: number, startingAfter?: string): Promise<IInvoiceListResponse>;
|
|
1218
|
+
get(workspaceId: string, invoiceId: string): Promise<IInvoiceResponse>;
|
|
1219
|
+
}
|
|
1220
|
+
interface UsageBatchRequest {
|
|
1221
|
+
items: Array<{
|
|
1222
|
+
quotaSlug: string;
|
|
1223
|
+
quantity: number;
|
|
1224
|
+
metadata?: Record<string, any>;
|
|
1225
|
+
source?: string;
|
|
1226
|
+
idempotencyKey?: string;
|
|
1227
|
+
}>;
|
|
1228
|
+
}
|
|
1229
|
+
interface UsageBatchResponse {
|
|
1230
|
+
success: boolean;
|
|
1231
|
+
total: number;
|
|
1232
|
+
succeeded: number;
|
|
1233
|
+
failed: number;
|
|
1234
|
+
results: Array<{
|
|
1235
|
+
success: boolean;
|
|
1236
|
+
quotaSlug: string;
|
|
1237
|
+
quantity: number;
|
|
1238
|
+
error?: string;
|
|
1239
|
+
}>;
|
|
1240
|
+
}
|
|
1241
|
+
interface UsageActions {
|
|
1242
|
+
record(workspaceId: string, request: IRecordUsageRequest): Promise<IRecordUsageResponse>;
|
|
1243
|
+
/** Record multiple usage entries in one request. Max 100 items. For bulk/batch operations. */
|
|
1244
|
+
recordBatch(workspaceId: string, request: UsageBatchRequest): Promise<UsageBatchResponse>;
|
|
1245
|
+
getQuota(workspaceId: string, quotaSlug: string): Promise<IQuotaUsageStatusResponse>;
|
|
1246
|
+
getAll(workspaceId: string): Promise<IAllQuotaUsageResponse>;
|
|
1247
|
+
getLogs(workspaceId: string, query?: IUsageLogsQuery): Promise<IUsageLogsResponse>;
|
|
1248
|
+
}
|
|
1249
|
+
interface SettingsActions {
|
|
1250
|
+
get(): Promise<ISettings>;
|
|
1251
|
+
}
|
|
1252
|
+
interface FeatureActions {
|
|
1253
|
+
list(): Promise<IWorkspaceFeature[]>;
|
|
1254
|
+
update(workspaceId: string, key: string, value: boolean): Promise<IWorkspace>;
|
|
1255
|
+
}
|
|
1256
|
+
interface PermissionActions {
|
|
1257
|
+
/** Check if a user has a permission (or all of an array) in a workspace. Works with both platform permissions (Permission.*) and app permissions (custom strings). */
|
|
1258
|
+
check(workspaceId: string, userId: string, permission: string | string[]): Promise<boolean>;
|
|
1259
|
+
/** Resolve all permissions for a user in a workspace. Returns both platform and app permissions. */
|
|
1260
|
+
resolve(workspaceId: string, userId: string): Promise<Set<string>>;
|
|
1261
|
+
}
|
|
1262
|
+
interface NotificationActions {
|
|
1263
|
+
/**
|
|
1264
|
+
* Send a notification to a user or all workspace members.
|
|
1265
|
+
* Respects all notification gates (org settings, event config, workspace preferences).
|
|
1266
|
+
*
|
|
1267
|
+
* @param workspaceId - The workspace context
|
|
1268
|
+
* @param event - The event slug (e.g., 'comment_added')
|
|
1269
|
+
* @param userId - The user to notify. Omit to notify all workspace members.
|
|
1270
|
+
* @param data - Template merge data. `message` is used as push body.
|
|
1271
|
+
*
|
|
1272
|
+
* @example
|
|
1273
|
+
* ```ts
|
|
1274
|
+
* // Notify one user
|
|
1275
|
+
* await notification.send(workspaceId, 'comment_added', userId, {
|
|
1276
|
+
* message: 'Alice commented on your project',
|
|
1277
|
+
* })
|
|
1278
|
+
*
|
|
1279
|
+
* // Notify all workspace members
|
|
1280
|
+
* await notification.send(workspaceId, 'new_release', undefined, {
|
|
1281
|
+
* message: 'Version 2.0 is now available!',
|
|
1282
|
+
* })
|
|
1283
|
+
* ```
|
|
1284
|
+
*/
|
|
1285
|
+
send(workspaceId: string, event: string, userId?: string, data?: NotificationData): Promise<NotificationResult>;
|
|
1286
|
+
}
|
|
1287
|
+
interface CreditActions {
|
|
1288
|
+
/** Get workspace credit balance */
|
|
1289
|
+
getBalance(workspaceId: string): Promise<ICreditBalance>;
|
|
1290
|
+
/** Consume credits from workspace. Throws with code 'INSUFFICIENT_CREDITS' on 402. */
|
|
1291
|
+
consume(workspaceId: string, request: IConsumeCreditsRequest): Promise<IConsumeCreditsResponse>;
|
|
1292
|
+
/** Create Stripe checkout session for purchasing a credit package */
|
|
1293
|
+
purchase(workspaceId: string, request: ICreditPurchaseRequest): Promise<ICreditPurchaseResponse>;
|
|
1294
|
+
/** List available credit packages for purchase */
|
|
1295
|
+
getPackages(workspaceId: string): Promise<ICreditPackage[]>;
|
|
1296
|
+
/** Get paginated credit transaction history */
|
|
1297
|
+
getTransactions(workspaceId: string, query?: ICreditTransactionsQuery): Promise<ICreditTransactionsResponse>;
|
|
1298
|
+
/** Get paginated credit buckets */
|
|
1299
|
+
getBuckets(workspaceId: string, query?: ICreditBucketsQuery): Promise<ICreditBucketsResponse>;
|
|
1300
|
+
/** Get credits expiring within N days (default 7) */
|
|
1301
|
+
getExpiring(workspaceId: string, days?: number): Promise<IExpiringCreditsResponse>;
|
|
1302
|
+
/** Get credit packages publicly (no auth required) */
|
|
1303
|
+
getPublicPackages(): Promise<IPublicCreditPackagesResponse>;
|
|
1304
|
+
}
|
|
1305
|
+
/** All action modules bound to a specific session. Returned by `withSession()`. */
|
|
1306
|
+
interface ScopedActions {
|
|
1307
|
+
workspace: WorkspaceActions;
|
|
1308
|
+
users: UserActions;
|
|
1309
|
+
subscription: SubscriptionActions;
|
|
1310
|
+
plans: PlanActions;
|
|
1311
|
+
invoices: InvoiceActions;
|
|
1312
|
+
usage: UsageActions;
|
|
1313
|
+
settings: SettingsActions;
|
|
1314
|
+
features: FeatureActions;
|
|
1315
|
+
permissions: PermissionActions;
|
|
1316
|
+
notification: NotificationActions;
|
|
1317
|
+
credits: CreditActions;
|
|
1318
|
+
}
|
|
1319
|
+
|
|
1320
|
+
/**
|
|
1321
|
+
* MCP server toolkit (server-side, framework-agnostic).
|
|
1322
|
+
*
|
|
1323
|
+
* Turns a consuming app into a live MCP (Model Context Protocol) server so AI
|
|
1324
|
+
* agents can operate its BuildBase capabilities — workspaces, subscriptions,
|
|
1325
|
+
* quotas, credits, feature flags, permissions — plus any custom tools the app
|
|
1326
|
+
* defines. The transport is stateless Streamable HTTP: a single JSON-RPC
|
|
1327
|
+
* message per POST, no sessions and no SSE, which keeps the handler pure and
|
|
1328
|
+
* identical on Node 18+, edge, Deno, and Bun.
|
|
1329
|
+
*
|
|
1330
|
+
* Zero framework types: the core `handle()` takes a plain
|
|
1331
|
+
* `{ method, headers, body }` and returns `{ status, headers, body }` (wire it
|
|
1332
|
+
* into Express/Fastify/Hono yourself), while `fetch()` adapts Web-standard
|
|
1333
|
+
* `Request` → `Response` for Next.js App Router and edge runtimes.
|
|
1334
|
+
*
|
|
1335
|
+
* Agents authenticate with the Bearer tokens the app mints via the OAuth2
|
|
1336
|
+
* app-bridge (`handleAppTokenRequest` + `signClientJwt`); the `auth.verify`
|
|
1337
|
+
* callback maps a verified token to the BuildBase session the tools run under.
|
|
1338
|
+
*
|
|
1339
|
+
* @example Next.js App Router — the entire integration:
|
|
1340
|
+
* ```ts
|
|
1341
|
+
* // lib/mcp.ts
|
|
1342
|
+
* import BuildBase from '@buildbase/sdk';
|
|
1343
|
+
* import { createMcpHandler, verifyClientJwt } from '@buildbase/sdk/mcp';
|
|
1344
|
+
*
|
|
1345
|
+
* const buildbase = BuildBase({
|
|
1346
|
+
* serverUrl: process.env.BUILDBASE_URL!,
|
|
1347
|
+
* orgId: process.env.BUILDBASE_ORG_ID!,
|
|
1348
|
+
* });
|
|
1349
|
+
*
|
|
1350
|
+
* export const mcp = createMcpHandler({
|
|
1351
|
+
* buildbase,
|
|
1352
|
+
* serverInfo: { name: 'imejis', version: '1.0.0' },
|
|
1353
|
+
* auth: {
|
|
1354
|
+
* verify: (token) => {
|
|
1355
|
+
* const c = verifyClientJwt(token, process.env.BUILDBASE_CLIENT_SECRET!);
|
|
1356
|
+
* return { sessionId: String(c.sid), userId: String(c.sub), scopes: c.scope };
|
|
1357
|
+
* },
|
|
1358
|
+
* resourceMetadataUrl: 'https://imejis.io/.well-known/oauth-protected-resource',
|
|
1359
|
+
* },
|
|
1360
|
+
* });
|
|
1361
|
+
*
|
|
1362
|
+
* // app/api/mcp/route.ts
|
|
1363
|
+
* import { mcp } from '@/lib/mcp';
|
|
1364
|
+
* export const POST = (req: Request) => mcp.fetch(req);
|
|
1365
|
+
* export const GET = (req: Request) => mcp.fetch(req); // 405 per spec (no SSE)
|
|
1366
|
+
* export const DELETE = (req: Request) => mcp.fetch(req); // 405 (stateless)
|
|
1367
|
+
* ```
|
|
1368
|
+
*/
|
|
1369
|
+
|
|
1370
|
+
/**
|
|
1371
|
+
* The slice of the `BuildBase()` client the MCP handler needs. Structural on
|
|
1372
|
+
* purpose (instead of the full `BuildBaseResult`) so the type stays assignable
|
|
1373
|
+
* across the SDK's separately-bundled entry points.
|
|
1374
|
+
*/
|
|
1375
|
+
interface McpBuildBaseClient {
|
|
1376
|
+
withSession(sessionId: string): ScopedActions;
|
|
1377
|
+
}
|
|
1378
|
+
/** A transport-agnostic HTTP request (mirror of the DiscoveryDocument idea). */
|
|
1379
|
+
interface McpHttpRequest {
|
|
1380
|
+
/** HTTP method, e.g. `'POST'`. */
|
|
1381
|
+
method: string;
|
|
1382
|
+
/** Header map. Keys are matched case-insensitively. */
|
|
1383
|
+
headers: Record<string, string | undefined>;
|
|
1384
|
+
/** Raw JSON body string, or an already-parsed value (e.g. Express req.body). */
|
|
1385
|
+
body?: string | unknown;
|
|
1386
|
+
}
|
|
1387
|
+
/** A rendered HTTP response ready to hand to any framework. */
|
|
1388
|
+
interface McpHttpResponse {
|
|
1389
|
+
status: number;
|
|
1390
|
+
headers: Record<string, string>;
|
|
1391
|
+
body: string;
|
|
1392
|
+
}
|
|
1393
|
+
/** The identity a verified Bearer token resolves to. */
|
|
1394
|
+
interface McpAuthInfo {
|
|
1395
|
+
/** BuildBase session all tool calls run under (`buildbase.withSession(...)`). */
|
|
1396
|
+
sessionId: string;
|
|
1397
|
+
/** The acting BuildBase user id — default subject for permission checks. */
|
|
1398
|
+
userId?: string;
|
|
1399
|
+
/** Pin tools to one workspace; used when the agent omits `workspaceId`. */
|
|
1400
|
+
workspaceId?: string;
|
|
1401
|
+
/** OAuth scopes granted to the agent; filters tools with `requiredScopes`. */
|
|
1402
|
+
scopes?: string[];
|
|
1403
|
+
/** Raw verified claims, passed through to tool context. */
|
|
1404
|
+
claims?: Record<string, unknown>;
|
|
1405
|
+
}
|
|
1406
|
+
/** Context passed to every tool execution. */
|
|
1407
|
+
interface McpToolContext<TCustom = unknown> {
|
|
1408
|
+
/**
|
|
1409
|
+
* Session-scoped BuildBase actions (`workspace`, `usage`, `credits`, …).
|
|
1410
|
+
* Only usable when a `buildbase` client was configured — otherwise any
|
|
1411
|
+
* access throws a clear error (tools that don't touch BuildBase never
|
|
1412
|
+
* notice).
|
|
1413
|
+
*/
|
|
1414
|
+
bb: ScopedActions;
|
|
1415
|
+
auth: McpAuthInfo;
|
|
1416
|
+
/** Default workspace (from `auth.workspaceId`), if any. */
|
|
1417
|
+
workspaceId?: string;
|
|
1418
|
+
/**
|
|
1419
|
+
* Whatever your `context` factory returned for this request — your own
|
|
1420
|
+
* database handles, services, request info. `undefined` when no factory is
|
|
1421
|
+
* configured.
|
|
1422
|
+
*/
|
|
1423
|
+
custom: TCustom;
|
|
1424
|
+
}
|
|
1425
|
+
/** MCP tool annotations (behavior hints for agents). */
|
|
1426
|
+
interface McpToolAnnotations {
|
|
1427
|
+
title?: string;
|
|
1428
|
+
readOnlyHint?: boolean;
|
|
1429
|
+
destructiveHint?: boolean;
|
|
1430
|
+
idempotentHint?: boolean;
|
|
1431
|
+
openWorldHint?: boolean;
|
|
1432
|
+
}
|
|
1433
|
+
/** A tool exposed over MCP. Use {@link defineMcpTool} for inferred input types. */
|
|
1434
|
+
interface McpToolDefinition<S extends z.ZodType = z.ZodType, TCustom = any> {
|
|
1435
|
+
/** Tool name: `[a-zA-Z0-9_-]`, 1–128 chars. */
|
|
1436
|
+
name: string;
|
|
1437
|
+
description: string;
|
|
1438
|
+
/**
|
|
1439
|
+
* Input schema: a zod schema (validated, converted to JSON Schema for
|
|
1440
|
+
* `tools/list`) or a raw JSON Schema object (served as-is, not validated).
|
|
1441
|
+
*/
|
|
1442
|
+
inputSchema: S | Record<string, unknown>;
|
|
1443
|
+
annotations?: McpToolAnnotations;
|
|
1444
|
+
/**
|
|
1445
|
+
* Scopes required to see/call this tool. The token must carry ALL of them
|
|
1446
|
+
* (`McpAuthInfo.scopes`) for the tool to be visible or callable; a token
|
|
1447
|
+
* with no scopes sees only tools that declare none. Built-in tools declare
|
|
1448
|
+
* no scopes and are governed by `builtinTools` + the user's own permissions.
|
|
1449
|
+
*/
|
|
1450
|
+
requiredScopes?: string[];
|
|
1451
|
+
execute: (input: z.output<S>, ctx: McpToolContext<TCustom>) => unknown | Promise<unknown>;
|
|
1452
|
+
}
|
|
1453
|
+
/** Configuration for {@link createMcpHandler}. */
|
|
1454
|
+
interface CreateMcpHandlerConfig {
|
|
1455
|
+
/**
|
|
1456
|
+
* The `BuildBase()` instance the built-in tools run against (via
|
|
1457
|
+
* `withSession`). Optional — omit it to run a standalone MCP server with
|
|
1458
|
+
* only your own tools (built-ins are then disabled and `ctx.bb` throws a
|
|
1459
|
+
* clear error if a tool touches it).
|
|
1460
|
+
*/
|
|
1461
|
+
buildbase?: McpBuildBaseClient;
|
|
1462
|
+
/** Advertised in `initialize`. Defaults to `buildbase-mcp`. */
|
|
1463
|
+
serverInfo?: {
|
|
1464
|
+
name: string;
|
|
1465
|
+
version: string;
|
|
1466
|
+
};
|
|
1467
|
+
/** Optional usage instructions surfaced to agents on `initialize`. */
|
|
1468
|
+
instructions?: string;
|
|
1469
|
+
/**
|
|
1470
|
+
* Per-request context factory for YOUR tools: whatever it returns (your
|
|
1471
|
+
* database, services, request info) is available as `ctx.custom` in every
|
|
1472
|
+
* `execute`. Runs once per `tools/call`, after auth.
|
|
1473
|
+
*/
|
|
1474
|
+
context?: (auth: McpAuthInfo | null, req: McpHttpRequest) => unknown | Promise<unknown>;
|
|
1475
|
+
/**
|
|
1476
|
+
* Bearer-token verification. Return null to reject (401). Set `false` to
|
|
1477
|
+
* disable auth entirely — local development only.
|
|
1478
|
+
*/
|
|
1479
|
+
auth: {
|
|
1480
|
+
verify: (token: string, req: McpHttpRequest) => McpAuthInfo | null | Promise<McpAuthInfo | null>;
|
|
1481
|
+
/** When set, 401s carry the RFC 9728 `WWW-Authenticate` challenge. */
|
|
1482
|
+
resourceMetadataUrl?: string;
|
|
1483
|
+
} | false;
|
|
1484
|
+
/**
|
|
1485
|
+
* App-defined tools. A custom tool with a built-in's name REPLACES the
|
|
1486
|
+
* built-in (your definition wins); duplicate custom names or invalid names
|
|
1487
|
+
* throw at create time.
|
|
1488
|
+
*/
|
|
1489
|
+
tools?: McpToolDefinition<any, any>[];
|
|
1490
|
+
/**
|
|
1491
|
+
* Which built-in BuildBase tools to expose. **Defaults to `'readonly'`**
|
|
1492
|
+
* when a `buildbase` client is configured (`false` otherwise) — reads only,
|
|
1493
|
+
* so no agent can mutate, bill, or delete anything unless you opt in. Set
|
|
1494
|
+
* `'all'` to expose the full surface (reads + writes + destructive/billing
|
|
1495
|
+
* ops like workspace delete, subscription cancel, credit purchase); `false`
|
|
1496
|
+
* for none; or an `{ include, exclude }` selection to hand-pick. Every tool
|
|
1497
|
+
* still runs under the user's session, so the platform enforces the user's
|
|
1498
|
+
* real permissions on top — but least privilege starts here.
|
|
1499
|
+
*/
|
|
1500
|
+
builtinTools?: 'all' | 'readonly' | false | {
|
|
1501
|
+
include?: BuiltinMcpToolName[];
|
|
1502
|
+
exclude?: BuiltinMcpToolName[];
|
|
1503
|
+
};
|
|
1504
|
+
/**
|
|
1505
|
+
* Allowed `Origin` header values (DNS-rebinding protection). When set, a
|
|
1506
|
+
* request with a non-matching Origin is rejected with 403. Requests without
|
|
1507
|
+
* an Origin header (curl, server-to-server) always pass.
|
|
1508
|
+
*/
|
|
1509
|
+
allowedOrigins?: string[];
|
|
1510
|
+
/**
|
|
1511
|
+
* CORS for browser-based MCP clients. Default **true**: emit
|
|
1512
|
+
* `Access-Control-Allow-Origin: *` (safe for a Bearer-token API — no
|
|
1513
|
+
* cookies are ever involved), or reflect the matching origin when
|
|
1514
|
+
* `allowedOrigins` is set. Pass an origin array to allow only those, or
|
|
1515
|
+
* `false` to emit no CORS headers at all. Preflight (OPTIONS) is answered
|
|
1516
|
+
* automatically either way — no wrapper needed in your route.
|
|
1517
|
+
*/
|
|
1518
|
+
cors?: boolean | string[];
|
|
1519
|
+
/**
|
|
1520
|
+
* Hard cap on the raw request-body size in bytes (DoS protection). Bodies
|
|
1521
|
+
* larger than this are rejected with 413 before parsing. Defaults to
|
|
1522
|
+
* 1 MiB (`1_048_576`); set `0` to disable the check.
|
|
1523
|
+
*/
|
|
1524
|
+
maxRequestBytes?: number;
|
|
1525
|
+
/**
|
|
1526
|
+
* Optional rate-limit gate, called after authentication and before the
|
|
1527
|
+
* JSON-RPC message is dispatched. Return `false` (or a `{ retryAfter }`
|
|
1528
|
+
* object) to reject the request with 429. The SDK is stateless and holds no
|
|
1529
|
+
* counters itself — back this with your own store (KV, Redis, edge limiter),
|
|
1530
|
+
* keyed by `auth.userId`/`auth.sessionId`. Recommended in production; also
|
|
1531
|
+
* apply platform/edge rate limiting in front of the endpoint.
|
|
1532
|
+
*/
|
|
1533
|
+
rateLimit?: (auth: McpAuthInfo | null, req: McpHttpRequest) => boolean | {
|
|
1534
|
+
ok: boolean;
|
|
1535
|
+
retryAfter?: number;
|
|
1536
|
+
} | Promise<boolean | {
|
|
1537
|
+
ok: boolean;
|
|
1538
|
+
retryAfter?: number;
|
|
1539
|
+
}>;
|
|
1540
|
+
/** Called on tool-execution and auth-callback errors (for logging). */
|
|
1541
|
+
onError?: (error: Error, ctx: {
|
|
1542
|
+
method: string;
|
|
1543
|
+
tool?: string;
|
|
1544
|
+
}) => void;
|
|
1545
|
+
/**
|
|
1546
|
+
* Map a thrown tool error to the message returned to the agent. Use it to
|
|
1547
|
+
* redact internal details in production (the full error still reaches
|
|
1548
|
+
* `onError`). Defaults to the raw `error.message`. Return a generic string
|
|
1549
|
+
* — e.g. `() => 'Tool execution failed'` — to leak nothing.
|
|
1550
|
+
*/
|
|
1551
|
+
formatToolError?: (error: Error, ctx: {
|
|
1552
|
+
tool: string;
|
|
1553
|
+
}) => string;
|
|
1554
|
+
}
|
|
1555
|
+
/** The handler returned by {@link createMcpHandler}. */
|
|
1556
|
+
interface McpHandler {
|
|
1557
|
+
/** Pure, framework-agnostic core (Express, Fastify, Hono, tests). */
|
|
1558
|
+
handle(req: McpHttpRequest): Promise<McpHttpResponse>;
|
|
1559
|
+
/** Web-standard adapter (Next.js App Router route handlers, edge). */
|
|
1560
|
+
fetch(request: Request): Promise<Response>;
|
|
1561
|
+
/** Metadata for the exposed tools (before per-request scope filtering). */
|
|
1562
|
+
listTools(): Array<{
|
|
1563
|
+
name: string;
|
|
1564
|
+
description: string;
|
|
1565
|
+
annotations?: McpToolAnnotations;
|
|
1566
|
+
}>;
|
|
1567
|
+
/** A ready-to-assign `AgentReadyConfig.mcpServerCard` for this server. */
|
|
1568
|
+
serverCard(options: {
|
|
1569
|
+
endpoint: string;
|
|
1570
|
+
description?: string;
|
|
1571
|
+
documentationUrl?: string;
|
|
1572
|
+
}): McpServerCard;
|
|
1573
|
+
}
|
|
1574
|
+
/**
|
|
1575
|
+
* Create a stateless MCP server handler exposing BuildBase capabilities (and
|
|
1576
|
+
* any custom tools) over Streamable HTTP. See the module docs for wiring.
|
|
1577
|
+
*/
|
|
1578
|
+
declare function createMcpHandler(config: CreateMcpHandlerConfig): McpHandler;
|
|
1579
|
+
/**
|
|
1580
|
+
* Identity helper that infers the tool's input type from its zod schema.
|
|
1581
|
+
* Pass a second type argument to type `ctx.custom` from your `context`
|
|
1582
|
+
* factory: `defineMcpTool<typeof schema, MyContext>({ ... })`.
|
|
1583
|
+
*/
|
|
1584
|
+
declare function defineMcpTool<S extends z.ZodType, TCustom = any>(tool: McpToolDefinition<S, TCustom>): McpToolDefinition<S, TCustom>;
|
|
1585
|
+
|
|
1586
|
+
/**
|
|
1587
|
+
* OAuth2 app-bridge toolkit (server-side).
|
|
1588
|
+
*
|
|
1589
|
+
* BuildBase runs the OAuth2 authorization flow (login, consent, code, PKCE,
|
|
1590
|
+
* refresh rotation) but it never mints the access token itself — on the token
|
|
1591
|
+
* grant it calls the org's own backend to mint the token the agent will carry.
|
|
1592
|
+
* Concretely, the platform makes signed webhook-style calls to two endpoints an
|
|
1593
|
+
* OAuth2 client registers:
|
|
1594
|
+
*
|
|
1595
|
+
* • applicationTokenUrl — mint an access token for a user (required)
|
|
1596
|
+
* • applicationRevokeUrl — invalidate a user's token on revocation (optional)
|
|
1597
|
+
*
|
|
1598
|
+
* Both requests carry an `Authorization: Bearer <JWT>` where the JWT is HS256,
|
|
1599
|
+
* signed with the client's secret (so possession of the secret authenticates
|
|
1600
|
+
* the platform). This module verifies those requests and shapes the responses,
|
|
1601
|
+
* so an implementor writes only the part that is theirs: minting/invalidating a
|
|
1602
|
+
* token in their own format.
|
|
1603
|
+
*
|
|
1604
|
+
* HMAC verification uses the SDK's dependency-free pure-JS HMAC-SHA256 (no Web
|
|
1605
|
+
* Crypto, no Node `crypto`, no `require`), so it behaves identically whether the
|
|
1606
|
+
* bundle is loaded as ESM or CJS, under a bundler or on bare Node.
|
|
1607
|
+
*
|
|
1608
|
+
* @example applicationTokenUrl handler (Next.js Pages Router):
|
|
1609
|
+
* ```ts
|
|
1610
|
+
* import { handleAppTokenRequest } from "@buildbase/sdk";
|
|
1611
|
+
* export default async function handler(req, res) {
|
|
1612
|
+
* const { status, body } = await handleAppTokenRequest({
|
|
1613
|
+
* authorization: req.headers.authorization,
|
|
1614
|
+
* clientSecret: process.env.BUILDBASE_CLIENT_SECRET!,
|
|
1615
|
+
* mintToken: (user) => ({
|
|
1616
|
+
* token: signMyAccessToken(user, { aud: user.resource }), // your token, your format
|
|
1617
|
+
* expiresIn: 3600,
|
|
1618
|
+
* }),
|
|
1619
|
+
* });
|
|
1620
|
+
* res.status(status).json(body);
|
|
1621
|
+
* }
|
|
1622
|
+
* ```
|
|
1623
|
+
*/
|
|
1624
|
+
/** Thrown when an incoming platform request fails verification. */
|
|
1625
|
+
declare class AppBridgeError extends Error {
|
|
1626
|
+
/** Machine-readable reason, e.g. `invalid_signature`, `token_expired`. */
|
|
1627
|
+
readonly code: string;
|
|
1628
|
+
constructor(code: string, message: string);
|
|
1629
|
+
}
|
|
1630
|
+
/**
|
|
1631
|
+
* The user + grant context BuildBase sends to `applicationTokenUrl`. The app
|
|
1632
|
+
* mints a token for this user; `resource` is the RFC 8707 audience(s) the token
|
|
1633
|
+
* should be bound to (stamp them as `aud`), and `scope` is what the user granted.
|
|
1634
|
+
* Unknown claims are preserved for forward-compatibility.
|
|
1635
|
+
*/
|
|
1636
|
+
interface AppTokenRequestClaims {
|
|
1637
|
+
/** The user's id in the org. */
|
|
1638
|
+
id: string;
|
|
1639
|
+
email: string;
|
|
1640
|
+
name?: string;
|
|
1641
|
+
role?: string;
|
|
1642
|
+
emailVerified?: boolean;
|
|
1643
|
+
image?: string;
|
|
1644
|
+
blocked?: boolean;
|
|
1645
|
+
blockedReason?: string;
|
|
1646
|
+
blockedAt?: string;
|
|
1647
|
+
/** Which grant triggered this mint. */
|
|
1648
|
+
grantType?: 'authorization_code' | 'refresh_token';
|
|
1649
|
+
/** Scopes granted at authorization time. */
|
|
1650
|
+
scope?: string[];
|
|
1651
|
+
/** RFC 8707 resource indicator(s) — bind the minted token's `aud` to these. */
|
|
1652
|
+
resource?: string[];
|
|
1653
|
+
/** The OAuth2 client's display title. */
|
|
1654
|
+
clientTitle?: string;
|
|
1655
|
+
/**
|
|
1656
|
+
* Per-user BuildBase session bound to this grant. Embed it ENCRYPTED in the
|
|
1657
|
+
* token you mint (JWTs are signed, not encrypted) and never store it — your
|
|
1658
|
+
* MCP/agent endpoints decrypt it per request to call BuildBase as this user
|
|
1659
|
+
* (`buildbase.withSession(...)`). Fresh on every grant, including refresh.
|
|
1660
|
+
*/
|
|
1661
|
+
sessionId?: string;
|
|
1662
|
+
[claim: string]: unknown;
|
|
1663
|
+
}
|
|
1664
|
+
/** Options for {@link verifyClientJwt} (all optional; secure defaults). */
|
|
1665
|
+
interface VerifyClientJwtOptions {
|
|
1666
|
+
/** Allowed clock skew in seconds for `exp`/`nbf`. Default 60. */
|
|
1667
|
+
clockToleranceSec?: number;
|
|
1668
|
+
/**
|
|
1669
|
+
* Require a numeric `exp` claim. Default **true** — a JWT with no expiry
|
|
1670
|
+
* would never expire, so a leaked token stays valid forever. Set `false`
|
|
1671
|
+
* only for a token type you know is intentionally non-expiring.
|
|
1672
|
+
*/
|
|
1673
|
+
requireExp?: boolean;
|
|
1674
|
+
/** If set, `iss` must equal this value (RFC 7519 issuer check). */
|
|
1675
|
+
issuer?: string;
|
|
1676
|
+
/** If set, `aud` must equal (or, for an array `aud`, include) this value. */
|
|
1677
|
+
audience?: string;
|
|
1678
|
+
}
|
|
1679
|
+
/**
|
|
1680
|
+
* Verify a BuildBase-issued HS256 JWT (signed with the client secret) and return
|
|
1681
|
+
* its payload. Checks the signature (timing-safe), the algorithm, `exp`/`nbf`,
|
|
1682
|
+
* and — by default — that an `exp` is present at all. Optionally pins `iss`/`aud`.
|
|
1683
|
+
* Throws {@link AppBridgeError} on any failure.
|
|
1684
|
+
*/
|
|
1685
|
+
declare function verifyClientJwt(token: string, clientSecret: string, options?: VerifyClientJwtOptions): Record<string, any>;
|
|
1686
|
+
/** Extract the token from an `Authorization: Bearer <token>` header. */
|
|
1687
|
+
declare function extractBearerToken(authorization: string | null | undefined): string | null;
|
|
1688
|
+
/**
|
|
1689
|
+
* Sign an HS256 JWT — the symmetric counterpart of {@link verifyClientJwt}.
|
|
1690
|
+
* Sets `iat` and `exp` (from `expiresInSec`, default 3600) unless the payload
|
|
1691
|
+
* already carries them. The intended use is minting the app's own agent access
|
|
1692
|
+
* tokens in an `applicationTokenUrl` handler, embedding whatever claims the
|
|
1693
|
+
* MCP/API layer needs to verify later (e.g. `sub`, `scope`, a session id).
|
|
1694
|
+
*/
|
|
1695
|
+
declare function signClientJwt(payload: Record<string, unknown>, secret: string, options?: {
|
|
1696
|
+
expiresInSec?: number;
|
|
1697
|
+
}): string;
|
|
1698
|
+
declare function bearerChallenge(options: {
|
|
1699
|
+
resourceMetadataUrl: string;
|
|
1700
|
+
error?: 'invalid_token' | 'insufficient_scope' | string;
|
|
1701
|
+
errorDescription?: string;
|
|
1702
|
+
}): {
|
|
1703
|
+
status: number;
|
|
1704
|
+
headers: Record<string, string>;
|
|
1705
|
+
body: string;
|
|
1706
|
+
};
|
|
1707
|
+
|
|
1708
|
+
/**
|
|
1709
|
+
* createAgentStack — the whole agent-readiness + MCP surface from ONE config.
|
|
1710
|
+
*
|
|
1711
|
+
* Everything the SDK can derive, it derives: the MCP endpoint, the server
|
|
1712
|
+
* card, the RFC 9728 protected-resource metadata, the API-catalog entry, the
|
|
1713
|
+
* BuildBase client, token verification (via `buildbaseAuth`), CORS, and the
|
|
1714
|
+
* discovery `Link` header — so a consumer configures identity once and wires
|
|
1715
|
+
* two routes. Every derived value stays overridable ("accelerate, never
|
|
1716
|
+
* gate").
|
|
1717
|
+
*
|
|
1718
|
+
* @example Next.js App Router — complete agent support:
|
|
1719
|
+
* ```ts
|
|
1720
|
+
* // lib/agent.ts
|
|
1721
|
+
* import { createAgentStack } from "@buildbase/sdk/mcp";
|
|
1722
|
+
* export const agent = createAgentStack({
|
|
1723
|
+
* serverUrl: process.env.NEXT_PUBLIC_BUILDBASE_SERVER_URL!,
|
|
1724
|
+
* orgId: process.env.NEXT_PUBLIC_BUILDBASE_ORG_ID!,
|
|
1725
|
+
* siteUrl: "https://app.example.com",
|
|
1726
|
+
* site: { name: "My App" },
|
|
1727
|
+
* secret: process.env.SYSTEM_SECRET!,
|
|
1728
|
+
* });
|
|
1729
|
+
*
|
|
1730
|
+
* // app/api/mcp/route.ts
|
|
1731
|
+
* import { agent } from "@/lib/agent";
|
|
1732
|
+
* export const { GET, POST, DELETE, OPTIONS } = agent.routes;
|
|
1733
|
+
*
|
|
1734
|
+
* // app/.well-known/[...path]/route.ts — and identical one-liners at
|
|
1735
|
+
* // app/robots.txt/route.ts, app/auth.md/route.ts, app/security.txt/route.ts
|
|
1736
|
+
* import { agent } from "@/lib/agent";
|
|
1737
|
+
* export const GET = agent.serveAgentPath;
|
|
1738
|
+
* ```
|
|
1739
|
+
*
|
|
1740
|
+
* @example Express / Hono / Bun — same stack, `handle`/`fetch` style:
|
|
1741
|
+
* ```ts
|
|
1742
|
+
* app.all("/api/mcp", async (req, res) => {
|
|
1743
|
+
* const r = await agent.mcp.handle({ method: req.method, headers: req.headers, body: req.body });
|
|
1744
|
+
* res.status(r.status).set(r.headers).send(r.body);
|
|
1745
|
+
* });
|
|
1746
|
+
* app.use(async (req, res, next) => {
|
|
1747
|
+
* const doc = await agent.resolvePath(req.path);
|
|
1748
|
+
* if (!doc) return next();
|
|
1749
|
+
* res.status(doc.status).set("Content-Type", doc.contentType).send(doc.body);
|
|
1750
|
+
* });
|
|
1751
|
+
* ```
|
|
1752
|
+
*/
|
|
1753
|
+
|
|
1754
|
+
/** Configuration for {@link createAgentStack}. */
|
|
1755
|
+
interface AgentStackConfig {
|
|
1756
|
+
/** BuildBase server base URL. */
|
|
1757
|
+
serverUrl: string;
|
|
1758
|
+
/** The org id. */
|
|
1759
|
+
orgId: string;
|
|
1760
|
+
/** This app's public origin, e.g. `https://app.example.com`. */
|
|
1761
|
+
siteUrl: string;
|
|
1762
|
+
/** Site identity for every discovery document. */
|
|
1763
|
+
site: AgentReadyConfig['site'];
|
|
1764
|
+
/**
|
|
1765
|
+
* The app's token-signing secret — wires `buildbaseAuth` (verify + audience
|
|
1766
|
+
* binding + `sid` decryption) automatically. Never sent anywhere. Omit only
|
|
1767
|
+
* when supplying `mcp.auth` yourself.
|
|
1768
|
+
*/
|
|
1769
|
+
secret?: string;
|
|
1770
|
+
/**
|
|
1771
|
+
* The app's OAuth scope catalog (see `AgentReadyConfig.scopes`) —
|
|
1772
|
+
* `scopes_supported` in the protected-resource metadata reads from it.
|
|
1773
|
+
*/
|
|
1774
|
+
scopes?: AppScope[];
|
|
1775
|
+
/** MCP server options. All optional — omit the whole block for defaults. */
|
|
1776
|
+
mcp?: {
|
|
1777
|
+
/** Endpoint path on `siteUrl`. Default `/api/mcp`. */
|
|
1778
|
+
path?: string;
|
|
1779
|
+
/** Advertised server identity. Defaults to the site name, v1.0.0. */
|
|
1780
|
+
serverInfo?: {
|
|
1781
|
+
name: string;
|
|
1782
|
+
version: string;
|
|
1783
|
+
};
|
|
1784
|
+
/** Your custom tools. */
|
|
1785
|
+
tools?: McpToolDefinition<any, any>[];
|
|
1786
|
+
/** Built-in tool selection. Default `'readonly'`. */
|
|
1787
|
+
builtinTools?: CreateMcpHandlerConfig['builtinTools'];
|
|
1788
|
+
/** Scopes advertised on the protected-resource metadata. */
|
|
1789
|
+
scopes?: string[];
|
|
1790
|
+
/** Your own BuildBase client; auto-created from serverUrl/orgId if omitted. */
|
|
1791
|
+
buildbase?: McpBuildBaseClient;
|
|
1792
|
+
/** Override the derived auth (e.g. `false` for local dev). */
|
|
1793
|
+
auth?: CreateMcpHandlerConfig['auth'];
|
|
1794
|
+
/** Any remaining `createMcpHandler` option, merged last. */
|
|
1795
|
+
handler?: Partial<CreateMcpHandlerConfig>;
|
|
1796
|
+
};
|
|
1797
|
+
/**
|
|
1798
|
+
* Any {@link AgentReadyConfig} field (robots, skills, llms.txt, security,
|
|
1799
|
+
* a2aCard, extraPaths, …) — merged over the derived discovery config, so
|
|
1800
|
+
* every derived value can be replaced.
|
|
1801
|
+
*/
|
|
1802
|
+
discovery?: Partial<AgentReadyConfig>;
|
|
1803
|
+
}
|
|
1804
|
+
/** What {@link createAgentStack} returns. */
|
|
1805
|
+
interface AgentStack {
|
|
1806
|
+
/** The MCP handler (`handle`/`fetch`/`listTools`/`serverCard`). */
|
|
1807
|
+
mcp: McpHandler;
|
|
1808
|
+
/** Absolute MCP endpoint URL. */
|
|
1809
|
+
mcpEndpoint: string;
|
|
1810
|
+
/** The fully derived discovery config (inspect or reuse in middleware). */
|
|
1811
|
+
config: AgentReadyConfig;
|
|
1812
|
+
/** Discovery `Link` header value for your middleware / edge responses. */
|
|
1813
|
+
linkHeader: string;
|
|
1814
|
+
/** Resolve any agent-facing path to a document (framework-agnostic). */
|
|
1815
|
+
resolvePath(path: string): Promise<DiscoveryDocument | null>;
|
|
1816
|
+
/** Web-standard discovery route: hand it any `Request`, get a `Response`. */
|
|
1817
|
+
serveAgentPath(request: Request): Promise<Response>;
|
|
1818
|
+
/**
|
|
1819
|
+
* Web-standard MCP route handlers, ready to re-export from a route file:
|
|
1820
|
+
* `export const { GET, POST, DELETE, OPTIONS } = agent.routes`.
|
|
1821
|
+
*/
|
|
1822
|
+
routes: {
|
|
1823
|
+
GET: (request: Request) => Promise<Response>;
|
|
1824
|
+
POST: (request: Request) => Promise<Response>;
|
|
1825
|
+
DELETE: (request: Request) => Promise<Response>;
|
|
1826
|
+
OPTIONS: (request: Request) => Promise<Response>;
|
|
1827
|
+
};
|
|
1828
|
+
}
|
|
1829
|
+
/**
|
|
1830
|
+
* Build the complete agent stack — MCP server + discovery surface — from one
|
|
1831
|
+
* config object. See the module doc for full wiring examples.
|
|
1832
|
+
*/
|
|
1833
|
+
declare function createAgentStack(stack: AgentStackConfig): AgentStack;
|
|
1834
|
+
|
|
1835
|
+
/**
|
|
1836
|
+
* BuildBase agent-auth presets (server-side, framework-agnostic).
|
|
1837
|
+
*
|
|
1838
|
+
* The BuildBase security model: the platform runs the OAuth2 flow (login,
|
|
1839
|
+
* consent, PKCE, refresh) but the APP mints and verifies its own user tokens,
|
|
1840
|
+
* signed with the app's own secret. The platform only relays the minted token
|
|
1841
|
+
* to the agent — it never sees the secret, so it can neither forge nor decode
|
|
1842
|
+
* an app token. The per-user BuildBase session travels inside the token only
|
|
1843
|
+
* as an AES-256-GCM-encrypted `sid` claim, so it is never stored and never
|
|
1844
|
+
* plaintext anywhere; access to it expires with the token.
|
|
1845
|
+
*
|
|
1846
|
+
* These presets make that model a one-liner on each side of the flow, and run
|
|
1847
|
+
* entirely in the app's process — pure local crypto, zero platform calls:
|
|
1848
|
+
*
|
|
1849
|
+
* • {@link mintAgentToken} — inside your `applicationTokenUrl` handler:
|
|
1850
|
+
* signs the app JWT (HS256) with your secret, stamps `aud` from the RFC
|
|
1851
|
+
* 8707 resource, and embeds the encrypted `sid` automatically.
|
|
1852
|
+
* • {@link buildbaseAuth} — the `auth` config for `createMcpHandler`:
|
|
1853
|
+
* verifies the JWT, enforces audience binding, decrypts the `sid`, and
|
|
1854
|
+
* maps the claims to `McpAuthInfo`.
|
|
1855
|
+
*
|
|
1856
|
+
* @example The full loop:
|
|
1857
|
+
* ```ts
|
|
1858
|
+
* // applicationTokenUrl route — the platform calls this on every grant
|
|
1859
|
+
* const { status, body } = await handleAppTokenRequest({
|
|
1860
|
+
* authorization: req.headers.get("authorization"),
|
|
1861
|
+
* clientSecret: process.env.BUILDBASE_CLIENT_SECRET!,
|
|
1862
|
+
* mintToken: (claims) => mintAgentToken({ claims, secret: process.env.SYSTEM_SECRET! }),
|
|
1863
|
+
* });
|
|
1864
|
+
*
|
|
1865
|
+
* // MCP server — verifies what the route above minted
|
|
1866
|
+
* const mcp = createMcpHandler({
|
|
1867
|
+
* buildbase,
|
|
1868
|
+
* auth: buildbaseAuth({ secret: process.env.SYSTEM_SECRET!, resource: "https://app.example.com/api/mcp" }),
|
|
1869
|
+
* });
|
|
1870
|
+
* ```
|
|
1871
|
+
*
|
|
1872
|
+
* AES-GCM comes from WebCrypto (`globalThis.crypto.subtle`) — Node 18+, Bun,
|
|
1873
|
+
* Deno, edge runtimes, browsers. The wire format is
|
|
1874
|
+
* `base64url(iv(12) || authTag(16) || ciphertext)` with the key derived as
|
|
1875
|
+
* `SHA-256(secret + ":bb-session")`, byte-compatible with Node
|
|
1876
|
+
* `createCipheriv("aes-256-gcm", ...)` implementations of the same layout.
|
|
1877
|
+
*/
|
|
1878
|
+
|
|
1879
|
+
/** Encrypt/decrypt pair for the `sid` claim, bound to one app secret. */
|
|
1880
|
+
interface SessionRefCrypto {
|
|
1881
|
+
/** Encrypt a BuildBase session id for embedding in an app JWT. */
|
|
1882
|
+
encryptSessionRef(sessionId: string): Promise<string>;
|
|
1883
|
+
/** Decrypt a `sid` claim. Returns null on any failure (wrong key, garbage). */
|
|
1884
|
+
decryptSessionRef(ref: string): Promise<string | null>;
|
|
1885
|
+
}
|
|
1886
|
+
/**
|
|
1887
|
+
* Session-ref crypto derived from the app's secret. Both sides of the loop
|
|
1888
|
+
* ({@link mintAgentToken}, {@link buildbaseAuth}) use this internally — reach
|
|
1889
|
+
* for it directly only when minting or verifying tokens by hand.
|
|
1890
|
+
*/
|
|
1891
|
+
declare function createSessionRefCrypto(secret: string): SessionRefCrypto;
|
|
1892
|
+
/** Options for {@link mintAgentToken}. */
|
|
1893
|
+
interface MintAgentTokenOptions {
|
|
1894
|
+
/** The verified platform claims (from `handleAppTokenRequest`'s callback). */
|
|
1895
|
+
claims: AppTokenRequestClaims;
|
|
1896
|
+
/** The APP's token-signing secret. Never leaves this process. */
|
|
1897
|
+
secret: string;
|
|
1898
|
+
/** Token lifetime in seconds. Default 3600 — keep agent tokens short-lived. */
|
|
1899
|
+
expiresInSec?: number;
|
|
1900
|
+
/**
|
|
1901
|
+
* App-specific claims merged into the token — e.g. a `workspaceId` resolved
|
|
1902
|
+
* by your own user sync. Merged last, so they can override the defaults.
|
|
1903
|
+
*/
|
|
1904
|
+
extraClaims?: Record<string, unknown>;
|
|
1905
|
+
}
|
|
1906
|
+
/**
|
|
1907
|
+
* Mint the app's agent access token from a platform grant: HS256-signed with
|
|
1908
|
+
* YOUR secret, `aud` bound to the granted RFC 8707 resource(s), scopes carried
|
|
1909
|
+
* through, and the per-user BuildBase session embedded as an encrypted `sid`
|
|
1910
|
+
* claim. The result plugs straight into `handleAppTokenRequest`'s `mintToken`.
|
|
1911
|
+
*/
|
|
1912
|
+
declare function mintAgentToken(options: MintAgentTokenOptions): Promise<{
|
|
1913
|
+
token: string;
|
|
1914
|
+
expiresIn: number;
|
|
1915
|
+
}>;
|
|
1916
|
+
/** Options for {@link buildbaseAuth}. */
|
|
1917
|
+
interface BuildBaseAuthOptions {
|
|
1918
|
+
/** The APP's token-signing secret — the same one `mintAgentToken` used. */
|
|
1919
|
+
secret: string;
|
|
1920
|
+
/**
|
|
1921
|
+
* The protected resource(s) this server IS. Enforces RFC 8707 audience
|
|
1922
|
+
* binding — the token's `aud` must include one of these URIs. Pass an array
|
|
1923
|
+
* when the server is addressable under more than one resource identifier
|
|
1924
|
+
* (e.g. the canonical `<host>/mcp` plus the literal endpoint URL); the
|
|
1925
|
+
* FIRST entry is the canonical one used to derive `resourceMetadataUrl`.
|
|
1926
|
+
*/
|
|
1927
|
+
resource?: string | string[];
|
|
1928
|
+
/**
|
|
1929
|
+
* Explicit RFC 9728 metadata URL for the 401 challenge. Defaults to the
|
|
1930
|
+
* path-derived `/.well-known/oauth-protected-resource<path>` of the first
|
|
1931
|
+
* `resource`.
|
|
1932
|
+
*/
|
|
1933
|
+
resourceMetadataUrl?: string;
|
|
1934
|
+
/**
|
|
1935
|
+
* Reject tokens that carry no `aud` claim at all. Default false: audience is
|
|
1936
|
+
* enforced when present, and legacy audience-less tokens still work. Turn
|
|
1937
|
+
* this on once every minted token is audience-bound.
|
|
1938
|
+
*/
|
|
1939
|
+
requireAudience?: boolean;
|
|
1940
|
+
/** Extra JWT verification options (clock tolerance, issuer pinning). */
|
|
1941
|
+
verify?: Pick<VerifyClientJwtOptions, 'clockToleranceSec' | 'issuer'>;
|
|
1942
|
+
}
|
|
1943
|
+
/**
|
|
1944
|
+
* The `auth` config for `createMcpHandler`, prewired for BuildBase-minted app
|
|
1945
|
+
* tokens: HS256 verification with your secret, RFC 8707 audience binding,
|
|
1946
|
+
* `sid` decryption to the BuildBase session, claim mapping to `McpAuthInfo`,
|
|
1947
|
+
* and the derived RFC 9728 `resourceMetadataUrl`. Entirely local — the token
|
|
1948
|
+
* and secret never leave this process.
|
|
1949
|
+
*/
|
|
1950
|
+
declare function buildbaseAuth(options: BuildBaseAuthOptions): {
|
|
1951
|
+
verify: (token: string, req: McpHttpRequest) => Promise<McpAuthInfo | null>;
|
|
1952
|
+
resourceMetadataUrl?: string;
|
|
1953
|
+
};
|
|
1954
|
+
|
|
1955
|
+
export { AppBridgeError, bearerChallenge, buildbaseAuth, builtinMcpTools, createAgentStack, createMcpHandler, createSessionRefCrypto, defineMcpTool, extractBearerToken, mintAgentToken, selectBuiltinTools, signClientJwt, verifyClientJwt };
|
|
1956
|
+
export type { AgentStack, AgentStackConfig, BuildBaseAuthOptions, BuiltinMcpToolName, CreateMcpHandlerConfig, McpAuthInfo, McpBuildBaseClient, McpHandler, McpHttpRequest, McpHttpResponse, McpServerCard, McpToolAnnotations, McpToolContext, McpToolDefinition, MintAgentTokenOptions, ScopedActions, SessionRefCrypto };
|