@buildbase/sdk 0.0.53 → 0.0.55
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 +16 -6
- package/CHANGELOG.md +99 -0
- package/LICENSE +21 -0
- package/README.md +278 -85
- package/dist/css/styles.css +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +582 -114
- package/dist/index.mjs +1 -1
- package/dist/mcp/index.cjs +1 -1
- package/dist/mcp/index.d.ts +780 -16
- package/dist/mcp/index.mjs +1 -1
- package/dist/react/chunks/SettingsDialog-B6DhyNae.cjs +2 -0
- package/dist/react/chunks/SettingsDialog-K38BI74F.mjs +2 -0
- package/dist/react/chunks/SubscriptionDialog-BidcQ_vc.mjs +2 -0
- package/dist/react/chunks/SubscriptionDialog-CfDLoOzW.cjs +2 -0
- package/dist/react/chunks/ar-CCKONfUU.mjs +2 -0
- package/dist/react/chunks/ar-DrHMtT1E.cjs +2 -0
- package/dist/react/chunks/de-Dhtorn10.cjs +2 -0
- package/dist/react/chunks/de-X9mfnMFM.mjs +2 -0
- package/dist/react/chunks/es--8iZ7Trv.mjs +2 -0
- package/dist/react/chunks/es-CUR7LB6a.cjs +2 -0
- package/dist/react/chunks/fr-BqMs_F5g.cjs +2 -0
- package/dist/react/chunks/fr-rUp34NG7.mjs +2 -0
- package/dist/react/chunks/hi-B_IiucJZ.mjs +2 -0
- package/dist/react/chunks/hi-C2i1_hdv.cjs +2 -0
- package/dist/react/chunks/ja-4hLI6wMX.cjs +2 -0
- package/dist/react/chunks/ja-CIGOj3vV.mjs +2 -0
- package/dist/react/chunks/react-BXTDLnE8.cjs +2 -0
- package/dist/react/chunks/react-CXCk05WI.mjs +2 -0
- package/dist/react/chunks/zh-BSgd6ai5.cjs +2 -0
- package/dist/react/chunks/zh-DyVvcYFC.mjs +2 -0
- package/dist/react/index.cjs +1 -1
- package/dist/react/index.d.ts +507 -141
- package/dist/react/index.mjs +1 -1
- package/docs/ARCHITECTURE.md +419 -0
- package/docs/ERROR_CODES.md +96 -0
- package/docs/MCP-AND-AGENT-READINESS.md +893 -0
- package/docs/THEMING.md +67 -0
- package/docs/UI-CONFIG.md +207 -0
- package/package.json +17 -4
- package/dist/react/chunks/SettingsDialog-BxDYsie6.mjs +0 -2
- package/dist/react/chunks/SettingsDialog-Dy8W3NA6.cjs +0 -2
- package/dist/react/chunks/SubscriptionDialog-6c5dHoQd.mjs +0 -2
- package/dist/react/chunks/SubscriptionDialog-CpVnnXJg.cjs +0 -2
- package/dist/react/chunks/ar-1Z1MOGAP.mjs +0 -2
- package/dist/react/chunks/ar-VGzBv3AZ.cjs +0 -2
- package/dist/react/chunks/de-BjdDg60Y.cjs +0 -2
- package/dist/react/chunks/de-CXUItplO.mjs +0 -2
- package/dist/react/chunks/es-BBPsSZUp.cjs +0 -2
- package/dist/react/chunks/es-BTbzVutz.mjs +0 -2
- package/dist/react/chunks/fr-Cax48X_S.cjs +0 -2
- package/dist/react/chunks/fr-DPMeOQu3.mjs +0 -2
- package/dist/react/chunks/hi-BJqvpG6d.cjs +0 -2
- package/dist/react/chunks/hi-JfJx-LV7.mjs +0 -2
- package/dist/react/chunks/ja-CDGtLzTk.mjs +0 -2
- package/dist/react/chunks/ja-DvVyj5xX.cjs +0 -2
- package/dist/react/chunks/react-4SlWxHdh.cjs +0 -2
- package/dist/react/chunks/react-OL1uSkpr.mjs +0 -2
- package/dist/react/chunks/zh-BAcqxkxk.cjs +0 -2
- package/dist/react/chunks/zh-BNZ2Ooe8.mjs +0 -2
package/dist/mcp/index.d.ts
CHANGED
|
@@ -1,6 +1,35 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
|
|
3
|
-
/**
|
|
3
|
+
/** An Agent Skill (Agent Skills Discovery RFC v0.2.0) published by this app. */
|
|
4
|
+
interface AgentSkill {
|
|
5
|
+
/** Stable slug, e.g. `acme-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.example.com`. */
|
|
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. */
|
|
4
33
|
interface McpServerCard {
|
|
5
34
|
/** Server name. */
|
|
6
35
|
name: string;
|
|
@@ -10,13 +39,251 @@ interface McpServerCard {
|
|
|
10
39
|
endpoint: string;
|
|
11
40
|
/** Transport type. Defaults to `"streamable-http"`. */
|
|
12
41
|
transport?: string;
|
|
13
|
-
/**
|
|
42
|
+
/** MCP protocol version the server speaks. Defaults to `"2025-11-25"`. */
|
|
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
|
+
*/
|
|
14
48
|
capabilities?: Record<string, unknown>;
|
|
15
49
|
/** Optional human description. */
|
|
16
50
|
description?: string;
|
|
17
51
|
/** Documentation URL. */
|
|
18
52
|
documentationUrl?: string;
|
|
19
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://example.com`. 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
|
+
}
|
|
20
287
|
|
|
21
288
|
/**
|
|
22
289
|
* Built-in MCP tools mapping BuildBase capabilities to agent-callable tools.
|
|
@@ -40,14 +307,14 @@ interface McpServerCard {
|
|
|
40
307
|
*/
|
|
41
308
|
|
|
42
309
|
/** Every built-in tool, keyed by name. */
|
|
43
|
-
declare const builtinMcpTools: ReadonlyMap<string,
|
|
310
|
+
declare const builtinMcpTools: ReadonlyMap<string, AnyMcpTool>;
|
|
44
311
|
/** The name of a built-in BuildBase MCP tool. */
|
|
45
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';
|
|
46
313
|
/** Resolve a `builtinTools` config value to the tools it selects. */
|
|
47
314
|
declare function selectBuiltinTools(selection: 'all' | 'readonly' | false | {
|
|
48
315
|
include?: BuiltinMcpToolName[];
|
|
49
316
|
exclude?: BuiltinMcpToolName[];
|
|
50
|
-
}):
|
|
317
|
+
}): AnyMcpTool[];
|
|
51
318
|
|
|
52
319
|
interface IDocument {
|
|
53
320
|
_id: string;
|
|
@@ -821,7 +1088,7 @@ interface ISettings {
|
|
|
821
1088
|
/** Auto-create workspace on first login */
|
|
822
1089
|
autoCreateFirst: boolean;
|
|
823
1090
|
};
|
|
824
|
-
[key: string]:
|
|
1091
|
+
[key: string]: unknown;
|
|
825
1092
|
}
|
|
826
1093
|
|
|
827
1094
|
/** Data passed to a notification template for merge tag replacement. */
|
|
@@ -880,7 +1147,7 @@ interface NotificationData {
|
|
|
880
1147
|
push?: boolean;
|
|
881
1148
|
};
|
|
882
1149
|
/** Any additional merge tags available as {{key}} in the email template. */
|
|
883
|
-
[key: string]:
|
|
1150
|
+
[key: string]: unknown;
|
|
884
1151
|
}
|
|
885
1152
|
/** Result of sending a notification. */
|
|
886
1153
|
interface NotificationResult {
|
|
@@ -1082,13 +1349,20 @@ interface ScopedActions {
|
|
|
1082
1349
|
*
|
|
1083
1350
|
* export const mcp = createMcpHandler({
|
|
1084
1351
|
* buildbase,
|
|
1085
|
-
* serverInfo: { name: '
|
|
1352
|
+
* serverInfo: { name: 'acme', version: '1.0.0' },
|
|
1086
1353
|
* auth: {
|
|
1087
1354
|
* verify: (token) => {
|
|
1088
1355
|
* const c = verifyClientJwt(token, process.env.BUILDBASE_CLIENT_SECRET!);
|
|
1089
|
-
*
|
|
1356
|
+
* // Claims beyond RFC 7519 are `unknown` — narrow before use.
|
|
1357
|
+
* return {
|
|
1358
|
+
* sessionId: typeof c.sid === 'string' ? c.sid : '',
|
|
1359
|
+
* userId: c.sub,
|
|
1360
|
+
* scopes: Array.isArray(c.scope)
|
|
1361
|
+
* ? c.scope.filter((s): s is string => typeof s === 'string')
|
|
1362
|
+
* : undefined,
|
|
1363
|
+
* };
|
|
1090
1364
|
* },
|
|
1091
|
-
* resourceMetadataUrl: 'https://
|
|
1365
|
+
* resourceMetadataUrl: 'https://example.com/.well-known/oauth-protected-resource',
|
|
1092
1366
|
* },
|
|
1093
1367
|
* });
|
|
1094
1368
|
*
|
|
@@ -1155,6 +1429,14 @@ interface McpToolContext<TCustom = unknown> {
|
|
|
1155
1429
|
*/
|
|
1156
1430
|
custom: TCustom;
|
|
1157
1431
|
}
|
|
1432
|
+
/** An icon for display in host UIs (SEP-973, protocol 2025-11-25). */
|
|
1433
|
+
interface McpIcon {
|
|
1434
|
+
/** Icon URL (https or data URI). */
|
|
1435
|
+
src: string;
|
|
1436
|
+
mimeType?: string;
|
|
1437
|
+
/** e.g. `['48x48']` or `['any']` for scalable formats. */
|
|
1438
|
+
sizes?: string[];
|
|
1439
|
+
}
|
|
1158
1440
|
/** MCP tool annotations (behavior hints for agents). */
|
|
1159
1441
|
interface McpToolAnnotations {
|
|
1160
1442
|
title?: string;
|
|
@@ -1163,6 +1445,70 @@ interface McpToolAnnotations {
|
|
|
1163
1445
|
idempotentHint?: boolean;
|
|
1164
1446
|
openWorldHint?: boolean;
|
|
1165
1447
|
}
|
|
1448
|
+
/** Plain text block. */
|
|
1449
|
+
interface McpTextContent {
|
|
1450
|
+
type: 'text';
|
|
1451
|
+
text: string;
|
|
1452
|
+
}
|
|
1453
|
+
/** Base64-encoded image (`data` has no data-URI prefix). */
|
|
1454
|
+
interface McpImageContent {
|
|
1455
|
+
type: 'image';
|
|
1456
|
+
data: string;
|
|
1457
|
+
mimeType: string;
|
|
1458
|
+
}
|
|
1459
|
+
/** Base64-encoded audio (`data` has no data-URI prefix). */
|
|
1460
|
+
interface McpAudioContent {
|
|
1461
|
+
type: 'audio';
|
|
1462
|
+
data: string;
|
|
1463
|
+
mimeType: string;
|
|
1464
|
+
}
|
|
1465
|
+
/** Link to a resource the client may fetch — the content itself is not embedded. */
|
|
1466
|
+
interface McpResourceLinkContent {
|
|
1467
|
+
type: 'resource_link';
|
|
1468
|
+
uri: string;
|
|
1469
|
+
name: string;
|
|
1470
|
+
title?: string;
|
|
1471
|
+
description?: string;
|
|
1472
|
+
mimeType?: string;
|
|
1473
|
+
size?: number;
|
|
1474
|
+
}
|
|
1475
|
+
/** Resource contents embedded directly in the result (text or base64 blob). */
|
|
1476
|
+
interface McpEmbeddedResourceContent {
|
|
1477
|
+
type: 'resource';
|
|
1478
|
+
resource: {
|
|
1479
|
+
uri: string;
|
|
1480
|
+
mimeType?: string;
|
|
1481
|
+
title?: string;
|
|
1482
|
+
} & ({
|
|
1483
|
+
text: string;
|
|
1484
|
+
} | {
|
|
1485
|
+
blob: string;
|
|
1486
|
+
});
|
|
1487
|
+
}
|
|
1488
|
+
/** Any content block a tool result may carry. */
|
|
1489
|
+
type McpContentBlock = McpTextContent | McpImageContent | McpAudioContent | McpResourceLinkContent | McpEmbeddedResourceContent;
|
|
1490
|
+
/**
|
|
1491
|
+
* Full wire-shaped tool result. Return this from `execute` to control the
|
|
1492
|
+
* result exactly — mixed content blocks (text + images + resource links),
|
|
1493
|
+
* `structuredContent`, and the `isError` flag. Any other return value keeps
|
|
1494
|
+
* the legacy behavior: strings become one text block, objects become
|
|
1495
|
+
* JSON text + `structuredContent`.
|
|
1496
|
+
*/
|
|
1497
|
+
interface McpToolResult {
|
|
1498
|
+
content: McpContentBlock[];
|
|
1499
|
+
structuredContent?: Record<string, unknown>;
|
|
1500
|
+
isError?: boolean;
|
|
1501
|
+
}
|
|
1502
|
+
/** Text content block (`mcpText('done')`). */
|
|
1503
|
+
declare const mcpText: (text: string) => McpTextContent;
|
|
1504
|
+
/** Image content block from base64 data (`mcpImage(pngBase64, 'image/png')`). */
|
|
1505
|
+
declare const mcpImage: (data: string, mimeType: string) => McpImageContent;
|
|
1506
|
+
/** Audio content block from base64 data (`mcpAudio(wavBase64, 'audio/wav')`). */
|
|
1507
|
+
declare const mcpAudio: (data: string, mimeType: string) => McpAudioContent;
|
|
1508
|
+
/** Resource-link content block (`mcpResourceLink('https://…/report.pdf', 'report')`). */
|
|
1509
|
+
declare const mcpResourceLink: (uri: string, name: string, extra?: Omit<McpResourceLinkContent, "type" | "uri" | "name">) => McpResourceLinkContent;
|
|
1510
|
+
/** Embedded-resource content block (`mcpEmbeddedResource({ uri, text })`). */
|
|
1511
|
+
declare const mcpEmbeddedResource: (resource: McpEmbeddedResourceContent["resource"]) => McpEmbeddedResourceContent;
|
|
1166
1512
|
/** A tool exposed over MCP. Use {@link defineMcpTool} for inferred input types. */
|
|
1167
1513
|
interface McpToolDefinition<S extends z.ZodType = z.ZodType, TCustom = any> {
|
|
1168
1514
|
/** Tool name: `[a-zA-Z0-9_-]`, 1–128 chars. */
|
|
@@ -1174,6 +1520,8 @@ interface McpToolDefinition<S extends z.ZodType = z.ZodType, TCustom = any> {
|
|
|
1174
1520
|
*/
|
|
1175
1521
|
inputSchema: S | Record<string, unknown>;
|
|
1176
1522
|
annotations?: McpToolAnnotations;
|
|
1523
|
+
/** Optional icons for host UIs (protocol 2025-11-25). */
|
|
1524
|
+
icons?: McpIcon[];
|
|
1177
1525
|
/**
|
|
1178
1526
|
* Scopes required to see/call this tool. The token must carry ALL of them
|
|
1179
1527
|
* (`McpAuthInfo.scopes`) for the tool to be visible or callable; a token
|
|
@@ -1181,8 +1529,98 @@ interface McpToolDefinition<S extends z.ZodType = z.ZodType, TCustom = any> {
|
|
|
1181
1529
|
* no scopes and are governed by `builtinTools` + the user's own permissions.
|
|
1182
1530
|
*/
|
|
1183
1531
|
requiredScopes?: string[];
|
|
1532
|
+
/**
|
|
1533
|
+
* Runs the tool. Return an {@link McpToolResult} for full control over the
|
|
1534
|
+
* wire result (images, resource links, mixed blocks); any other value is
|
|
1535
|
+
* auto-wrapped (string → text block; object → JSON text + structuredContent).
|
|
1536
|
+
*/
|
|
1184
1537
|
execute: (input: z.output<S>, ctx: McpToolContext<TCustom>) => unknown | Promise<unknown>;
|
|
1185
1538
|
}
|
|
1539
|
+
/**
|
|
1540
|
+
* Existential tool type for heterogeneous lists (registries, config arrays).
|
|
1541
|
+
* Each tool keeps its precise schema/context types at its definition site
|
|
1542
|
+
* (use {@link defineMcpTool}); `any` here only erases them for storage —
|
|
1543
|
+
* never use it to define a tool.
|
|
1544
|
+
*/
|
|
1545
|
+
type AnyMcpTool = McpToolDefinition<any, any>;
|
|
1546
|
+
/**
|
|
1547
|
+
* What a resource `read` may return. Strings become text contents, plain
|
|
1548
|
+
* objects become pretty-printed JSON (`application/json`), and an explicit
|
|
1549
|
+
* `{ text }` or `{ blob }` shape is used as-is (blob = base64).
|
|
1550
|
+
*/
|
|
1551
|
+
type McpResourceReadResult = string | {
|
|
1552
|
+
text: string;
|
|
1553
|
+
mimeType?: string;
|
|
1554
|
+
} | {
|
|
1555
|
+
blob: string;
|
|
1556
|
+
mimeType?: string;
|
|
1557
|
+
} | object;
|
|
1558
|
+
/** A fixed-URI resource served via `resources/list` + `resources/read`. */
|
|
1559
|
+
interface McpResourceDefinition<TCustom = any> {
|
|
1560
|
+
/** Unique resource URI (custom schemes welcome, e.g. `app://orders`). */
|
|
1561
|
+
uri: string;
|
|
1562
|
+
name: string;
|
|
1563
|
+
title?: string;
|
|
1564
|
+
description?: string;
|
|
1565
|
+
mimeType?: string;
|
|
1566
|
+
icons?: McpIcon[];
|
|
1567
|
+
/** Same gating semantics as tools: token must carry ALL listed scopes. */
|
|
1568
|
+
requiredScopes?: string[];
|
|
1569
|
+
read: (ctx: McpToolContext<TCustom>) => McpResourceReadResult | Promise<McpResourceReadResult>;
|
|
1570
|
+
}
|
|
1571
|
+
/**
|
|
1572
|
+
* A parameterized resource (RFC 6570 level-1 `{var}` templates only), served
|
|
1573
|
+
* via `resources/templates/list` and matched on `resources/read`.
|
|
1574
|
+
*/
|
|
1575
|
+
interface McpResourceTemplateDefinition<TCustom = any> {
|
|
1576
|
+
/** e.g. `buildbase://workspace/{workspaceId}` — `{var}` matches one segment. */
|
|
1577
|
+
uriTemplate: string;
|
|
1578
|
+
name: string;
|
|
1579
|
+
title?: string;
|
|
1580
|
+
description?: string;
|
|
1581
|
+
mimeType?: string;
|
|
1582
|
+
icons?: McpIcon[];
|
|
1583
|
+
requiredScopes?: string[];
|
|
1584
|
+
read: (params: Record<string, string>, uri: string, ctx: McpToolContext<TCustom>) => McpResourceReadResult | Promise<McpResourceReadResult>;
|
|
1585
|
+
}
|
|
1586
|
+
/** Message content allowed in prompts (spec: text, image, audio, embedded resource). */
|
|
1587
|
+
type McpPromptContent = McpTextContent | McpImageContent | McpAudioContent | McpEmbeddedResourceContent;
|
|
1588
|
+
/** One message of a prompt template. */
|
|
1589
|
+
interface McpPromptMessage {
|
|
1590
|
+
role: 'user' | 'assistant';
|
|
1591
|
+
content: McpPromptContent;
|
|
1592
|
+
}
|
|
1593
|
+
/** A prompt template served via `prompts/list` + `prompts/get`. */
|
|
1594
|
+
interface McpPromptDefinition<TCustom = any> {
|
|
1595
|
+
/** Unique prompt name (same charset rules as tool names). */
|
|
1596
|
+
name: string;
|
|
1597
|
+
title?: string;
|
|
1598
|
+
description?: string;
|
|
1599
|
+
icons?: McpIcon[];
|
|
1600
|
+
arguments?: Array<{
|
|
1601
|
+
name: string;
|
|
1602
|
+
description?: string;
|
|
1603
|
+
required?: boolean;
|
|
1604
|
+
}>;
|
|
1605
|
+
requiredScopes?: string[];
|
|
1606
|
+
/**
|
|
1607
|
+
* Build the messages. A plain string return becomes one user text message;
|
|
1608
|
+
* an array is used as the messages; the object form also sets `description`.
|
|
1609
|
+
*/
|
|
1610
|
+
get: (args: Record<string, string>, ctx: McpToolContext<TCustom>) => string | McpPromptMessage[] | {
|
|
1611
|
+
description?: string;
|
|
1612
|
+
messages: McpPromptMessage[];
|
|
1613
|
+
} | Promise<string | McpPromptMessage[] | {
|
|
1614
|
+
description?: string;
|
|
1615
|
+
messages: McpPromptMessage[];
|
|
1616
|
+
}>;
|
|
1617
|
+
}
|
|
1618
|
+
/** Identity helper for inferred types (mirror of {@link defineMcpTool}). */
|
|
1619
|
+
declare const defineMcpResource: <TCustom = any>(resource: McpResourceDefinition<TCustom>) => McpResourceDefinition<TCustom>;
|
|
1620
|
+
/** Identity helper for inferred types (mirror of {@link defineMcpTool}). */
|
|
1621
|
+
declare const defineMcpResourceTemplate: <TCustom = any>(template: McpResourceTemplateDefinition<TCustom>) => McpResourceTemplateDefinition<TCustom>;
|
|
1622
|
+
/** Identity helper for inferred types (mirror of {@link defineMcpTool}). */
|
|
1623
|
+
declare const defineMcpPrompt: <TCustom = any>(prompt: McpPromptDefinition<TCustom>) => McpPromptDefinition<TCustom>;
|
|
1186
1624
|
/** Configuration for {@link createMcpHandler}. */
|
|
1187
1625
|
interface CreateMcpHandlerConfig {
|
|
1188
1626
|
/**
|
|
@@ -1219,7 +1657,28 @@ interface CreateMcpHandlerConfig {
|
|
|
1219
1657
|
* built-in (your definition wins); duplicate custom names or invalid names
|
|
1220
1658
|
* throw at create time.
|
|
1221
1659
|
*/
|
|
1222
|
-
tools?:
|
|
1660
|
+
tools?: AnyMcpTool[];
|
|
1661
|
+
/**
|
|
1662
|
+
* App-defined resources (`resources/list` + `resources/read`). The
|
|
1663
|
+
* `resources` capability is advertised only when at least one resource,
|
|
1664
|
+
* template, or `builtinResources` is configured.
|
|
1665
|
+
*/
|
|
1666
|
+
resources?: McpResourceDefinition[];
|
|
1667
|
+
/** App-defined parameterized resources (`resources/templates/list`). */
|
|
1668
|
+
resourceTemplates?: McpResourceTemplateDefinition[];
|
|
1669
|
+
/**
|
|
1670
|
+
* Built-in BuildBase context resources (opt-in; requires `buildbase`):
|
|
1671
|
+
* `buildbase://profile`, `buildbase://workspaces`, and the
|
|
1672
|
+
* `buildbase://workspace/{workspaceId}` template — read-only context a host
|
|
1673
|
+
* can load without spending tool calls. Richer data (subscription, usage,
|
|
1674
|
+
* credits) stays tools-only.
|
|
1675
|
+
*/
|
|
1676
|
+
builtinResources?: boolean;
|
|
1677
|
+
/**
|
|
1678
|
+
* App-defined prompt templates (`prompts/list` + `prompts/get`). The
|
|
1679
|
+
* `prompts` capability is advertised only when at least one is configured.
|
|
1680
|
+
*/
|
|
1681
|
+
prompts?: McpPromptDefinition[];
|
|
1223
1682
|
/**
|
|
1224
1683
|
* Which built-in BuildBase tools to expose. **Defaults to `'readonly'`**
|
|
1225
1684
|
* when a `buildbase` client is configured (`false` otherwise) — reads only,
|
|
@@ -1240,6 +1699,15 @@ interface CreateMcpHandlerConfig {
|
|
|
1240
1699
|
* an Origin header (curl, server-to-server) always pass.
|
|
1241
1700
|
*/
|
|
1242
1701
|
allowedOrigins?: string[];
|
|
1702
|
+
/**
|
|
1703
|
+
* CORS for browser-based MCP clients. Default **true**: emit
|
|
1704
|
+
* `Access-Control-Allow-Origin: *` (safe for a Bearer-token API — no
|
|
1705
|
+
* cookies are ever involved), or reflect the matching origin when
|
|
1706
|
+
* `allowedOrigins` is set. Pass an origin array to allow only those, or
|
|
1707
|
+
* `false` to emit no CORS headers at all. Preflight (OPTIONS) is answered
|
|
1708
|
+
* automatically either way — no wrapper needed in your route.
|
|
1709
|
+
*/
|
|
1710
|
+
cors?: boolean | string[];
|
|
1243
1711
|
/**
|
|
1244
1712
|
* Hard cap on the raw request-body size in bytes (DoS protection). Bodies
|
|
1245
1713
|
* larger than this are rejected with 413 before parsing. Defaults to
|
|
@@ -1351,6 +1819,58 @@ declare class AppBridgeError extends Error {
|
|
|
1351
1819
|
readonly code: string;
|
|
1352
1820
|
constructor(code: string, message: string);
|
|
1353
1821
|
}
|
|
1822
|
+
/**
|
|
1823
|
+
* The user + grant context BuildBase sends to `applicationTokenUrl`. The app
|
|
1824
|
+
* mints a token for this user; `resource` is the RFC 8707 audience(s) the token
|
|
1825
|
+
* should be bound to (stamp them as `aud`), and `scope` is what the user granted.
|
|
1826
|
+
* Unknown claims are preserved for forward-compatibility.
|
|
1827
|
+
*/
|
|
1828
|
+
interface AppTokenRequestClaims {
|
|
1829
|
+
/** The user's id in the org. */
|
|
1830
|
+
id: string;
|
|
1831
|
+
email: string;
|
|
1832
|
+
name?: string;
|
|
1833
|
+
role?: string;
|
|
1834
|
+
emailVerified?: boolean;
|
|
1835
|
+
image?: string;
|
|
1836
|
+
blocked?: boolean;
|
|
1837
|
+
blockedReason?: string;
|
|
1838
|
+
blockedAt?: string;
|
|
1839
|
+
/** Which grant triggered this mint. */
|
|
1840
|
+
grantType?: 'authorization_code' | 'refresh_token';
|
|
1841
|
+
/** Scopes granted at authorization time. */
|
|
1842
|
+
scope?: string[];
|
|
1843
|
+
/** RFC 8707 resource indicator(s) — bind the minted token's `aud` to these. */
|
|
1844
|
+
resource?: string[];
|
|
1845
|
+
/** The OAuth2 client's display title. */
|
|
1846
|
+
clientTitle?: string;
|
|
1847
|
+
/**
|
|
1848
|
+
* Per-user BuildBase session bound to this grant. Embed it ENCRYPTED in the
|
|
1849
|
+
* token you mint (JWTs are signed, not encrypted) and never store it — your
|
|
1850
|
+
* MCP/agent endpoints decrypt it per request to call BuildBase as this user
|
|
1851
|
+
* (`buildbase.withSession(...)`). Fresh on every grant, including refresh.
|
|
1852
|
+
*/
|
|
1853
|
+
sessionId?: string;
|
|
1854
|
+
[claim: string]: unknown;
|
|
1855
|
+
}
|
|
1856
|
+
/**
|
|
1857
|
+
* A verified JWT payload: registered claims (RFC 7519) are typed AND
|
|
1858
|
+
* runtime-validated by {@link verifyClientJwt} (a signed token whose `sub` is
|
|
1859
|
+
* a number is rejected, so the types here are real guarantees). Every other
|
|
1860
|
+
* claim is `unknown` — custom claims are attacker-influenced input until you
|
|
1861
|
+
* narrow them (`typeof payload.sid === 'string'`), even after the signature
|
|
1862
|
+
* checks out.
|
|
1863
|
+
*/
|
|
1864
|
+
interface VerifiedJwtPayload {
|
|
1865
|
+
iss?: string;
|
|
1866
|
+
sub?: string;
|
|
1867
|
+
aud?: string | string[];
|
|
1868
|
+
exp?: number;
|
|
1869
|
+
nbf?: number;
|
|
1870
|
+
iat?: number;
|
|
1871
|
+
jti?: string;
|
|
1872
|
+
[claim: string]: unknown;
|
|
1873
|
+
}
|
|
1354
1874
|
/** Options for {@link verifyClientJwt} (all optional; secure defaults). */
|
|
1355
1875
|
interface VerifyClientJwtOptions {
|
|
1356
1876
|
/** Allowed clock skew in seconds for `exp`/`nbf`. Default 60. */
|
|
@@ -1371,11 +1891,8 @@ interface VerifyClientJwtOptions {
|
|
|
1371
1891
|
* its payload. Checks the signature (timing-safe), the algorithm, `exp`/`nbf`,
|
|
1372
1892
|
* and — by default — that an `exp` is present at all. Optionally pins `iss`/`aud`.
|
|
1373
1893
|
* Throws {@link AppBridgeError} on any failure.
|
|
1374
|
-
*
|
|
1375
|
-
* The third argument accepts either the legacy `clockToleranceSec` number or a
|
|
1376
|
-
* {@link VerifyClientJwtOptions} object.
|
|
1377
1894
|
*/
|
|
1378
|
-
declare function verifyClientJwt(token: string, clientSecret: string,
|
|
1895
|
+
declare function verifyClientJwt(token: string, clientSecret: string, options?: VerifyClientJwtOptions): VerifiedJwtPayload;
|
|
1379
1896
|
/** Extract the token from an `Authorization: Bearer <token>` header. */
|
|
1380
1897
|
declare function extractBearerToken(authorization: string | null | undefined): string | null;
|
|
1381
1898
|
/**
|
|
@@ -1398,5 +1915,252 @@ declare function bearerChallenge(options: {
|
|
|
1398
1915
|
body: string;
|
|
1399
1916
|
};
|
|
1400
1917
|
|
|
1401
|
-
|
|
1402
|
-
|
|
1918
|
+
/**
|
|
1919
|
+
* createAgentStack — the whole agent-readiness + MCP surface from ONE config.
|
|
1920
|
+
*
|
|
1921
|
+
* Everything the SDK can derive, it derives: the MCP endpoint, the server
|
|
1922
|
+
* card, the RFC 9728 protected-resource metadata, the API-catalog entry, the
|
|
1923
|
+
* BuildBase client, token verification (via `buildbaseAuth`), CORS, and the
|
|
1924
|
+
* discovery `Link` header — so a consumer configures identity once and wires
|
|
1925
|
+
* two routes. Every derived value stays overridable ("accelerate, never
|
|
1926
|
+
* gate").
|
|
1927
|
+
*
|
|
1928
|
+
* @example Next.js App Router — complete agent support:
|
|
1929
|
+
* ```ts
|
|
1930
|
+
* // lib/agent.ts
|
|
1931
|
+
* import { createAgentStack } from "@buildbase/sdk/mcp";
|
|
1932
|
+
* export const agent = createAgentStack({
|
|
1933
|
+
* serverUrl: process.env.NEXT_PUBLIC_BUILDBASE_SERVER_URL!,
|
|
1934
|
+
* orgId: process.env.NEXT_PUBLIC_BUILDBASE_ORG_ID!,
|
|
1935
|
+
* siteUrl: "https://app.example.com",
|
|
1936
|
+
* site: { name: "My App" },
|
|
1937
|
+
* secret: process.env.SYSTEM_SECRET!,
|
|
1938
|
+
* });
|
|
1939
|
+
*
|
|
1940
|
+
* // app/api/mcp/route.ts
|
|
1941
|
+
* import { agent } from "@/lib/agent";
|
|
1942
|
+
* export const { GET, POST, DELETE, OPTIONS } = agent.routes;
|
|
1943
|
+
*
|
|
1944
|
+
* // app/.well-known/[...path]/route.ts — and identical one-liners at
|
|
1945
|
+
* // app/robots.txt/route.ts, app/auth.md/route.ts, app/security.txt/route.ts
|
|
1946
|
+
* import { agent } from "@/lib/agent";
|
|
1947
|
+
* export const GET = agent.serveAgentPath;
|
|
1948
|
+
* ```
|
|
1949
|
+
*
|
|
1950
|
+
* @example Express / Hono / Bun — same stack, `handle`/`fetch` style:
|
|
1951
|
+
* ```ts
|
|
1952
|
+
* app.all("/api/mcp", async (req, res) => {
|
|
1953
|
+
* const r = await agent.mcp.handle({ method: req.method, headers: req.headers, body: req.body });
|
|
1954
|
+
* res.status(r.status).set(r.headers).send(r.body);
|
|
1955
|
+
* });
|
|
1956
|
+
* app.use(async (req, res, next) => {
|
|
1957
|
+
* const doc = await agent.resolvePath(req.path);
|
|
1958
|
+
* if (!doc) return next();
|
|
1959
|
+
* res.status(doc.status).set("Content-Type", doc.contentType).send(doc.body);
|
|
1960
|
+
* });
|
|
1961
|
+
* ```
|
|
1962
|
+
*/
|
|
1963
|
+
|
|
1964
|
+
/** Configuration for {@link createAgentStack}. */
|
|
1965
|
+
interface AgentStackConfig {
|
|
1966
|
+
/** BuildBase server base URL. */
|
|
1967
|
+
serverUrl: string;
|
|
1968
|
+
/** The org id. */
|
|
1969
|
+
orgId: string;
|
|
1970
|
+
/** This app's public origin, e.g. `https://app.example.com`. */
|
|
1971
|
+
siteUrl: string;
|
|
1972
|
+
/** Site identity for every discovery document. */
|
|
1973
|
+
site: AgentReadyConfig['site'];
|
|
1974
|
+
/**
|
|
1975
|
+
* The app's token-signing secret — wires `buildbaseAuth` (verify + audience
|
|
1976
|
+
* binding + `sid` decryption) automatically. Never sent anywhere. Omit only
|
|
1977
|
+
* when supplying `mcp.auth` yourself.
|
|
1978
|
+
*/
|
|
1979
|
+
secret?: string;
|
|
1980
|
+
/**
|
|
1981
|
+
* The app's OAuth scope catalog (see `AgentReadyConfig.scopes`) —
|
|
1982
|
+
* `scopes_supported` in the protected-resource metadata reads from it.
|
|
1983
|
+
*/
|
|
1984
|
+
scopes?: AppScope[];
|
|
1985
|
+
/** MCP server options. All optional — omit the whole block for defaults. */
|
|
1986
|
+
mcp?: {
|
|
1987
|
+
/** Endpoint path on `siteUrl`. Default `/api/mcp`. */
|
|
1988
|
+
path?: string;
|
|
1989
|
+
/** Advertised server identity. Defaults to the site name, v1.0.0. */
|
|
1990
|
+
serverInfo?: {
|
|
1991
|
+
name: string;
|
|
1992
|
+
version: string;
|
|
1993
|
+
};
|
|
1994
|
+
/** Your custom tools. */
|
|
1995
|
+
tools?: AnyMcpTool[];
|
|
1996
|
+
/** Built-in tool selection. Default `'readonly'`. */
|
|
1997
|
+
builtinTools?: CreateMcpHandlerConfig['builtinTools'];
|
|
1998
|
+
/** Scopes advertised on the protected-resource metadata. */
|
|
1999
|
+
scopes?: string[];
|
|
2000
|
+
/** Your own BuildBase client; auto-created from serverUrl/orgId if omitted. */
|
|
2001
|
+
buildbase?: McpBuildBaseClient;
|
|
2002
|
+
/** Override the derived auth (e.g. `false` for local dev). */
|
|
2003
|
+
auth?: CreateMcpHandlerConfig['auth'];
|
|
2004
|
+
/** Any remaining `createMcpHandler` option, merged last. */
|
|
2005
|
+
handler?: Partial<CreateMcpHandlerConfig>;
|
|
2006
|
+
};
|
|
2007
|
+
/**
|
|
2008
|
+
* Any {@link AgentReadyConfig} field (robots, skills, llms.txt, security,
|
|
2009
|
+
* a2aCard, extraPaths, …) — merged over the derived discovery config, so
|
|
2010
|
+
* every derived value can be replaced.
|
|
2011
|
+
*/
|
|
2012
|
+
discovery?: Partial<AgentReadyConfig>;
|
|
2013
|
+
}
|
|
2014
|
+
/** What {@link createAgentStack} returns. */
|
|
2015
|
+
interface AgentStack {
|
|
2016
|
+
/** The MCP handler (`handle`/`fetch`/`listTools`/`serverCard`). */
|
|
2017
|
+
mcp: McpHandler;
|
|
2018
|
+
/** Absolute MCP endpoint URL. */
|
|
2019
|
+
mcpEndpoint: string;
|
|
2020
|
+
/** The fully derived discovery config (inspect or reuse in middleware). */
|
|
2021
|
+
config: AgentReadyConfig;
|
|
2022
|
+
/** Discovery `Link` header value for your middleware / edge responses. */
|
|
2023
|
+
linkHeader: string;
|
|
2024
|
+
/** Resolve any agent-facing path to a document (framework-agnostic). */
|
|
2025
|
+
resolvePath(path: string): Promise<DiscoveryDocument | null>;
|
|
2026
|
+
/** Web-standard discovery route: hand it any `Request`, get a `Response`. */
|
|
2027
|
+
serveAgentPath(request: Request): Promise<Response>;
|
|
2028
|
+
/**
|
|
2029
|
+
* Web-standard MCP route handlers, ready to re-export from a route file:
|
|
2030
|
+
* `export const { GET, POST, DELETE, OPTIONS } = agent.routes`.
|
|
2031
|
+
*/
|
|
2032
|
+
routes: {
|
|
2033
|
+
GET: (request: Request) => Promise<Response>;
|
|
2034
|
+
POST: (request: Request) => Promise<Response>;
|
|
2035
|
+
DELETE: (request: Request) => Promise<Response>;
|
|
2036
|
+
OPTIONS: (request: Request) => Promise<Response>;
|
|
2037
|
+
};
|
|
2038
|
+
}
|
|
2039
|
+
/**
|
|
2040
|
+
* Build the complete agent stack — MCP server + discovery surface — from one
|
|
2041
|
+
* config object. See the module doc for full wiring examples.
|
|
2042
|
+
*/
|
|
2043
|
+
declare function createAgentStack(stack: AgentStackConfig): AgentStack;
|
|
2044
|
+
|
|
2045
|
+
/**
|
|
2046
|
+
* BuildBase agent-auth presets (server-side, framework-agnostic).
|
|
2047
|
+
*
|
|
2048
|
+
* The BuildBase security model: the platform runs the OAuth2 flow (login,
|
|
2049
|
+
* consent, PKCE, refresh) but the APP mints and verifies its own user tokens,
|
|
2050
|
+
* signed with the app's own secret. The platform only relays the minted token
|
|
2051
|
+
* to the agent — it never sees the secret, so it can neither forge nor decode
|
|
2052
|
+
* an app token. The per-user BuildBase session travels inside the token only
|
|
2053
|
+
* as an AES-256-GCM-encrypted `sid` claim, so it is never stored and never
|
|
2054
|
+
* plaintext anywhere; access to it expires with the token.
|
|
2055
|
+
*
|
|
2056
|
+
* These presets make that model a one-liner on each side of the flow, and run
|
|
2057
|
+
* entirely in the app's process — pure local crypto, zero platform calls:
|
|
2058
|
+
*
|
|
2059
|
+
* • {@link mintAgentToken} — inside your `applicationTokenUrl` handler:
|
|
2060
|
+
* signs the app JWT (HS256) with your secret, stamps `aud` from the RFC
|
|
2061
|
+
* 8707 resource, and embeds the encrypted `sid` automatically.
|
|
2062
|
+
* • {@link buildbaseAuth} — the `auth` config for `createMcpHandler`:
|
|
2063
|
+
* verifies the JWT, enforces audience binding, decrypts the `sid`, and
|
|
2064
|
+
* maps the claims to `McpAuthInfo`.
|
|
2065
|
+
*
|
|
2066
|
+
* @example The full loop:
|
|
2067
|
+
* ```ts
|
|
2068
|
+
* // applicationTokenUrl route — the platform calls this on every grant
|
|
2069
|
+
* const { status, body } = await handleAppTokenRequest({
|
|
2070
|
+
* authorization: req.headers.get("authorization"),
|
|
2071
|
+
* clientSecret: process.env.BUILDBASE_CLIENT_SECRET!,
|
|
2072
|
+
* mintToken: (claims) => mintAgentToken({ claims, secret: process.env.SYSTEM_SECRET! }),
|
|
2073
|
+
* });
|
|
2074
|
+
*
|
|
2075
|
+
* // MCP server — verifies what the route above minted
|
|
2076
|
+
* const mcp = createMcpHandler({
|
|
2077
|
+
* buildbase,
|
|
2078
|
+
* auth: buildbaseAuth({ secret: process.env.SYSTEM_SECRET!, resource: "https://app.example.com/api/mcp" }),
|
|
2079
|
+
* });
|
|
2080
|
+
* ```
|
|
2081
|
+
*
|
|
2082
|
+
* AES-GCM comes from WebCrypto (`globalThis.crypto.subtle`) — Node 18+, Bun,
|
|
2083
|
+
* Deno, edge runtimes, browsers. The wire format is
|
|
2084
|
+
* `base64url(iv(12) || authTag(16) || ciphertext)` with the key derived as
|
|
2085
|
+
* `SHA-256(secret + ":bb-session")`, byte-compatible with Node
|
|
2086
|
+
* `createCipheriv("aes-256-gcm", ...)` implementations of the same layout.
|
|
2087
|
+
*/
|
|
2088
|
+
|
|
2089
|
+
/** Encrypt/decrypt pair for the `sid` claim, bound to one app secret. */
|
|
2090
|
+
interface SessionRefCrypto {
|
|
2091
|
+
/** Encrypt a BuildBase session id for embedding in an app JWT. */
|
|
2092
|
+
encryptSessionRef(sessionId: string): Promise<string>;
|
|
2093
|
+
/** Decrypt a `sid` claim. Returns null on any failure (wrong key, garbage). */
|
|
2094
|
+
decryptSessionRef(ref: string): Promise<string | null>;
|
|
2095
|
+
}
|
|
2096
|
+
/**
|
|
2097
|
+
* Session-ref crypto derived from the app's secret. Both sides of the loop
|
|
2098
|
+
* ({@link mintAgentToken}, {@link buildbaseAuth}) use this internally — reach
|
|
2099
|
+
* for it directly only when minting or verifying tokens by hand.
|
|
2100
|
+
*/
|
|
2101
|
+
declare function createSessionRefCrypto(secret: string): SessionRefCrypto;
|
|
2102
|
+
/** Options for {@link mintAgentToken}. */
|
|
2103
|
+
interface MintAgentTokenOptions {
|
|
2104
|
+
/** The verified platform claims (from `handleAppTokenRequest`'s callback). */
|
|
2105
|
+
claims: AppTokenRequestClaims;
|
|
2106
|
+
/** The APP's token-signing secret. Never leaves this process. */
|
|
2107
|
+
secret: string;
|
|
2108
|
+
/** Token lifetime in seconds. Default 3600 — keep agent tokens short-lived. */
|
|
2109
|
+
expiresInSec?: number;
|
|
2110
|
+
/**
|
|
2111
|
+
* App-specific claims merged into the token — e.g. a `workspaceId` resolved
|
|
2112
|
+
* by your own user sync. Merged last, so they can override the defaults.
|
|
2113
|
+
*/
|
|
2114
|
+
extraClaims?: Record<string, unknown>;
|
|
2115
|
+
}
|
|
2116
|
+
/**
|
|
2117
|
+
* Mint the app's agent access token from a platform grant: HS256-signed with
|
|
2118
|
+
* YOUR secret, `aud` bound to the granted RFC 8707 resource(s), scopes carried
|
|
2119
|
+
* through, and the per-user BuildBase session embedded as an encrypted `sid`
|
|
2120
|
+
* claim. The result plugs straight into `handleAppTokenRequest`'s `mintToken`.
|
|
2121
|
+
*/
|
|
2122
|
+
declare function mintAgentToken(options: MintAgentTokenOptions): Promise<{
|
|
2123
|
+
token: string;
|
|
2124
|
+
expiresIn: number;
|
|
2125
|
+
}>;
|
|
2126
|
+
/** Options for {@link buildbaseAuth}. */
|
|
2127
|
+
interface BuildBaseAuthOptions {
|
|
2128
|
+
/** The APP's token-signing secret — the same one `mintAgentToken` used. */
|
|
2129
|
+
secret: string;
|
|
2130
|
+
/**
|
|
2131
|
+
* The protected resource(s) this server IS. Enforces RFC 8707 audience
|
|
2132
|
+
* binding — the token's `aud` must include one of these URIs. Pass an array
|
|
2133
|
+
* when the server is addressable under more than one resource identifier
|
|
2134
|
+
* (e.g. the canonical `<host>/mcp` plus the literal endpoint URL); the
|
|
2135
|
+
* FIRST entry is the canonical one used to derive `resourceMetadataUrl`.
|
|
2136
|
+
*/
|
|
2137
|
+
resource?: string | string[];
|
|
2138
|
+
/**
|
|
2139
|
+
* Explicit RFC 9728 metadata URL for the 401 challenge. Defaults to the
|
|
2140
|
+
* path-derived `/.well-known/oauth-protected-resource<path>` of the first
|
|
2141
|
+
* `resource`.
|
|
2142
|
+
*/
|
|
2143
|
+
resourceMetadataUrl?: string;
|
|
2144
|
+
/**
|
|
2145
|
+
* Reject tokens that carry no `aud` claim at all. Default false: audience is
|
|
2146
|
+
* enforced when present, and legacy audience-less tokens still work. Turn
|
|
2147
|
+
* this on once every minted token is audience-bound.
|
|
2148
|
+
*/
|
|
2149
|
+
requireAudience?: boolean;
|
|
2150
|
+
/** Extra JWT verification options (clock tolerance, issuer pinning). */
|
|
2151
|
+
verify?: Pick<VerifyClientJwtOptions, 'clockToleranceSec' | 'issuer'>;
|
|
2152
|
+
}
|
|
2153
|
+
/**
|
|
2154
|
+
* The `auth` config for `createMcpHandler`, prewired for BuildBase-minted app
|
|
2155
|
+
* tokens: HS256 verification with your secret, RFC 8707 audience binding,
|
|
2156
|
+
* `sid` decryption to the BuildBase session, claim mapping to `McpAuthInfo`,
|
|
2157
|
+
* and the derived RFC 9728 `resourceMetadataUrl`. Entirely local — the token
|
|
2158
|
+
* and secret never leave this process.
|
|
2159
|
+
*/
|
|
2160
|
+
declare function buildbaseAuth(options: BuildBaseAuthOptions): {
|
|
2161
|
+
verify: (token: string, req: McpHttpRequest) => Promise<McpAuthInfo | null>;
|
|
2162
|
+
resourceMetadataUrl?: string;
|
|
2163
|
+
};
|
|
2164
|
+
|
|
2165
|
+
export { AppBridgeError, bearerChallenge, buildbaseAuth, builtinMcpTools, createAgentStack, createMcpHandler, createSessionRefCrypto, defineMcpPrompt, defineMcpResource, defineMcpResourceTemplate, defineMcpTool, extractBearerToken, mcpAudio, mcpEmbeddedResource, mcpImage, mcpResourceLink, mcpText, mintAgentToken, selectBuiltinTools, signClientJwt, verifyClientJwt };
|
|
2166
|
+
export type { AgentStack, AgentStackConfig, AnyMcpTool, BuildBaseAuthOptions, BuiltinMcpToolName, CreateMcpHandlerConfig, McpAudioContent, McpAuthInfo, McpBuildBaseClient, McpContentBlock, McpEmbeddedResourceContent, McpHandler, McpHttpRequest, McpHttpResponse, McpIcon, McpImageContent, McpPromptContent, McpPromptDefinition, McpPromptMessage, McpResourceDefinition, McpResourceLinkContent, McpResourceReadResult, McpResourceTemplateDefinition, McpServerCard, McpTextContent, McpToolAnnotations, McpToolContext, McpToolDefinition, McpToolResult, MintAgentTokenOptions, ScopedActions, SessionRefCrypto, VerifiedJwtPayload };
|