@01.software/cli 0.8.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,18 +1,23 @@
1
1
  // src/handler.ts
2
2
  import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
3
- import {
4
- MCP_OAUTH_ISSUER as MCP_OAUTH_ISSUER3,
5
- MCP_PROTECTED_RESOURCE_METADATA_PATH,
6
- MCP_RESOURCE_AUDIENCE as MCP_RESOURCE_AUDIENCE2,
7
- MCP_SCOPES as MCP_SCOPES2
8
- } from "@01.software/auth-contracts";
3
+
4
+ // ../../packages/auth-contracts/dist/index.js
5
+ var MCP_RESOURCE_AUDIENCE = "https://mcp.01.software/mcp";
6
+ var MCP_OAUTH_ISSUER = "https://01.software";
7
+ var MCP_PROTECTED_RESOURCE_METADATA_PATH = "/.well-known/oauth-protected-resource/mcp";
8
+ var MCP_TENANT_CLAIM = "tenant_id";
9
+ var MCP_TENANT_ROLE_CLAIM = "tenant_role";
10
+ var MCP_SCOPES = {
11
+ read: "mcp:read",
12
+ write: "mcp:write"
13
+ };
14
+ var MCP_CONSOLE_SERVICE_AUDIENCE = "https://api.01.software/internal/mcp";
15
+ var MCP_CONSOLE_SERVICE_SCOPE = "console:mcp_proxy";
16
+ var MCP_SERVICE_TOKEN_LIFETIME_SECONDS = 60;
9
17
 
10
18
  // src/server.ts
11
19
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
12
20
 
13
- // src/tools/query-collection.ts
14
- import { z } from "zod";
15
-
16
21
  // src/lib/request-context.ts
17
22
  import { AsyncLocalStorage } from "async_hooks";
18
23
  var requestContext = new AsyncLocalStorage();
@@ -23,25 +28,631 @@ function hasRequestContext() {
23
28
  return requestContext.getStore() !== void 0;
24
29
  }
25
30
 
26
- // src/lib/client.ts
27
- import {
28
- CollectionClient,
29
- CommunityClient,
30
- ModerationApi,
31
- ServerCommerceClient,
32
- createServerClient
33
- } from "@01.software/sdk";
31
+ // src/lib/tool-utils.ts
32
+ function toolSuccess(data) {
33
+ return JSON.stringify({ success: true, ...data }, null, 2);
34
+ }
35
+ function toolError(error) {
36
+ const base = { success: false };
37
+ const isStructured = !!error && typeof error === "object" && ("code" in error || "reason" in error);
38
+ if (isStructured) {
39
+ const sdkErr = error;
40
+ base.error = sdkErr.message || "Unknown error";
41
+ if (sdkErr.status) base.status = sdkErr.status;
42
+ if (sdkErr.code) base.code = sdkErr.code;
43
+ if (sdkErr.reason) base.reason = sdkErr.reason;
44
+ if (sdkErr.requestId) base.requestId = sdkErr.requestId;
45
+ if (sdkErr.suggestion) base.suggestion = sdkErr.suggestion;
46
+ if (sdkErr.details?.errors) base.errors = sdkErr.details.errors;
47
+ } else {
48
+ base.error = error instanceof Error ? error.message : "Unknown error";
49
+ }
50
+ return JSON.stringify(base, null, 2);
51
+ }
52
+ var MAX_QUERY_DEPTH = 5;
53
+ function checkDepth(obj, depth = 0) {
54
+ if (depth > MAX_QUERY_DEPTH) return false;
55
+ if (obj && typeof obj === "object") {
56
+ for (const val of Object.values(obj)) {
57
+ if (!checkDepth(val, depth + 1)) return false;
58
+ }
59
+ }
60
+ return true;
61
+ }
62
+ function parseJsonWhere(where) {
63
+ try {
64
+ const parsed = JSON.parse(where);
65
+ if (!checkDepth(parsed)) {
66
+ return {
67
+ success: false,
68
+ error: JSON.stringify(
69
+ {
70
+ success: false,
71
+ error: `Query exceeds maximum nesting depth of ${MAX_QUERY_DEPTH}`
72
+ },
73
+ null,
74
+ 2
75
+ )
76
+ };
77
+ }
78
+ return { success: true, data: parsed };
79
+ } catch {
80
+ return {
81
+ success: false,
82
+ error: JSON.stringify(
83
+ {
84
+ success: false,
85
+ error: `Invalid JSON in "where" parameter: ${where.length > 100 ? where.substring(0, 100) + "..." : where}`
86
+ },
87
+ null,
88
+ 2
89
+ )
90
+ };
91
+ }
92
+ }
93
+
94
+ // ../../packages/contracts/src/tenant/index.ts
95
+ import { z } from "zod";
96
+ var tenantFieldConfigStateSchema = z.object({
97
+ hiddenFields: z.array(z.string()),
98
+ isHidden: z.boolean()
99
+ }).strict();
100
+ var tenantContextQuerySchema = z.object({
101
+ counts: z.literal("true").optional()
102
+ }).strict();
103
+ var tenantContextToolInputSchema = z.object({
104
+ includeCounts: z.boolean().optional().default(false).describe(
105
+ "Include per-collection document counts and config status (bypasses cache, slower)"
106
+ )
107
+ }).strict();
108
+ var tenantContextResponseSchema = z.object({
109
+ tenant: z.object({
110
+ id: z.string(),
111
+ name: z.string(),
112
+ plan: z.string(),
113
+ planSource: z.string().optional(),
114
+ authoritative: z.boolean().optional(),
115
+ capabilityVersion: z.string().optional()
116
+ }).strict(),
117
+ features: z.array(z.string()),
118
+ collections: z.object({
119
+ active: z.array(z.string()),
120
+ inactive: z.array(z.string())
121
+ }).strict(),
122
+ fieldConfigs: z.record(z.string(), tenantFieldConfigStateSchema),
123
+ counts: z.record(z.string(), z.number()).optional(),
124
+ config: z.object({
125
+ webhookConfigured: z.boolean()
126
+ }).strict().optional()
127
+ }).strict();
128
+ var COLLECTION_SCHEMA_CONTRACT_VERSION = 1;
129
+ var collectionSchemaEndpointParamsSchema = z.object({
130
+ collectionSlug: z.string().min(1, "collectionSlug is required")
131
+ }).strict();
132
+ function createCollectionSchemaToolInputSchema(collections) {
133
+ return z.object({
134
+ collection: z.enum(collections).describe("Collection name (required)")
135
+ }).strict();
136
+ }
137
+ var collectionFieldOptionSchema = z.object({
138
+ label: z.string(),
139
+ value: z.string()
140
+ }).strict();
141
+ var collectionFieldSchema = z.lazy(
142
+ () => z.object({
143
+ name: z.string(),
144
+ path: z.string(),
145
+ type: z.string(),
146
+ required: z.literal(true).optional(),
147
+ unique: z.literal(true).optional(),
148
+ hasMany: z.literal(true).optional(),
149
+ relationTo: z.union([z.string(), z.array(z.string())]).optional(),
150
+ options: z.array(collectionFieldOptionSchema).optional(),
151
+ hidden: z.literal(true).optional(),
152
+ systemManaged: z.literal(true).optional(),
153
+ writable: z.boolean().optional(),
154
+ fields: z.array(collectionFieldSchema).optional()
155
+ }).strict()
156
+ );
157
+ var collectionSchemaResponseSchema = z.object({
158
+ contractVersion: z.literal(COLLECTION_SCHEMA_CONTRACT_VERSION),
159
+ mode: z.literal("effective"),
160
+ collection: z.object({
161
+ slug: z.string(),
162
+ timestamps: z.boolean(),
163
+ alwaysActive: z.boolean(),
164
+ feature: z.string().nullable(),
165
+ systemFields: z.array(z.string()),
166
+ visibility: z.object({
167
+ collectionHidden: z.boolean(),
168
+ hiddenFields: z.array(z.string())
169
+ }).strict(),
170
+ fields: z.array(collectionFieldSchema)
171
+ }).strict()
172
+ }).strict();
173
+
174
+ // ../../packages/contracts/src/ecommerce/index.ts
175
+ import { z as z2 } from "zod";
176
+ var transactionStatusSchema = z2.enum([
177
+ "pending",
178
+ "paid",
179
+ "failed",
180
+ "canceled"
181
+ ]);
182
+ var updateTransactionSchema = z2.object({
183
+ pgPaymentId: z2.string().min(1, "pgPaymentId is required").describe("PG payment ID (required)"),
184
+ status: transactionStatusSchema.describe(
185
+ "New transaction status (required)"
186
+ ),
187
+ paymentMethod: z2.string().optional().describe("Payment method (optional)"),
188
+ receiptUrl: z2.string().optional().describe("Receipt URL (optional)"),
189
+ paymentKey: z2.string().min(1).optional().describe("Provider payment key for verified paid confirmation"),
190
+ amount: z2.number().int().positive().optional().describe("Provider-confirmed amount for verified paid confirmation")
191
+ }).strict();
192
+ var UpdateTransactionSchema = updateTransactionSchema;
193
+ var returnReasonSchema = z2.enum([
194
+ "change_of_mind",
195
+ "defective",
196
+ "wrong_delivery",
197
+ "damaged",
198
+ "other"
199
+ ]);
200
+ var restockActionSchema = z2.enum(["return_to_stock", "discard"]);
201
+ var returnWithRefundItemSchema = z2.object({
202
+ orderItem: z2.union([z2.string(), z2.number()]).transform(String),
203
+ quantity: z2.number().int().positive("quantity must be a positive integer"),
204
+ restockAction: restockActionSchema.default("return_to_stock")
205
+ }).strict();
206
+ var returnWithRefundSchema = z2.object({
207
+ orderNumber: z2.string().min(1, "orderNumber is required").describe("Order number (required)"),
208
+ reason: returnReasonSchema.optional().describe("Return reason (optional)"),
209
+ reasonDetail: z2.string().optional().describe("Detailed reason text (optional)"),
210
+ returnItems: z2.array(returnWithRefundItemSchema).min(1, "At least one return item is required").max(100, "Too many return items").describe("Array of products to return (required)"),
211
+ refundAmount: z2.number().min(0, "refundAmount must be non-negative").describe("Refund amount (required, min 0)"),
212
+ pgPaymentId: z2.string().min(1, "pgPaymentId is required").describe("PG payment ID for refund (required)"),
213
+ paymentKey: z2.string().min(1).optional().describe("Provider payment key for verified refund"),
214
+ refundReceiptUrl: z2.string().optional().describe("Refund receipt URL (optional)")
215
+ }).strict();
216
+ var ReturnWithRefundSchema = returnWithRefundSchema;
217
+
218
+ // ../../packages/contracts/src/mcp/index.ts
219
+ var MCP_TOOL_CONTRACT = {
220
+ "query-collection": {
221
+ consoleRole: "tenant-viewer",
222
+ oauthScope: "mcp:read",
223
+ readOnly: true
224
+ },
225
+ "get-collection-by-id": {
226
+ consoleRole: "tenant-viewer",
227
+ oauthScope: "mcp:read",
228
+ readOnly: true
229
+ },
230
+ "get-order": {
231
+ consoleRole: "tenant-viewer",
232
+ oauthScope: "mcp:read",
233
+ readOnly: true
234
+ },
235
+ "stock-check": {
236
+ consoleRole: "tenant-viewer",
237
+ oauthScope: "mcp:read",
238
+ readOnly: true
239
+ },
240
+ "validate-discount": {
241
+ consoleRole: "tenant-viewer",
242
+ oauthScope: "mcp:read",
243
+ readOnly: true
244
+ },
245
+ "calculate-shipping": {
246
+ consoleRole: "tenant-viewer",
247
+ oauthScope: "mcp:read",
248
+ readOnly: true
249
+ },
250
+ "get-collection-schema": {
251
+ consoleRole: "tenant-viewer",
252
+ oauthScope: "mcp:read",
253
+ readOnly: true
254
+ },
255
+ "list-configurable-fields": {
256
+ consoleRole: "tenant-viewer",
257
+ oauthScope: "mcp:read",
258
+ readOnly: true
259
+ },
260
+ "get-tenant-context": {
261
+ consoleRole: "tenant-viewer",
262
+ oauthScope: "mcp:read",
263
+ readOnly: true
264
+ },
265
+ "add-cart-item": {
266
+ consoleRole: "tenant-editor",
267
+ oauthScope: "mcp:write",
268
+ readOnly: false
269
+ },
270
+ "update-cart-item": {
271
+ consoleRole: "tenant-editor",
272
+ oauthScope: "mcp:write",
273
+ readOnly: false
274
+ },
275
+ "remove-cart-item": {
276
+ consoleRole: "tenant-editor",
277
+ oauthScope: "mcp:write",
278
+ readOnly: false
279
+ },
280
+ "clear-cart": {
281
+ consoleRole: "tenant-editor",
282
+ oauthScope: "mcp:write",
283
+ readOnly: false
284
+ },
285
+ "apply-discount": {
286
+ consoleRole: "tenant-editor",
287
+ oauthScope: "mcp:write",
288
+ readOnly: false
289
+ },
290
+ "remove-discount": {
291
+ consoleRole: "tenant-editor",
292
+ oauthScope: "mcp:write",
293
+ readOnly: false
294
+ },
295
+ checkout: {
296
+ consoleRole: "tenant-admin",
297
+ oauthScope: "mcp:write",
298
+ readOnly: false
299
+ },
300
+ "create-order": {
301
+ consoleRole: "tenant-admin",
302
+ oauthScope: "mcp:write",
303
+ readOnly: false
304
+ },
305
+ "update-order": {
306
+ consoleRole: "tenant-admin",
307
+ oauthScope: "mcp:write",
308
+ readOnly: false
309
+ },
310
+ "create-fulfillment": {
311
+ consoleRole: "tenant-admin",
312
+ oauthScope: "mcp:write",
313
+ readOnly: false
314
+ },
315
+ "update-fulfillment": {
316
+ consoleRole: "tenant-admin",
317
+ oauthScope: "mcp:write",
318
+ readOnly: false
319
+ },
320
+ "create-return": {
321
+ consoleRole: "tenant-admin",
322
+ oauthScope: "mcp:write",
323
+ readOnly: false
324
+ },
325
+ "update-return": {
326
+ consoleRole: "tenant-admin",
327
+ oauthScope: "mcp:write",
328
+ readOnly: false
329
+ },
330
+ "return-with-refund": {
331
+ consoleRole: "tenant-admin",
332
+ oauthScope: "mcp:write",
333
+ readOnly: false
334
+ },
335
+ "update-transaction": {
336
+ consoleRole: "tenant-admin",
337
+ oauthScope: "mcp:write",
338
+ readOnly: false
339
+ },
340
+ "update-field-config": {
341
+ consoleRole: "tenant-admin",
342
+ oauthScope: "mcp:write",
343
+ readOnly: false
344
+ },
345
+ "sdk-get-recipe": {
346
+ consoleRole: "tenant-viewer",
347
+ oauthScope: "mcp:read",
348
+ readOnly: true
349
+ },
350
+ "sdk-search-docs": {
351
+ consoleRole: "tenant-viewer",
352
+ oauthScope: "mcp:read",
353
+ readOnly: true
354
+ },
355
+ "sdk-get-auth-setup": {
356
+ consoleRole: "tenant-viewer",
357
+ oauthScope: "mcp:read",
358
+ readOnly: true
359
+ },
360
+ "sdk-get-collection-pattern": {
361
+ consoleRole: "tenant-viewer",
362
+ oauthScope: "mcp:read",
363
+ readOnly: true
364
+ }
365
+ };
366
+ var MCP_TOOL_NAMES = Object.keys(
367
+ MCP_TOOL_CONTRACT
368
+ );
369
+ function isMcpToolName(toolName) {
370
+ return Object.prototype.hasOwnProperty.call(MCP_TOOL_CONTRACT, toolName);
371
+ }
372
+
373
+ // src/tool-policy.ts
374
+ var READ_ONLY_ANNOTATION = {
375
+ readOnly: true,
376
+ destructive: false,
377
+ idempotent: true,
378
+ openWorld: false
379
+ };
380
+ var NON_DESTRUCTIVE_MUTATION_ANNOTATION = {
381
+ readOnly: false,
382
+ destructive: false,
383
+ idempotent: false,
384
+ openWorld: false
385
+ };
386
+ var NON_DESTRUCTIVE_IDEMPOTENT_MUTATION_ANNOTATION = {
387
+ readOnly: false,
388
+ destructive: false,
389
+ idempotent: true,
390
+ openWorld: false
391
+ };
392
+ var DESTRUCTIVE_NON_IDEMPOTENT_MUTATION_ANNOTATION = {
393
+ readOnly: false,
394
+ destructive: true,
395
+ idempotent: false,
396
+ openWorld: false
397
+ };
398
+ var DESTRUCTIVE_IDEMPOTENT_MUTATION_ANNOTATION = {
399
+ readOnly: false,
400
+ destructive: true,
401
+ idempotent: true,
402
+ openWorld: false
403
+ };
404
+ var REASON_IDEMPOTENT_DESTRUCTIVE_UPDATE = "Update operations mutate persisted state but converge to the same end state under repeated identical input.";
405
+ var REASON_CART_EPHEMERAL = "Cart is pre-checkout ephemeral state; reversal is possible by reissuing the prior input. Console enforces tenant scope.";
406
+ var TOOL_POLICY_MANIFEST = {
407
+ // ── Read-only collection / validation (mcp:read, tenant-viewer) ──
408
+ "query-collection": {
409
+ category: "read-only-collection",
410
+ oauthScope: MCP_SCOPES.read,
411
+ consoleRole: "tenant-viewer",
412
+ consoleSurface: "GET /api/{collection}",
413
+ annotationPolicy: READ_ONLY_ANNOTATION
414
+ },
415
+ "get-collection-by-id": {
416
+ category: "read-only-collection",
417
+ oauthScope: MCP_SCOPES.read,
418
+ consoleRole: "tenant-viewer",
419
+ consoleSurface: "GET /api/{collection}/{id}",
420
+ annotationPolicy: READ_ONLY_ANNOTATION
421
+ },
422
+ "get-order": {
423
+ category: "read-only-collection",
424
+ oauthScope: MCP_SCOPES.read,
425
+ consoleRole: "tenant-viewer",
426
+ consoleSurface: "GET /api/orders/{id}",
427
+ annotationPolicy: READ_ONLY_ANNOTATION
428
+ },
429
+ "stock-check": {
430
+ category: "read-only-collection",
431
+ oauthScope: MCP_SCOPES.read,
432
+ consoleRole: "tenant-viewer",
433
+ consoleSurface: "GET /api/products/{id}/stock",
434
+ annotationPolicy: READ_ONLY_ANNOTATION
435
+ },
436
+ "validate-discount": {
437
+ category: "read-only-collection",
438
+ oauthScope: MCP_SCOPES.read,
439
+ consoleRole: "tenant-viewer",
440
+ consoleSurface: "POST /api/discounts/validate",
441
+ annotationPolicy: READ_ONLY_ANNOTATION
442
+ },
443
+ "calculate-shipping": {
444
+ category: "read-only-collection",
445
+ oauthScope: MCP_SCOPES.read,
446
+ consoleRole: "tenant-viewer",
447
+ consoleSurface: "POST /api/shipping/calculate",
448
+ annotationPolicy: READ_ONLY_ANNOTATION
449
+ },
450
+ "get-collection-schema": {
451
+ category: "read-only-collection",
452
+ oauthScope: MCP_SCOPES.read,
453
+ consoleRole: "tenant-viewer",
454
+ consoleSurface: "GET /api/tenants/schema/{collectionSlug}",
455
+ annotationPolicy: READ_ONLY_ANNOTATION
456
+ },
457
+ "list-configurable-fields": {
458
+ category: "read-only-collection",
459
+ oauthScope: MCP_SCOPES.read,
460
+ consoleRole: "tenant-viewer",
461
+ consoleSurface: "GET /api/tenants/field-config",
462
+ annotationPolicy: READ_ONLY_ANNOTATION
463
+ },
464
+ // ── Tenant context (mcp:read, tenant-viewer) ──
465
+ "get-tenant-context": {
466
+ category: "read-only-tenant",
467
+ oauthScope: MCP_SCOPES.read,
468
+ consoleRole: "tenant-viewer",
469
+ consoleSurface: "GET /api/tenants/context",
470
+ annotationPolicy: READ_ONLY_ANNOTATION
471
+ },
472
+ // ── Cart mutations (mcp:write, tenant-editor) ──
473
+ "add-cart-item": {
474
+ category: "mutation-cart",
475
+ oauthScope: MCP_SCOPES.write,
476
+ consoleRole: "tenant-editor",
477
+ consoleSurface: "POST /api/carts/{id}/items",
478
+ annotationPolicy: NON_DESTRUCTIVE_IDEMPOTENT_MUTATION_ANNOTATION
479
+ },
480
+ "update-cart-item": {
481
+ category: "mutation-cart",
482
+ oauthScope: MCP_SCOPES.write,
483
+ consoleRole: "tenant-editor",
484
+ consoleSurface: "PATCH /api/carts/{id}/items/{itemId}",
485
+ annotationPolicy: DESTRUCTIVE_IDEMPOTENT_MUTATION_ANNOTATION,
486
+ exemptionReason: REASON_CART_EPHEMERAL
487
+ },
488
+ "remove-cart-item": {
489
+ category: "mutation-cart",
490
+ oauthScope: MCP_SCOPES.write,
491
+ consoleRole: "tenant-editor",
492
+ consoleSurface: "DELETE /api/carts/{id}/items/{itemId}",
493
+ annotationPolicy: DESTRUCTIVE_IDEMPOTENT_MUTATION_ANNOTATION,
494
+ exemptionReason: REASON_CART_EPHEMERAL
495
+ },
496
+ "clear-cart": {
497
+ category: "mutation-cart",
498
+ oauthScope: MCP_SCOPES.write,
499
+ consoleRole: "tenant-editor",
500
+ consoleSurface: "POST /api/carts/{id}/clear",
501
+ annotationPolicy: DESTRUCTIVE_IDEMPOTENT_MUTATION_ANNOTATION,
502
+ exemptionReason: REASON_CART_EPHEMERAL
503
+ },
504
+ "apply-discount": {
505
+ category: "mutation-cart",
506
+ oauthScope: MCP_SCOPES.write,
507
+ consoleRole: "tenant-editor",
508
+ consoleSurface: "POST /api/carts/{id}/discount",
509
+ annotationPolicy: DESTRUCTIVE_IDEMPOTENT_MUTATION_ANNOTATION,
510
+ exemptionReason: REASON_CART_EPHEMERAL
511
+ },
512
+ "remove-discount": {
513
+ category: "mutation-cart",
514
+ oauthScope: MCP_SCOPES.write,
515
+ consoleRole: "tenant-editor",
516
+ consoleSurface: "DELETE /api/carts/{id}/discount",
517
+ annotationPolicy: DESTRUCTIVE_IDEMPOTENT_MUTATION_ANNOTATION,
518
+ exemptionReason: REASON_CART_EPHEMERAL
519
+ },
520
+ // ── Order mutations (mcp:write, tenant-admin) ──
521
+ "checkout": {
522
+ category: "mutation-order",
523
+ oauthScope: MCP_SCOPES.write,
524
+ consoleRole: "tenant-admin",
525
+ consoleSurface: "POST /api/checkout",
526
+ annotationPolicy: DESTRUCTIVE_NON_IDEMPOTENT_MUTATION_ANNOTATION
527
+ },
528
+ "create-order": {
529
+ category: "mutation-order",
530
+ oauthScope: MCP_SCOPES.write,
531
+ consoleRole: "tenant-admin",
532
+ consoleSurface: "POST /api/orders",
533
+ annotationPolicy: DESTRUCTIVE_NON_IDEMPOTENT_MUTATION_ANNOTATION
534
+ },
535
+ "update-order": {
536
+ category: "mutation-order",
537
+ oauthScope: MCP_SCOPES.write,
538
+ consoleRole: "tenant-admin",
539
+ consoleSurface: "PATCH /api/orders/{id}",
540
+ annotationPolicy: DESTRUCTIVE_IDEMPOTENT_MUTATION_ANNOTATION,
541
+ exemptionReason: REASON_IDEMPOTENT_DESTRUCTIVE_UPDATE
542
+ },
543
+ // ── Fulfillment mutations (mcp:write, tenant-admin) ──
544
+ "create-fulfillment": {
545
+ category: "mutation-fulfillment",
546
+ oauthScope: MCP_SCOPES.write,
547
+ consoleRole: "tenant-admin",
548
+ consoleSurface: "POST /api/orders/{id}/fulfillments",
549
+ annotationPolicy: NON_DESTRUCTIVE_MUTATION_ANNOTATION
550
+ },
551
+ "update-fulfillment": {
552
+ category: "mutation-fulfillment",
553
+ oauthScope: MCP_SCOPES.write,
554
+ consoleRole: "tenant-admin",
555
+ consoleSurface: "PATCH /api/fulfillments/{id}",
556
+ annotationPolicy: DESTRUCTIVE_IDEMPOTENT_MUTATION_ANNOTATION,
557
+ exemptionReason: REASON_IDEMPOTENT_DESTRUCTIVE_UPDATE
558
+ },
559
+ // ── Return mutations (mcp:write, tenant-admin) ──
560
+ "create-return": {
561
+ category: "mutation-return",
562
+ oauthScope: MCP_SCOPES.write,
563
+ consoleRole: "tenant-admin",
564
+ consoleSurface: "POST /api/returns",
565
+ annotationPolicy: DESTRUCTIVE_NON_IDEMPOTENT_MUTATION_ANNOTATION
566
+ },
567
+ "update-return": {
568
+ category: "mutation-return",
569
+ oauthScope: MCP_SCOPES.write,
570
+ consoleRole: "tenant-admin",
571
+ consoleSurface: "PATCH /api/returns/{id}",
572
+ annotationPolicy: DESTRUCTIVE_IDEMPOTENT_MUTATION_ANNOTATION,
573
+ exemptionReason: REASON_IDEMPOTENT_DESTRUCTIVE_UPDATE
574
+ },
575
+ "return-with-refund": {
576
+ category: "mutation-return",
577
+ oauthScope: MCP_SCOPES.write,
578
+ consoleRole: "tenant-admin",
579
+ consoleSurface: "POST /api/returns/with-refund",
580
+ annotationPolicy: DESTRUCTIVE_NON_IDEMPOTENT_MUTATION_ANNOTATION
581
+ },
582
+ // ── Transaction mutations (mcp:write, tenant-admin) ──
583
+ "update-transaction": {
584
+ category: "mutation-transaction",
585
+ oauthScope: MCP_SCOPES.write,
586
+ consoleRole: "tenant-admin",
587
+ consoleSurface: "PATCH /api/transactions/{id}",
588
+ annotationPolicy: DESTRUCTIVE_NON_IDEMPOTENT_MUTATION_ANNOTATION
589
+ },
590
+ // ── Field-config mutations (mcp:write, tenant-admin) ──
591
+ "update-field-config": {
592
+ category: "mutation-field-config",
593
+ oauthScope: MCP_SCOPES.write,
594
+ consoleRole: "tenant-admin",
595
+ consoleSurface: "PATCH /api/tenants/field-config",
596
+ annotationPolicy: NON_DESTRUCTIVE_IDEMPOTENT_MUTATION_ANNOTATION
597
+ },
598
+ // ── SDK doc tools (mcp:read, tenant-viewer, sdk-static surface) ──
599
+ "sdk-get-recipe": {
600
+ category: "sdk-doc",
601
+ oauthScope: MCP_SCOPES.read,
602
+ consoleRole: "tenant-viewer",
603
+ consoleSurface: "sdk-static",
604
+ annotationPolicy: READ_ONLY_ANNOTATION
605
+ },
606
+ "sdk-search-docs": {
607
+ category: "sdk-doc",
608
+ oauthScope: MCP_SCOPES.read,
609
+ consoleRole: "tenant-viewer",
610
+ consoleSurface: "sdk-static",
611
+ annotationPolicy: READ_ONLY_ANNOTATION
612
+ },
613
+ "sdk-get-auth-setup": {
614
+ category: "sdk-doc",
615
+ oauthScope: MCP_SCOPES.read,
616
+ consoleRole: "tenant-viewer",
617
+ consoleSurface: "sdk-static",
618
+ annotationPolicy: READ_ONLY_ANNOTATION
619
+ },
620
+ "sdk-get-collection-pattern": {
621
+ category: "sdk-doc",
622
+ oauthScope: MCP_SCOPES.read,
623
+ consoleRole: "tenant-viewer",
624
+ consoleSurface: "sdk-static",
625
+ annotationPolicy: READ_ONLY_ANNOTATION
626
+ }
627
+ };
628
+ function evaluateToolPolicy(toolName, scopes) {
629
+ if (!isMcpToolName(toolName)) {
630
+ return {
631
+ allowed: false,
632
+ reason: "tool_policy_missing",
633
+ message: `No tool-policy entry for ${toolName}`
634
+ };
635
+ }
636
+ const entry = TOOL_POLICY_MANIFEST[toolName];
637
+ if (!scopes.includes(entry.oauthScope)) {
638
+ return {
639
+ allowed: false,
640
+ reason: "insufficient_scope",
641
+ message: `Tool ${toolName} requires ${entry.oauthScope}`
642
+ };
643
+ }
644
+ return { allowed: true, entry };
645
+ }
646
+
647
+ // src/lib/mcp-telemetry.ts
648
+ import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
649
+ import { randomUUID as randomUUID2 } from "crypto";
650
+
651
+ // src/lib/console-api.ts
652
+ import { createHash } from "crypto";
34
653
 
35
654
  // src/service-auth.ts
36
655
  import { createPrivateKey, randomUUID, sign as signBytes } from "crypto";
37
- import {
38
- MCP_CONSOLE_SERVICE_AUDIENCE,
39
- MCP_CONSOLE_SERVICE_SCOPE,
40
- MCP_OAUTH_ISSUER,
41
- MCP_SERVICE_TOKEN_LIFETIME_SECONDS,
42
- MCP_TENANT_CLAIM,
43
- MCP_TENANT_ROLE_CLAIM
44
- } from "@01.software/auth-contracts";
45
656
  var KEYSET_ENV = "MCP_SERVICE_KEYSET";
46
657
  function assertProductionKeysetUse(source) {
47
658
  const vercelEnv = process.env.VERCEL_ENV;
@@ -167,136 +778,243 @@ function signMcpServiceToken(context) {
167
778
  return `${signingInput}.${signature.toString("base64url")}`;
168
779
  }
169
780
 
170
- // src/lib/client.ts
781
+ // src/lib/console-api.ts
782
+ var BASE_URL = process.env.SOFTWARE_API_URL || "http://localhost:3000";
783
+ var TIMEOUT_MS = 5e3;
171
784
  var MISSING_HTTP_AUTH_CONTEXT_ERROR = "MCP HTTP requests require a validated OAuth tenant context before tool execution.";
172
- function getClient() {
785
+ function resolveAuthHeaderContext() {
173
786
  const oauthContext = tenantAuthContext();
174
787
  if (oauthContext) {
175
- const serviceToken = signMcpServiceToken(oauthContext);
176
- const client = {
177
- lastRequestId: null,
178
- commerce: void 0,
179
- collections: void 0,
180
- community: void 0
181
- };
182
- const onRequestId = (id) => {
183
- client.lastRequestId = id;
788
+ return {
789
+ apiKey: signMcpServiceToken(oauthContext),
790
+ mode: "oauth"
184
791
  };
185
- client.commerce = new ServerCommerceClient({
186
- secretKey: serviceToken,
187
- onRequestId
188
- });
189
- client.collections = new CollectionClient(
190
- "",
191
- serviceToken,
192
- void 0,
193
- void 0,
194
- onRequestId
195
- );
196
- const community = new CommunityClient({ secretKey: serviceToken });
197
- const moderation = new ModerationApi({ secretKey: serviceToken, onRequestId });
198
- client.community = Object.assign(community, {
199
- moderation: {
200
- banCustomer: moderation.banCustomer.bind(moderation),
201
- unbanCustomer: moderation.unbanCustomer.bind(moderation)
202
- }
203
- });
204
- return client;
205
792
  }
206
793
  if (hasRequestContext()) throw new Error(MISSING_HTTP_AUTH_CONTEXT_ERROR);
207
- const secretKey = process.env.SOFTWARE_SECRET_KEY;
208
- const publishableKey = process.env.SOFTWARE_PUBLISHABLE_KEY || process.env.NEXT_PUBLIC_SOFTWARE_PUBLISHABLE_KEY;
209
- if (!secretKey) {
794
+ return {
795
+ apiKey: process.env.SOFTWARE_SECRET_KEY,
796
+ mode: "stdio",
797
+ publishableKey: process.env.SOFTWARE_PUBLISHABLE_KEY ?? process.env.NEXT_PUBLIC_SOFTWARE_PUBLISHABLE_KEY
798
+ };
799
+ }
800
+ function resolveApiKey() {
801
+ const { apiKey } = resolveAuthHeaderContext();
802
+ if (!apiKey || typeof apiKey !== "string") {
210
803
  throw new Error(
211
804
  "Authentication required. Set SOFTWARE_SECRET_KEY for stdio transport."
212
805
  );
213
806
  }
214
- if (!secretKey.startsWith("sk01_") && !secretKey.startsWith("pat01_")) {
215
- throw new Error("Invalid SOFTWARE_SECRET_KEY format. Expected sk01_ or pat01_ token.");
216
- }
217
- if (!publishableKey) {
218
- throw new Error(
219
- "publishableKey is required. Set SOFTWARE_PUBLISHABLE_KEY for stdio transport. It is used for rate limiting and monthly quota enforcement via the edge proxy."
220
- );
807
+ return apiKey;
808
+ }
809
+ function buildAuthHeaders(apiKey) {
810
+ const { mode, publishableKey } = resolveAuthHeaderContext();
811
+ const headers = {
812
+ Authorization: `Bearer ${apiKey}`
813
+ };
814
+ if (mode === "stdio" && publishableKey) {
815
+ headers["X-Publishable-Key"] = publishableKey;
221
816
  }
222
- return createServerClient({
223
- publishableKey,
224
- secretKey
225
- });
817
+ return headers;
226
818
  }
227
-
228
- // src/tools/query-collection.ts
229
- import { COLLECTIONS } from "@01.software/sdk";
230
-
231
- // src/lib/tool-utils.ts
232
- function toolSuccess(data) {
233
- return JSON.stringify({ success: true, ...data }, null, 2);
819
+ function extractErrorMessage(body) {
820
+ if (!body || typeof body !== "object") return void 0;
821
+ const b = body;
822
+ if (typeof b.error === "string") return b.error;
823
+ if (Array.isArray(b.errors) && b.errors[0]?.message) {
824
+ return String(b.errors[0].message);
825
+ }
826
+ if (typeof b.message === "string") return b.message;
827
+ return void 0;
234
828
  }
235
- function toolError(error) {
236
- const base = { success: false };
237
- if (error && typeof error === "object" && "code" in error) {
238
- const sdkErr = error;
239
- base.error = sdkErr.message || "Unknown error";
240
- if (sdkErr.status) base.status = sdkErr.status;
241
- if (sdkErr.code) base.code = sdkErr.code;
242
- if (sdkErr.suggestion) base.suggestion = sdkErr.suggestion;
243
- if (sdkErr.details?.errors) base.errors = sdkErr.details.errors;
244
- } else {
245
- base.error = error instanceof Error ? error.message : "Unknown error";
829
+ async function consoleGet(path, apiKey) {
830
+ const authHeaders = buildAuthHeaders(apiKey);
831
+ const controller = new AbortController();
832
+ const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS);
833
+ try {
834
+ const res = await fetch(`${BASE_URL}${path}`, {
835
+ headers: authHeaders,
836
+ signal: controller.signal
837
+ });
838
+ if (!res.ok) {
839
+ const body = await res.json().catch(() => ({}));
840
+ const msg = extractErrorMessage(body);
841
+ throw new Error(msg || `Console GET ${path} failed: ${res.status}`);
842
+ }
843
+ return res.json();
844
+ } finally {
845
+ clearTimeout(timeoutId);
246
846
  }
247
- return JSON.stringify(base, null, 2);
248
847
  }
249
- var MAX_QUERY_DEPTH = 5;
250
- function checkDepth(obj, depth = 0) {
251
- if (depth > MAX_QUERY_DEPTH) return false;
252
- if (obj && typeof obj === "object") {
253
- for (const val of Object.values(obj)) {
254
- if (!checkDepth(val, depth + 1)) return false;
848
+ async function consolePost(path, body, apiKey) {
849
+ const authHeaders = buildAuthHeaders(apiKey);
850
+ const controller = new AbortController();
851
+ const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS);
852
+ try {
853
+ const res = await fetch(`${BASE_URL}${path}`, {
854
+ method: "POST",
855
+ headers: { ...authHeaders, "Content-Type": "application/json" },
856
+ body: JSON.stringify(body),
857
+ signal: controller.signal
858
+ });
859
+ if (!res.ok) {
860
+ const errBody = await res.json().catch(() => ({}));
861
+ const msg = extractErrorMessage(errBody);
862
+ throw new Error(msg || `Console POST ${path} failed: ${res.status}`);
255
863
  }
864
+ return res.json();
865
+ } finally {
866
+ clearTimeout(timeoutId);
256
867
  }
257
- return true;
258
868
  }
259
- function parseJsonWhere(where) {
869
+ async function consolePostTelemetry(path, body, apiKey) {
870
+ const authHeaders = buildAuthHeaders(apiKey);
871
+ const controller = new AbortController();
872
+ const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS);
260
873
  try {
261
- const parsed = JSON.parse(where);
262
- if (!checkDepth(parsed)) {
263
- return {
264
- success: false,
265
- error: JSON.stringify(
266
- {
267
- success: false,
268
- error: `Query exceeds maximum nesting depth of ${MAX_QUERY_DEPTH}`
269
- },
270
- null,
271
- 2
272
- )
273
- };
874
+ const res = await fetch(`${BASE_URL}${path}`, {
875
+ method: "POST",
876
+ headers: { ...authHeaders, "Content-Type": "application/json" },
877
+ body: JSON.stringify(body),
878
+ signal: controller.signal
879
+ });
880
+ if (!res.ok) {
881
+ const errBody = await res.json().catch(() => ({}));
882
+ const msg = extractErrorMessage(errBody);
883
+ throw new Error(msg || `Console POST ${path} failed: ${res.status}`);
274
884
  }
275
- return { success: true, data: parsed };
885
+ } finally {
886
+ clearTimeout(timeoutId);
887
+ }
888
+ }
889
+
890
+ // src/lib/mcp-telemetry.ts
891
+ var TELEMETRY_ENDPOINT = "/api/tenants/mcp-telemetry";
892
+ var FLUSH_TIMEOUT_MS = 1500;
893
+ var telemetryContext = new AsyncLocalStorage2();
894
+ function createMcpTelemetrySummary(transport) {
895
+ return {
896
+ sessionId: randomUUID2(),
897
+ startedAtMs: Date.now(),
898
+ successfulWriteCount: 0,
899
+ toolCallCount: 0,
900
+ toolCounts: /* @__PURE__ */ new Map(),
901
+ transport
902
+ };
903
+ }
904
+ function currentMcpTelemetrySummary() {
905
+ return telemetryContext.getStore();
906
+ }
907
+ function runWithMcpTelemetry(summary, fn) {
908
+ return telemetryContext.run(summary, fn);
909
+ }
910
+ function recordMcpToolResult(params) {
911
+ if (!isMcpToolName(params.toolName)) return;
912
+ const toolName = params.toolName;
913
+ params.summary.toolCallCount += 1;
914
+ params.summary.toolCounts.set(
915
+ toolName,
916
+ (params.summary.toolCounts.get(toolName) ?? 0) + 1
917
+ );
918
+ if (!MCP_TOOL_CONTRACT[toolName].readOnly && toolResultSucceeded(params.resultText)) {
919
+ params.summary.successfulWriteCount += 1;
920
+ }
921
+ }
922
+ function toMcpTelemetryBody(summary) {
923
+ if (summary.toolCallCount <= 0) return null;
924
+ const durationMs = summary.transport === "http" ? Math.max(0, summary.durationMs ?? Date.now() - summary.startedAtMs) : void 0;
925
+ return {
926
+ converted: summary.successfulWriteCount > 0,
927
+ ...durationMs !== void 0 ? { durationMs } : {},
928
+ sessionId: summary.sessionId,
929
+ successfulWriteCount: summary.successfulWriteCount,
930
+ toolCallCount: summary.toolCallCount,
931
+ toolCounts: Object.fromEntries(summary.toolCounts),
932
+ transport: summary.transport
933
+ };
934
+ }
935
+ async function flushMcpTelemetrySummary(summary) {
936
+ const body = toMcpTelemetryBody(summary);
937
+ if (!body) return;
938
+ await swallow(
939
+ withTimeout(async () => {
940
+ const apiKey = resolveApiKey();
941
+ await consolePostTelemetry(TELEMETRY_ENDPOINT, body, apiKey);
942
+ }, FLUSH_TIMEOUT_MS)
943
+ );
944
+ }
945
+ function toolResultSucceeded(resultText) {
946
+ if (!resultText) return false;
947
+ try {
948
+ const parsed = JSON.parse(resultText);
949
+ return parsed.success === true;
950
+ } catch {
951
+ return false;
952
+ }
953
+ }
954
+ async function withTimeout(fn, timeoutMs) {
955
+ let timer;
956
+ await Promise.race([
957
+ fn(),
958
+ new Promise((resolve) => {
959
+ timer = setTimeout(resolve, timeoutMs);
960
+ })
961
+ ]);
962
+ if (timer) clearTimeout(timer);
963
+ }
964
+ async function swallow(promise) {
965
+ try {
966
+ await promise;
276
967
  } catch {
277
- return {
278
- success: false,
279
- error: JSON.stringify(
280
- {
281
- success: false,
282
- error: `Invalid JSON in "where" parameter: ${where.length > 100 ? where.substring(0, 100) + "..." : where}`
283
- },
284
- null,
285
- 2
286
- )
287
- };
288
968
  }
289
969
  }
290
970
 
291
971
  // src/tools/query-collection.ts
972
+ import { z as z3 } from "zod";
973
+
974
+ // src/lib/client.ts
975
+ import { createServerClient } from "@01.software/sdk";
976
+ var MISSING_HTTP_AUTH_CONTEXT_ERROR2 = "MCP HTTP requests require a validated OAuth tenant context before tool execution.";
977
+ var HTTP_OAUTH_SDK_CLIENT_ERROR = "MCP HTTP OAuth requests cannot use SDK-backed tools. Use reviewed Console service endpoints for OAuth transport.";
978
+ function getClient() {
979
+ const oauthContext = tenantAuthContext();
980
+ if (oauthContext) {
981
+ throw new Error(HTTP_OAUTH_SDK_CLIENT_ERROR);
982
+ }
983
+ if (hasRequestContext()) throw new Error(MISSING_HTTP_AUTH_CONTEXT_ERROR2);
984
+ const secretKey = process.env.SOFTWARE_SECRET_KEY;
985
+ const publishableKey = process.env.SOFTWARE_PUBLISHABLE_KEY || process.env.NEXT_PUBLIC_SOFTWARE_PUBLISHABLE_KEY;
986
+ if (!secretKey) {
987
+ throw new Error(
988
+ "Authentication required. Set SOFTWARE_SECRET_KEY for stdio transport."
989
+ );
990
+ }
991
+ if (!secretKey.startsWith("sk01_") && !secretKey.startsWith("pat01_")) {
992
+ throw new Error("Invalid SOFTWARE_SECRET_KEY format. Expected sk01_ or pat01_ token.");
993
+ }
994
+ if (!publishableKey) {
995
+ throw new Error(
996
+ "publishableKey is required. Set SOFTWARE_PUBLISHABLE_KEY for stdio transport. It is used for rate limiting and monthly quota enforcement via the edge proxy."
997
+ );
998
+ }
999
+ return createServerClient({
1000
+ publishableKey,
1001
+ secretKey
1002
+ });
1003
+ }
1004
+
1005
+ // src/tools/query-collection.ts
1006
+ import { SERVER_COLLECTIONS } from "@01.software/sdk";
292
1007
  var schema = {
293
- collection: z.enum(COLLECTIONS).describe("Collection name (required)"),
294
- where: z.string().optional().describe(
1008
+ collection: z3.enum(SERVER_COLLECTIONS).describe("Collection name (required)"),
1009
+ where: z3.string().optional().describe(
295
1010
  `Filter conditions (JSON string, optional). Pass the Payload query condition object as a JSON string. Example: '{"title":{"equals":"Product name"}}'`
296
1011
  ),
297
- limit: z.number().min(1).max(100).default(10).describe("Maximum number of items to return (1-100, default: 10)."),
298
- page: z.number().optional().describe("Page number (optional). Starts from 1. Used for pagination."),
299
- sort: z.string().regex(/^-?[a-zA-Z0-9_.]+$/, 'Sort must be a field name, optionally prefixed with "-" for descending').optional().describe(
1012
+ limit: z3.number().min(1).max(100).default(10).describe("Maximum number of items to return (1-100, default: 10)."),
1013
+ page: z3.number().optional().describe("Page number (optional). Starts from 1. Used for pagination."),
1014
+ sort: z3.string().regex(
1015
+ /^-?[a-zA-Z0-9_.]+$/,
1016
+ 'Sort must be a field name, optionally prefixed with "-" for descending'
1017
+ ).optional().describe(
300
1018
  'Sort field (optional). Use "fieldName" for ascending or "-fieldName" for descending. Example: "createdAt" or "-createdAt"'
301
1019
  )
302
1020
  };
@@ -350,11 +1068,11 @@ async function queryCollection({
350
1068
  }
351
1069
 
352
1070
  // src/tools/get-collection-by-id.ts
353
- import { z as z2 } from "zod";
354
- import { COLLECTIONS as COLLECTIONS2 } from "@01.software/sdk";
1071
+ import { z as z4 } from "zod";
1072
+ import { SERVER_COLLECTIONS as SERVER_COLLECTIONS2 } from "@01.software/sdk";
355
1073
  var schema2 = {
356
- collection: z2.enum(COLLECTIONS2).describe("Collection name (required)"),
357
- id: z2.string().min(1).describe("Item ID (required)")
1074
+ collection: z4.enum(SERVER_COLLECTIONS2).describe("Collection name (required)"),
1075
+ id: z4.string().min(1).describe("Item ID (required)")
358
1076
  };
359
1077
  var metadata2 = {
360
1078
  name: "get-collection-by-id",
@@ -379,201 +1097,12 @@ async function getCollectionById({
379
1097
  }
380
1098
  }
381
1099
 
382
- // src/tools/create-collection.ts
383
- import { z as z3 } from "zod";
384
- import { COLLECTIONS as COLLECTIONS3 } from "@01.software/sdk";
1100
+ // src/tools/get-order.ts
1101
+ import { z as z5 } from "zod";
385
1102
  var schema3 = {
386
- collection: z3.enum(COLLECTIONS3).describe("Collection name (required)"),
387
- data: z3.record(z3.string(), z3.unknown()).describe(
388
- "Data to create (required). Use get-collection-schema first to understand writable fields, hidden fields, and required metadata. Server will validate and reject invalid fields."
389
- )
1103
+ orderNumber: z5.string().min(1).describe("Order number to look up (required)")
390
1104
  };
391
1105
  var metadata3 = {
392
- name: "create-collection",
393
- description: "Create a new collection item",
394
- annotations: {
395
- title: "Create collection item",
396
- readOnlyHint: false,
397
- destructiveHint: false,
398
- idempotentHint: false
399
- }
400
- };
401
- async function createCollection({
402
- collection,
403
- data
404
- }) {
405
- try {
406
- const client = getClient().collections;
407
- const result = await client.from(collection).create(data);
408
- return toolSuccess({ data: result.doc, message: result.message });
409
- } catch (error) {
410
- return toolError(error);
411
- }
412
- }
413
-
414
- // src/tools/update-collection.ts
415
- import { z as z4 } from "zod";
416
- import { COLLECTIONS as COLLECTIONS4 } from "@01.software/sdk";
417
- var schema4 = {
418
- collection: z4.enum(COLLECTIONS4).describe("Collection name (required)"),
419
- id: z4.string().min(1).describe("Item ID (required)"),
420
- data: z4.record(z4.string(), z4.unknown()).describe(
421
- "Data to update (required). Use get-collection-by-id first to check current structure, then get-collection-schema to confirm writable fields and required metadata. Server will validate and reject invalid fields."
422
- )
423
- };
424
- var metadata4 = {
425
- name: "update-collection",
426
- description: "Update an existing collection item",
427
- annotations: {
428
- title: "Update collection item",
429
- readOnlyHint: false,
430
- destructiveHint: true,
431
- idempotentHint: true
432
- }
433
- };
434
- async function updateCollection({
435
- collection,
436
- id,
437
- data
438
- }) {
439
- try {
440
- const client = getClient().collections;
441
- const result = await client.from(collection).update(id, data);
442
- return toolSuccess({ data: result.doc, message: result.message });
443
- } catch (error) {
444
- return toolError(error);
445
- }
446
- }
447
-
448
- // src/tools/delete-collection.ts
449
- import { z as z5 } from "zod";
450
- import { COLLECTIONS as COLLECTIONS5 } from "@01.software/sdk";
451
- var schema5 = {
452
- collection: z5.enum(COLLECTIONS5).describe("Collection name (required)"),
453
- id: z5.string().min(1).describe("Item ID (required)")
454
- };
455
- var metadata5 = {
456
- name: "delete-collection",
457
- description: "Delete a collection item",
458
- annotations: {
459
- title: "Delete collection item",
460
- readOnlyHint: false,
461
- destructiveHint: true,
462
- idempotentHint: true
463
- }
464
- };
465
- async function deleteCollection({
466
- collection,
467
- id
468
- }) {
469
- try {
470
- const client = getClient();
471
- await client.collections.from(collection).remove(id);
472
- return toolSuccess({ message: "Deleted successfully." });
473
- } catch (error) {
474
- return toolError(error);
475
- }
476
- }
477
-
478
- // src/tools/delete-many-collection.ts
479
- import { z as z6 } from "zod";
480
- import { COLLECTIONS as COLLECTIONS6 } from "@01.software/sdk";
481
- var schema6 = {
482
- collection: z6.enum(COLLECTIONS6).describe("Collection name (required)"),
483
- where: z6.string().describe(
484
- `Filter conditions (JSON string, required). Determines which items to delete. Example: '{"status":{"equals":"archived"}}'`
485
- )
486
- };
487
- var metadata6 = {
488
- name: "delete-many-collection",
489
- description: "Bulk delete collection items matching a filter. All matching items will be permanently deleted.",
490
- annotations: {
491
- title: "Bulk delete collection items",
492
- readOnlyHint: false,
493
- destructiveHint: true,
494
- idempotentHint: true
495
- }
496
- };
497
- async function deleteManyCollection({
498
- collection,
499
- where
500
- }) {
501
- try {
502
- const client = getClient().collections;
503
- const parsed = parseJsonWhere(where);
504
- if (!parsed.success) return parsed.error;
505
- if (!parsed.data || typeof parsed.data !== "object" || Object.keys(parsed.data).length === 0) {
506
- return toolError(
507
- new Error(
508
- 'Empty "where" filter is not allowed for bulk deletes. Provide at least one filter condition.'
509
- )
510
- );
511
- }
512
- const result = await client.from(collection).removeMany(parsed.data);
513
- return toolSuccess({
514
- totalDocs: result.totalDocs,
515
- message: `Deleted ${result.totalDocs} item(s).`
516
- });
517
- } catch (error) {
518
- return toolError(error);
519
- }
520
- }
521
-
522
- // src/tools/update-many-collection.ts
523
- import { z as z7 } from "zod";
524
- import { COLLECTIONS as COLLECTIONS7 } from "@01.software/sdk";
525
- var schema7 = {
526
- collection: z7.enum(COLLECTIONS7).describe("Collection name (required)"),
527
- where: z7.string().describe(
528
- `Filter conditions (JSON string, required). Determines which items to update. Example: '{"status":{"equals":"draft"}}'`
529
- ),
530
- data: z7.record(z7.string(), z7.unknown()).describe(
531
- "Data to update (required). Partial updates supported. Server will validate and reject invalid fields."
532
- )
533
- };
534
- var metadata7 = {
535
- name: "update-many-collection",
536
- description: "Bulk update collection items matching a filter. All matching items will be updated with the provided data.",
537
- annotations: {
538
- title: "Bulk update collection items",
539
- readOnlyHint: false,
540
- destructiveHint: true,
541
- idempotentHint: true
542
- }
543
- };
544
- async function updateManyCollection({
545
- collection,
546
- where,
547
- data
548
- }) {
549
- try {
550
- const client = getClient().collections;
551
- const parsed = parseJsonWhere(where);
552
- if (!parsed.success) return parsed.error;
553
- if (!parsed.data || typeof parsed.data !== "object" || Object.keys(parsed.data).length === 0) {
554
- return toolError(
555
- new Error(
556
- 'Empty "where" filter is not allowed for bulk updates. Provide at least one filter condition.'
557
- )
558
- );
559
- }
560
- const result = await client.from(collection).updateMany(parsed.data, data);
561
- return toolSuccess({
562
- data: result.docs,
563
- totalDocs: result.totalDocs,
564
- message: `Updated ${result.totalDocs} item(s).`
565
- });
566
- } catch (error) {
567
- return toolError(error);
568
- }
569
- }
570
-
571
- // src/tools/get-order.ts
572
- import { z as z8 } from "zod";
573
- var schema8 = {
574
- orderNumber: z8.string().min(1).describe("Order number to look up (required)")
575
- };
576
- var metadata8 = {
577
1106
  name: "get-order",
578
1107
  description: "Get order details by order number. Returns order with related data (depth:1).",
579
1108
  annotations: {
@@ -601,26 +1130,26 @@ async function getOrder({
601
1130
  }
602
1131
 
603
1132
  // src/tools/create-order.ts
604
- import { z as z9 } from "zod";
605
- var schema9 = {
606
- pgPaymentId: z9.string().optional().describe("PG payment ID (optional \u2014 omit for free orders)"),
607
- orderNumber: z9.string().min(1).describe("Unique order number (required)"),
608
- customerSnapshot: z9.object({
609
- name: z9.string().optional().describe("Customer name"),
610
- email: z9.string().describe("Customer email (required)"),
611
- phone: z9.string().optional().describe("Customer phone")
1133
+ import { z as z6 } from "zod";
1134
+ var schema4 = {
1135
+ pgPaymentId: z6.string().optional().describe("PG payment ID (optional \u2014 omit for free orders)"),
1136
+ orderNumber: z6.string().min(1).describe("Unique order number (required)"),
1137
+ customerSnapshot: z6.object({
1138
+ name: z6.string().optional().describe("Customer name"),
1139
+ email: z6.string().describe("Customer email (required)"),
1140
+ phone: z6.string().optional().describe("Customer phone")
612
1141
  }).describe("Customer snapshot at time of order (required)"),
613
- shippingAddress: z9.record(z9.string(), z9.unknown()).describe(
1142
+ shippingAddress: z6.record(z6.string(), z6.unknown()).describe(
614
1143
  "Shipping address object (required). Fields: postalCode, address1, address2, deliveryMessage, recipientName, phone"
615
1144
  ),
616
- orderItems: z9.array(z9.record(z9.string(), z9.unknown())).describe(
1145
+ orderItems: z6.array(z6.record(z6.string(), z6.unknown())).describe(
617
1146
  "Array of order item objects (required). Each: { product, variant, option, quantity, unitPrice?, totalPrice? }"
618
1147
  ),
619
- totalAmount: z9.number().nonnegative().describe("Total order amount (required, min 0)"),
620
- shippingAmount: z9.number().nonnegative().optional().describe("Shipping amount (optional, default 0)"),
621
- discountCode: z9.string().optional().describe("Discount code to apply (optional)")
1148
+ totalAmount: z6.number().nonnegative().describe("Total order amount (required, min 0)"),
1149
+ shippingAmount: z6.number().nonnegative().optional().describe("Shipping amount (optional, default 0)"),
1150
+ discountCode: z6.string().optional().describe("Discount code to apply (optional)")
622
1151
  };
623
- var metadata9 = {
1152
+ var metadata4 = {
624
1153
  name: "create-order",
625
1154
  description: "Create a new order with products and shipping information. Supports idempotency.",
626
1155
  annotations: {
@@ -643,10 +1172,10 @@ async function createOrder(params) {
643
1172
  }
644
1173
 
645
1174
  // src/tools/update-order.ts
646
- import { z as z10 } from "zod";
647
- var schema10 = {
648
- orderNumber: z10.string().min(1).describe("Order number (required)"),
649
- status: z10.enum([
1175
+ import { z as z7 } from "zod";
1176
+ var schema5 = {
1177
+ orderNumber: z7.string().min(1).describe("Order number (required)"),
1178
+ status: z7.enum([
650
1179
  "pending",
651
1180
  "paid",
652
1181
  "failed",
@@ -659,7 +1188,7 @@ var schema10 = {
659
1188
  "New order status. Return-related statuses (return_requested, return_processing, returned) must be set via Return endpoints."
660
1189
  )
661
1190
  };
662
- var metadata10 = {
1191
+ var metadata5 = {
663
1192
  name: "update-order",
664
1193
  description: "Update order status. Automatically adjusts stock on status changes (e.g., canceled restores stock).",
665
1194
  annotations: {
@@ -683,17 +1212,17 @@ async function updateOrder({
683
1212
  }
684
1213
 
685
1214
  // src/tools/checkout.ts
686
- import { z as z11 } from "zod";
687
- var schema11 = {
688
- cartId: z11.string().min(1).describe("Cart ID to convert to order (required)"),
689
- pgPaymentId: z11.string().optional().describe("PG payment ID (optional \u2014 omit for free orders)"),
690
- orderNumber: z11.string().min(1).describe("Unique order number (required)"),
691
- customerSnapshot: z11.record(z11.string(), z11.unknown()).describe(
1215
+ import { z as z8 } from "zod";
1216
+ var schema6 = {
1217
+ cartId: z8.string().min(1).describe("Cart ID to convert to order (required)"),
1218
+ pgPaymentId: z8.string().optional().describe("PG payment ID (optional \u2014 omit for free orders)"),
1219
+ orderNumber: z8.string().min(1).describe("Unique order number (required)"),
1220
+ customerSnapshot: z8.record(z8.string(), z8.unknown()).describe(
692
1221
  "Customer snapshot object (required). Fields: { name?, email, phone? }"
693
1222
  ),
694
- discountCode: z11.string().optional().describe("Discount code to apply (optional)")
1223
+ discountCode: z8.string().optional().describe("Discount code to apply (optional)")
695
1224
  };
696
- var metadata11 = {
1225
+ var metadata6 = {
697
1226
  name: "checkout",
698
1227
  description: "Convert a cart to an order. Validates stock, creates order and transaction, marks cart as completed. Supports idempotency.",
699
1228
  annotations: {
@@ -716,21 +1245,21 @@ async function checkout(params) {
716
1245
  }
717
1246
 
718
1247
  // src/tools/create-fulfillment.ts
719
- import { z as z12 } from "zod";
720
- var schema12 = {
721
- orderNumber: z12.string().min(1).describe("Order number (required)"),
722
- carrier: z12.string().optional().describe("Shipping carrier name (optional)"),
723
- trackingNumber: z12.string().optional().describe(
1248
+ import { z as z9 } from "zod";
1249
+ var schema7 = {
1250
+ orderNumber: z9.string().min(1).describe("Order number (required)"),
1251
+ carrier: z9.string().optional().describe("Shipping carrier name (optional)"),
1252
+ trackingNumber: z9.string().optional().describe(
724
1253
  'Tracking number (optional). Setting carrier + tracking triggers "shipped" status'
725
1254
  ),
726
- items: z12.array(
727
- z12.object({
728
- orderItem: z12.string().min(1).describe("Order item ID"),
729
- quantity: z12.number().int().positive().describe("Quantity to fulfill")
1255
+ items: z9.array(
1256
+ z9.object({
1257
+ orderItem: z9.string().min(1).describe("Order item ID"),
1258
+ quantity: z9.number().int().positive().describe("Quantity to fulfill")
730
1259
  })
731
1260
  ).describe("Array of items to fulfill (required)")
732
1261
  };
733
- var metadata12 = {
1262
+ var metadata7 = {
734
1263
  name: "create-fulfillment",
735
1264
  description: "Create a shipment/fulfillment for order items. Auto-updates order status (paid \u2192 preparing \u2192 shipped).",
736
1265
  annotations: {
@@ -761,20 +1290,20 @@ async function createFulfillment({
761
1290
  }
762
1291
 
763
1292
  // src/tools/update-fulfillment.ts
764
- import { z as z13 } from "zod";
765
- var schema13 = {
766
- fulfillmentId: z13.string().min(1).describe("Fulfillment ID (required)"),
767
- status: z13.enum(["packed", "shipped", "delivered", "failed"]).describe(
1293
+ import { z as z10 } from "zod";
1294
+ var schema8 = {
1295
+ fulfillmentId: z10.string().min(1).describe("Fulfillment ID (required)"),
1296
+ status: z10.enum(["packed", "shipped", "delivered", "failed"]).describe(
768
1297
  "New fulfillment status (required). FSM: pending\u2192packed/shipped/failed, packed\u2192shipped/failed, shipped\u2192delivered/failed"
769
1298
  ),
770
- carrier: z13.string().optional().describe(
1299
+ carrier: z10.string().optional().describe(
771
1300
  "Shipping carrier (optional, changeable only in pending/packed status)"
772
1301
  ),
773
- trackingNumber: z13.string().optional().describe(
1302
+ trackingNumber: z10.string().optional().describe(
774
1303
  "Tracking number (optional, changeable only in pending/packed status)"
775
1304
  )
776
1305
  };
777
- var metadata13 = {
1306
+ var metadata8 = {
778
1307
  name: "update-fulfillment",
779
1308
  description: "Update fulfillment status, carrier, and tracking number. Auto-updates order status when all fulfillments are delivered.",
780
1309
  annotations: {
@@ -805,14 +1334,8 @@ async function updateFulfillment({
805
1334
  }
806
1335
 
807
1336
  // src/tools/update-transaction.ts
808
- import { z as z14 } from "zod";
809
- var schema14 = {
810
- pgPaymentId: z14.string().min(1).describe("PG payment ID (required)"),
811
- status: z14.enum(["pending", "paid", "failed", "canceled"]).describe("New transaction status (required)"),
812
- paymentMethod: z14.string().optional().describe("Payment method (optional)"),
813
- receiptUrl: z14.string().optional().describe("Receipt URL (optional)")
814
- };
815
- var metadata14 = {
1337
+ var schema9 = UpdateTransactionSchema.shape;
1338
+ var metadata9 = {
816
1339
  name: "update-transaction",
817
1340
  description: "Update transaction status, payment method, and receipt URL.",
818
1341
  annotations: {
@@ -826,16 +1349,21 @@ async function updateTransaction({
826
1349
  pgPaymentId,
827
1350
  status,
828
1351
  paymentMethod,
829
- receiptUrl
1352
+ receiptUrl,
1353
+ paymentKey,
1354
+ amount
830
1355
  }) {
831
1356
  try {
832
1357
  const client = getClient();
833
- const result = await client.commerce.orders.updateTransaction({
1358
+ const params = {
834
1359
  pgPaymentId,
835
1360
  status,
836
1361
  paymentMethod,
837
- receiptUrl
838
- });
1362
+ receiptUrl,
1363
+ paymentKey,
1364
+ amount
1365
+ };
1366
+ const result = await client.commerce.orders.updateTransaction(params);
839
1367
  return toolSuccess({ data: result });
840
1368
  } catch (error) {
841
1369
  return toolError(error);
@@ -843,20 +1371,20 @@ async function updateTransaction({
843
1371
  }
844
1372
 
845
1373
  // src/tools/create-return.ts
846
- import { z as z15 } from "zod";
847
- var schema15 = {
848
- orderNumber: z15.string().min(1).describe("Order number (required)"),
849
- reason: z15.enum(["change_of_mind", "defective", "wrong_delivery", "damaged", "other"]).optional().describe("Return reason (optional)"),
850
- reasonDetail: z15.string().optional().describe("Detailed reason text (optional)"),
851
- returnItems: z15.array(
852
- z15.object({
853
- orderItem: z15.string().min(1).describe("Order item ID"),
854
- quantity: z15.number().int().positive().describe("Quantity to return")
1374
+ import { z as z11 } from "zod";
1375
+ var schema10 = {
1376
+ orderNumber: z11.string().min(1).describe("Order number (required)"),
1377
+ reason: z11.enum(["change_of_mind", "defective", "wrong_delivery", "damaged", "other"]).optional().describe("Return reason (optional)"),
1378
+ reasonDetail: z11.string().optional().describe("Detailed reason text (optional)"),
1379
+ returnItems: z11.array(
1380
+ z11.object({
1381
+ orderItem: z11.string().min(1).describe("Order item ID"),
1382
+ quantity: z11.number().int().positive().describe("Quantity to return")
855
1383
  })
856
1384
  ).describe("Array of products to return (required)"),
857
- refundAmount: z15.number().nonnegative().describe("Refund amount (required, min 0)")
1385
+ refundAmount: z11.number().nonnegative().describe("Refund amount (required, min 0)")
858
1386
  };
859
- var metadata15 = {
1387
+ var metadata10 = {
860
1388
  name: "create-return",
861
1389
  description: "Create a return request for an order. Only works for delivered/confirmed orders. Updates order status to return_requested.",
862
1390
  annotations: {
@@ -889,14 +1417,14 @@ async function createReturn({
889
1417
  }
890
1418
 
891
1419
  // src/tools/update-return.ts
892
- import { z as z16 } from "zod";
893
- var schema16 = {
894
- returnId: z16.string().min(1).describe("Return ID (required)"),
895
- status: z16.enum(["processing", "approved", "rejected", "completed"]).describe(
1420
+ import { z as z12 } from "zod";
1421
+ var schema11 = {
1422
+ returnId: z12.string().min(1).describe("Return ID (required)"),
1423
+ status: z12.enum(["processing", "approved", "rejected", "completed"]).describe(
896
1424
  "New return status (required). Valid transitions: requested\u2192processing/rejected, processing\u2192approved/rejected, approved\u2192completed"
897
1425
  )
898
1426
  };
899
- var metadata16 = {
1427
+ var metadata11 = {
900
1428
  name: "update-return",
901
1429
  description: "Update return status with FSM validation. Restores inventory on completion, reverts order status on rejection.",
902
1430
  annotations: {
@@ -920,22 +1448,8 @@ async function updateReturn({
920
1448
  }
921
1449
 
922
1450
  // src/tools/return-with-refund.ts
923
- import { z as z17 } from "zod";
924
- var schema17 = {
925
- orderNumber: z17.string().min(1).describe("Order number (required)"),
926
- reason: z17.enum(["change_of_mind", "defective", "wrong_delivery", "damaged", "other"]).optional().describe("Return reason (optional)"),
927
- reasonDetail: z17.string().optional().describe("Detailed reason text (optional)"),
928
- returnItems: z17.array(
929
- z17.object({
930
- orderItem: z17.string().min(1).describe("Order item ID"),
931
- quantity: z17.number().int().positive().describe("Quantity to return")
932
- })
933
- ).describe("Array of products to return (required)"),
934
- refundAmount: z17.number().nonnegative().describe("Refund amount (required, min 0)"),
935
- pgPaymentId: z17.string().min(1).describe("PG payment ID for refund (required)"),
936
- refundReceiptUrl: z17.string().optional().describe("Refund receipt URL (optional)")
937
- };
938
- var metadata17 = {
1451
+ var schema12 = ReturnWithRefundSchema.shape;
1452
+ var metadata12 = {
939
1453
  name: "return-with-refund",
940
1454
  description: "Combined return + refund operation. Creates return, restores stock, cancels transaction, updates order status.",
941
1455
  annotations: {
@@ -952,19 +1466,22 @@ async function returnWithRefund({
952
1466
  returnItems,
953
1467
  refundAmount,
954
1468
  pgPaymentId,
1469
+ paymentKey,
955
1470
  refundReceiptUrl
956
1471
  }) {
957
1472
  try {
958
1473
  const client = getClient();
959
- const result = await client.commerce.orders.returnWithRefund({
1474
+ const params = {
960
1475
  orderNumber,
961
1476
  reason,
962
1477
  reasonDetail,
963
1478
  returnItems,
964
1479
  refundAmount,
965
1480
  pgPaymentId,
1481
+ paymentKey,
966
1482
  refundReceiptUrl
967
- });
1483
+ };
1484
+ const result = await client.commerce.orders.returnWithRefund(params);
968
1485
  return toolSuccess({ data: result });
969
1486
  } catch (error) {
970
1487
  return toolError(error);
@@ -972,15 +1489,15 @@ async function returnWithRefund({
972
1489
  }
973
1490
 
974
1491
  // src/tools/add-cart-item.ts
975
- import { z as z18 } from "zod";
976
- var schema18 = {
977
- cartId: z18.string().min(1).describe("Cart ID (required)"),
978
- product: z18.string().min(1).describe("Product ID (required)"),
979
- variant: z18.string().min(1).describe("Product variant ID (required)"),
980
- option: z18.string().min(1).describe("Product option ID (required)"),
981
- quantity: z18.number().int().positive().describe("Quantity to add (required, positive integer)")
1492
+ import { z as z13 } from "zod";
1493
+ var schema13 = {
1494
+ cartId: z13.string().min(1).describe("Cart ID (required)"),
1495
+ product: z13.string().min(1).describe("Product ID (required)"),
1496
+ variant: z13.string().min(1).describe("Product variant ID (required)"),
1497
+ option: z13.string().min(1).describe("Product option ID (required)"),
1498
+ quantity: z13.number().int().positive().describe("Quantity to add (required, positive integer)")
982
1499
  };
983
- var metadata18 = {
1500
+ var metadata13 = {
984
1501
  name: "add-cart-item",
985
1502
  description: "Add a product to cart. Validates stock, merges quantity if item already exists, recalculates totals.",
986
1503
  annotations: {
@@ -1013,12 +1530,12 @@ async function addCartItem({
1013
1530
  }
1014
1531
 
1015
1532
  // src/tools/update-cart-item.ts
1016
- import { z as z19 } from "zod";
1017
- var schema19 = {
1018
- cartItemId: z19.string().min(1).describe("Cart item ID (required)"),
1019
- quantity: z19.number().int().positive().describe("New quantity (required, positive integer)")
1533
+ import { z as z14 } from "zod";
1534
+ var schema14 = {
1535
+ cartItemId: z14.string().min(1).describe("Cart item ID (required)"),
1536
+ quantity: z14.number().int().positive().describe("New quantity (required, positive integer)")
1020
1537
  };
1021
- var metadata19 = {
1538
+ var metadata14 = {
1022
1539
  name: "update-cart-item",
1023
1540
  description: "Update cart item quantity. Validates stock availability, recalculates cart totals.",
1024
1541
  annotations: {
@@ -1042,11 +1559,11 @@ async function updateCartItem({
1042
1559
  }
1043
1560
 
1044
1561
  // src/tools/remove-cart-item.ts
1045
- import { z as z20 } from "zod";
1046
- var schema20 = {
1047
- cartItemId: z20.string().min(1).describe("Cart item ID to remove (required)")
1562
+ import { z as z15 } from "zod";
1563
+ var schema15 = {
1564
+ cartItemId: z15.string().min(1).describe("Cart item ID to remove (required)")
1048
1565
  };
1049
- var metadata20 = {
1566
+ var metadata15 = {
1050
1567
  name: "remove-cart-item",
1051
1568
  description: "Remove an item from cart. Recalculates cart totals after removal.",
1052
1569
  annotations: {
@@ -1069,12 +1586,12 @@ async function removeCartItem({
1069
1586
  }
1070
1587
 
1071
1588
  // src/tools/apply-discount.ts
1072
- import { z as z21 } from "zod";
1073
- var schema21 = {
1074
- cartId: z21.string().min(1).describe("Cart ID (required)"),
1075
- discountCode: z21.string().describe("Discount code to apply (required)")
1589
+ import { z as z16 } from "zod";
1590
+ var schema16 = {
1591
+ cartId: z16.string().min(1).describe("Cart ID (required)"),
1592
+ discountCode: z16.string().describe("Discount code to apply (required)")
1076
1593
  };
1077
- var metadata21 = {
1594
+ var metadata16 = {
1078
1595
  name: "apply-discount",
1079
1596
  description: "Apply a discount code to a cart. Validates the code, updates cart totals, and sets free shipping if applicable.",
1080
1597
  annotations: {
@@ -1098,11 +1615,11 @@ async function applyDiscount({
1098
1615
  }
1099
1616
 
1100
1617
  // src/tools/remove-discount.ts
1101
- import { z as z22 } from "zod";
1102
- var schema22 = {
1103
- cartId: z22.string().min(1).describe("Cart ID (required)")
1618
+ import { z as z17 } from "zod";
1619
+ var schema17 = {
1620
+ cartId: z17.string().min(1).describe("Cart ID (required)")
1104
1621
  };
1105
- var metadata22 = {
1622
+ var metadata17 = {
1106
1623
  name: "remove-discount",
1107
1624
  description: "Remove the applied discount code from a cart and recalculate totals.",
1108
1625
  annotations: {
@@ -1125,11 +1642,11 @@ async function removeDiscount({
1125
1642
  }
1126
1643
 
1127
1644
  // src/tools/clear-cart.ts
1128
- import { z as z23 } from "zod";
1129
- var schema23 = {
1130
- cartId: z23.string().min(1).describe("Cart ID (required)")
1645
+ import { z as z18 } from "zod";
1646
+ var schema18 = {
1647
+ cartId: z18.string().min(1).describe("Cart ID (required)")
1131
1648
  };
1132
- var metadata23 = {
1649
+ var metadata18 = {
1133
1650
  name: "clear-cart",
1134
1651
  description: "Remove all items from a cart, reset discount and amounts. Shipping fee is preserved.",
1135
1652
  annotations: {
@@ -1152,12 +1669,12 @@ async function clearCart({
1152
1669
  }
1153
1670
 
1154
1671
  // src/tools/validate-discount.ts
1155
- import { z as z24 } from "zod";
1156
- var schema24 = {
1157
- code: z24.string().describe("Discount code to validate (required)"),
1158
- orderAmount: z24.number().describe("Order amount for validation (required)")
1672
+ import { z as z19 } from "zod";
1673
+ var schema19 = {
1674
+ code: z19.string().describe("Discount code to validate (required)"),
1675
+ orderAmount: z19.number().describe("Order amount for validation (required)")
1159
1676
  };
1160
- var metadata24 = {
1677
+ var metadata19 = {
1161
1678
  name: "validate-discount",
1162
1679
  description: "Validate a discount code. Checks active status, date range, usage limits, minimum order amount, and calculates discount.",
1163
1680
  annotations: {
@@ -1184,13 +1701,13 @@ async function validateDiscount({
1184
1701
  }
1185
1702
 
1186
1703
  // src/tools/calculate-shipping.ts
1187
- import { z as z25 } from "zod";
1188
- var schema25 = {
1189
- shippingPolicyId: z25.string().optional().describe("Shipping policy ID (uses default policy if omitted)"),
1190
- orderAmount: z25.number().describe("Order amount for fee calculation (required)"),
1191
- postalCode: z25.string().optional().describe("Postal code for Jeju surcharge detection (63000-63644)")
1704
+ import { z as z20 } from "zod";
1705
+ var schema20 = {
1706
+ shippingPolicyId: z20.string().optional().describe("Shipping policy ID (uses default policy if omitted)"),
1707
+ orderAmount: z20.number().describe("Order amount for fee calculation (required)"),
1708
+ postalCode: z20.string().optional().describe("Postal code for Jeju surcharge detection (63000-63644)")
1192
1709
  };
1193
- var metadata25 = {
1710
+ var metadata20 = {
1194
1711
  name: "calculate-shipping",
1195
1712
  description: "Calculate shipping fee based on order amount and postal code. Supports free shipping threshold and Jeju surcharge.",
1196
1713
  annotations: {
@@ -1219,18 +1736,18 @@ async function calculateShipping({
1219
1736
  }
1220
1737
 
1221
1738
  // src/tools/stock-check.ts
1222
- import { z as z26 } from "zod";
1223
- var schema26 = {
1224
- items: z26.array(
1225
- z26.object({
1226
- variantId: z26.string().describe("Product variant ID"),
1227
- quantity: z26.number().int().positive().describe("Requested quantity")
1739
+ import { z as z21 } from "zod";
1740
+ var schema21 = {
1741
+ items: z21.array(
1742
+ z21.object({
1743
+ variantId: z21.string().describe("Product variant ID"),
1744
+ quantity: z21.number().int().positive().describe("Requested quantity")
1228
1745
  })
1229
1746
  ).describe(
1230
1747
  "Array of items to check stock for (required, max 100). Each: { variantId, quantity }"
1231
1748
  )
1232
1749
  };
1233
- var metadata26 = {
1750
+ var metadata21 = {
1234
1751
  name: "stock-check",
1235
1752
  description: "Batch check product option stock availability. Returns per-item availability and an allAvailable flag.",
1236
1753
  annotations: {
@@ -1253,113 +1770,21 @@ async function stockCheck({
1253
1770
  }
1254
1771
 
1255
1772
  // src/tools/get-collection-schema.ts
1256
- import { z as z27 } from "zod";
1257
- import { COLLECTIONS as COLLECTIONS8 } from "@01.software/sdk";
1258
-
1259
- // src/lib/console-api.ts
1260
- import { createHash } from "crypto";
1261
- var BASE_URL = process.env.SOFTWARE_API_URL || "http://localhost:3000";
1262
- var TIMEOUT_MS = 5e3;
1263
- var MISSING_HTTP_AUTH_CONTEXT_ERROR2 = "MCP HTTP requests require a validated OAuth tenant context before tool execution.";
1264
- function resolveAuthHeaderContext() {
1265
- const oauthContext = tenantAuthContext();
1266
- if (oauthContext) {
1267
- return {
1268
- apiKey: signMcpServiceToken(oauthContext),
1269
- mode: "oauth"
1270
- };
1271
- }
1272
- if (hasRequestContext()) throw new Error(MISSING_HTTP_AUTH_CONTEXT_ERROR2);
1273
- return {
1274
- apiKey: process.env.SOFTWARE_SECRET_KEY,
1275
- mode: "stdio",
1276
- publishableKey: process.env.SOFTWARE_PUBLISHABLE_KEY ?? process.env.NEXT_PUBLIC_SOFTWARE_PUBLISHABLE_KEY
1277
- };
1278
- }
1279
- function resolveApiKey() {
1280
- const { apiKey } = resolveAuthHeaderContext();
1281
- if (!apiKey || typeof apiKey !== "string") {
1282
- throw new Error(
1283
- "Authentication required. Set SOFTWARE_SECRET_KEY for stdio transport."
1284
- );
1285
- }
1286
- return apiKey;
1287
- }
1288
- function buildAuthHeaders(apiKey) {
1289
- const { mode, publishableKey } = resolveAuthHeaderContext();
1290
- const headers = {
1291
- Authorization: `Bearer ${apiKey}`
1292
- };
1293
- if (mode === "stdio" && publishableKey) {
1294
- headers["X-Publishable-Key"] = publishableKey;
1295
- }
1296
- return headers;
1297
- }
1298
- function extractErrorMessage(body) {
1299
- if (!body || typeof body !== "object") return void 0;
1300
- const b = body;
1301
- if (typeof b.error === "string") return b.error;
1302
- if (Array.isArray(b.errors) && b.errors[0]?.message) {
1303
- return String(b.errors[0].message);
1304
- }
1305
- if (typeof b.message === "string") return b.message;
1306
- return void 0;
1307
- }
1308
- async function consoleGet(path, apiKey) {
1309
- const authHeaders = buildAuthHeaders(apiKey);
1310
- const controller = new AbortController();
1311
- const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS);
1312
- try {
1313
- const res = await fetch(`${BASE_URL}${path}`, {
1314
- headers: authHeaders,
1315
- signal: controller.signal
1316
- });
1317
- if (!res.ok) {
1318
- const body = await res.json().catch(() => ({}));
1319
- const msg = extractErrorMessage(body);
1320
- throw new Error(msg || `Console GET ${path} failed: ${res.status}`);
1321
- }
1322
- return res.json();
1323
- } finally {
1324
- clearTimeout(timeoutId);
1325
- }
1326
- }
1327
- async function consolePost(path, body, apiKey) {
1328
- const authHeaders = buildAuthHeaders(apiKey);
1329
- const controller = new AbortController();
1330
- const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS);
1331
- try {
1332
- const res = await fetch(`${BASE_URL}${path}`, {
1333
- method: "POST",
1334
- headers: { ...authHeaders, "Content-Type": "application/json" },
1335
- body: JSON.stringify(body),
1336
- signal: controller.signal
1337
- });
1338
- if (!res.ok) {
1339
- const errBody = await res.json().catch(() => ({}));
1340
- const msg = extractErrorMessage(errBody);
1341
- throw new Error(msg || `Console POST ${path} failed: ${res.status}`);
1342
- }
1343
- return res.json();
1344
- } finally {
1345
- clearTimeout(timeoutId);
1346
- }
1347
- }
1773
+ import { SERVER_COLLECTIONS as SERVER_COLLECTIONS3 } from "@01.software/sdk";
1348
1774
 
1349
1775
  // src/lib/collection-schema.ts
1350
1776
  async function getCollectionSchema(collection) {
1351
1777
  const apiKey = resolveApiKey();
1352
- return consoleGet(
1778
+ const data = await consoleGet(
1353
1779
  `/api/tenants/schema/${encodeURIComponent(collection)}`,
1354
1780
  apiKey
1355
1781
  );
1782
+ return collectionSchemaResponseSchema.parse(data);
1356
1783
  }
1357
1784
 
1358
1785
  // src/tools/get-collection-schema.ts
1359
- var schema27 = {
1360
- collection: z27.enum(COLLECTIONS8).describe("Collection name (required)")
1361
- };
1362
- var metadata27 = {
1786
+ var schema22 = createCollectionSchemaToolInputSchema(SERVER_COLLECTIONS3).shape;
1787
+ var metadata22 = {
1363
1788
  name: "get-collection-schema",
1364
1789
  description: "Get the authoritative tenant-aware collection schema from console. Use this before create/update to understand writable fields, hidden fields, required metadata, and collection-level visibility.",
1365
1790
  annotations: {
@@ -1383,9 +1808,6 @@ async function getCollectionSchemaTool({
1383
1808
  }
1384
1809
  }
1385
1810
 
1386
- // src/tools/get-tenant-context.ts
1387
- import { z as z28 } from "zod";
1388
-
1389
1811
  // src/lib/tenant-context.ts
1390
1812
  function getTenantContextPath(includeCounts) {
1391
1813
  return includeCounts ? "/api/tenants/context?counts=true" : "/api/tenants/context";
@@ -1396,16 +1818,12 @@ async function getTenantContext(includeCounts = false) {
1396
1818
  getTenantContextPath(includeCounts),
1397
1819
  apiKey
1398
1820
  );
1399
- return data;
1400
- }
1401
- function invalidateTenantContextCache() {
1821
+ return tenantContextResponseSchema.parse(data);
1402
1822
  }
1403
1823
 
1404
1824
  // src/tools/get-tenant-context.ts
1405
- var schema28 = {
1406
- includeCounts: z28.boolean().optional().default(false).describe("Include per-collection document counts and config status (bypasses cache, slower)")
1407
- };
1408
- var metadata28 = {
1825
+ var schema23 = tenantContextToolInputSchema.shape;
1826
+ var metadata23 = {
1409
1827
  name: "get-tenant-context",
1410
1828
  description: "Get current tenant features, active collections, and field visibility. Call this at the start of every session. Use includeCounts=true to also get per-collection document counts for setup diagnostics.",
1411
1829
  annotations: {
@@ -1415,7 +1833,9 @@ var metadata28 = {
1415
1833
  idempotentHint: true
1416
1834
  }
1417
1835
  };
1418
- async function handler({ includeCounts }) {
1836
+ async function handler({
1837
+ includeCounts
1838
+ }) {
1419
1839
  try {
1420
1840
  const ctx = await getTenantContext(includeCounts);
1421
1841
  const lines = [
@@ -1468,11 +1888,10 @@ async function handler({ includeCounts }) {
1468
1888
  }
1469
1889
  }
1470
1890
  if (ctx.config) {
1891
+ lines.push("", "## Config Status");
1471
1892
  lines.push(
1472
- "",
1473
- "## Config Status"
1893
+ `- Webhook configured: ${ctx.config.webhookConfigured ? "Yes" : "No"}`
1474
1894
  );
1475
- lines.push(`- Webhook configured: ${ctx.config.webhookConfigured ? "Yes" : "No"}`);
1476
1895
  }
1477
1896
  return toolSuccess({ context: lines.join("\n") });
1478
1897
  } catch (error) {
@@ -1481,7 +1900,7 @@ async function handler({ includeCounts }) {
1481
1900
  }
1482
1901
 
1483
1902
  // src/tools/list-configurable-fields.ts
1484
- import { z as z29 } from "zod";
1903
+ import { z as z22 } from "zod";
1485
1904
 
1486
1905
  // src/lib/field-config.ts
1487
1906
  async function fetchFieldConfigs() {
@@ -1504,12 +1923,12 @@ function invalidateFieldConfigCache() {
1504
1923
  }
1505
1924
 
1506
1925
  // src/tools/list-configurable-fields.ts
1507
- var schema29 = {
1508
- collection: z29.string().optional().describe(
1926
+ var schema24 = {
1927
+ collection: z22.string().optional().describe(
1509
1928
  "Filter by collection slug (optional \u2014 returns all if omitted). Use this filter to reduce response size when you know which collection to check."
1510
1929
  )
1511
1930
  };
1512
- var metadata29 = {
1931
+ var metadata24 = {
1513
1932
  name: "list-configurable-fields",
1514
1933
  description: "List all configurable fields for tenant collections with current visibility state. Shows which fields can be shown/hidden and their current status. Returns all collections including inactive features \u2014 cross-reference with get-tenant-context for active features. Response includes ~300 fields across 47 collections \u2014 use collection filter when possible.",
1515
1934
  annotations: {
@@ -1540,17 +1959,17 @@ async function listConfigurableFields(params) {
1540
1959
  }
1541
1960
 
1542
1961
  // src/tools/update-field-config.ts
1543
- import { z as z30 } from "zod";
1544
- var schema30 = {
1545
- collection: z30.string().min(1).describe("Collection slug (required)"),
1546
- hiddenFields: z30.array(z30.string().min(1).max(200)).max(300).describe(
1962
+ import { z as z23 } from "zod";
1963
+ var schema25 = {
1964
+ collection: z23.string().min(1).describe("Collection slug (required)"),
1965
+ hiddenFields: z23.array(z23.string().min(1).max(200)).max(300).describe(
1547
1966
  "Fields to hide (required). This is a FULL REPLACE \u2014 fields NOT in this list will be shown. Pass [] to show all fields. Use list-configurable-fields first to see available field paths."
1548
1967
  ),
1549
- isHidden: z30.boolean().optional().describe(
1968
+ isHidden: z23.boolean().optional().describe(
1550
1969
  "Hide the entire collection from Admin Panel (optional). When true, individual hiddenFields are irrelevant."
1551
1970
  )
1552
1971
  };
1553
- var metadata30 = {
1972
+ var metadata25 = {
1554
1973
  name: "update-field-config",
1555
1974
  description: "Update field visibility configuration for a tenant collection. Hidden fields are removed from the Admin Panel UI. IMPORTANT: hiddenFields is a full replace, not a merge. Always call list-configurable-fields first to see current state.",
1556
1975
  annotations: {
@@ -1568,7 +1987,6 @@ async function updateFieldConfig(params) {
1568
1987
  isHidden: params.isHidden
1569
1988
  });
1570
1989
  invalidateFieldConfigCache();
1571
- invalidateTenantContextCache();
1572
1990
  return toolSuccess({
1573
1991
  message: `Field config updated for '${params.collection}'`,
1574
1992
  data: result
@@ -1579,7 +1997,7 @@ async function updateFieldConfig(params) {
1579
1997
  }
1580
1998
 
1581
1999
  // src/tools/sdk-get-recipe.ts
1582
- import { z as z31 } from "zod";
2000
+ import { z as z24 } from "zod";
1583
2001
 
1584
2002
  // src/lib/sdk-recipes.ts
1585
2003
  var recipes = {
@@ -1731,7 +2149,7 @@ const result = await client.collections.from('products').create({
1731
2149
  "Returns result.doc (not the document directly)"
1732
2150
  ],
1733
2151
  relatedResources: ["docs://sdk/query-builder"],
1734
- relatedTools: ["create-collection"]
2152
+ relatedTools: ["query-collection", "get-collection-schema"]
1735
2153
  }
1736
2154
  },
1737
2155
  "update-item": {
@@ -1760,7 +2178,7 @@ const result = await client.collections.from('products').update('product-id', {
1760
2178
  "Partial updates are supported \u2014 omitted fields retain their current value"
1761
2179
  ],
1762
2180
  relatedResources: ["docs://sdk/query-builder"],
1763
- relatedTools: ["update-collection"]
2181
+ relatedTools: ["get-collection-by-id", "get-collection-schema"]
1764
2182
  }
1765
2183
  },
1766
2184
  "delete-item": {
@@ -1784,7 +2202,7 @@ console.log('Deleted:', deleted.title)`,
1784
2202
  "Throws if the item does not exist"
1785
2203
  ],
1786
2204
  relatedResources: ["docs://sdk/query-builder"],
1787
- relatedTools: ["delete-collection"]
2205
+ relatedTools: ["get-collection-by-id", "query-collection"]
1788
2206
  }
1789
2207
  },
1790
2208
  "infinite-scroll": {
@@ -1961,7 +2379,7 @@ const result = await client.collections.from('images').create(formData as unknow
1961
2379
  "Always set alt text for accessibility"
1962
2380
  ],
1963
2381
  relatedResources: ["docs://sdk/query-builder"],
1964
- relatedTools: ["create-collection"]
2382
+ relatedTools: ["query-collection", "get-collection-schema"]
1965
2383
  }
1966
2384
  },
1967
2385
  "bulk-operations": {
@@ -1997,7 +2415,7 @@ const removed = await client.collections.from('products').removeMany(
1997
2415
  "Very broad where clauses (or empty) will affect all documents in the collection"
1998
2416
  ],
1999
2417
  relatedResources: ["docs://sdk/query-builder"],
2000
- relatedTools: ["update-many-collection", "delete-many-collection"]
2418
+ relatedTools: ["query-collection", "get-collection-schema"]
2001
2419
  }
2002
2420
  }
2003
2421
  };
@@ -2011,8 +2429,8 @@ function getRecipe(goal, runtime = "both") {
2011
2429
  }
2012
2430
 
2013
2431
  // src/tools/sdk-get-recipe.ts
2014
- var schema31 = {
2015
- goal: z31.enum([
2432
+ var schema26 = {
2433
+ goal: z24.enum([
2016
2434
  "fetch-list",
2017
2435
  "fetch-by-id",
2018
2436
  "create-item",
@@ -2024,11 +2442,11 @@ var schema31 = {
2024
2442
  "file-upload",
2025
2443
  "bulk-operations"
2026
2444
  ]).describe("What the user wants to accomplish"),
2027
- runtime: z31.enum(["browser", "server", "both"]).default("both").describe("Target runtime environment"),
2028
- collection: z31.string().optional().describe("Specific collection name if applicable"),
2029
- includeExample: z31.boolean().default(true).describe("Whether to include a full code example")
2445
+ runtime: z24.enum(["browser", "server", "both"]).default("both").describe("Target runtime environment"),
2446
+ collection: z24.string().optional().describe("Specific collection name if applicable"),
2447
+ includeExample: z24.boolean().default(true).describe("Whether to include a full code example")
2030
2448
  };
2031
- var metadata31 = {
2449
+ var metadata26 = {
2032
2450
  name: "sdk-get-recipe",
2033
2451
  description: "Get a complete SDK code recipe for a specific task. Returns recommended approach, code example, and related documentation links. Use this FIRST when the user asks how to do something with the SDK.",
2034
2452
  annotations: {
@@ -2071,7 +2489,7 @@ function handler2({
2071
2489
  }
2072
2490
 
2073
2491
  // src/tools/sdk-search-docs.ts
2074
- import { z as z32 } from "zod";
2492
+ import { z as z25 } from "zod";
2075
2493
 
2076
2494
  // src/lib/sdk-doc-index.ts
2077
2495
  var docIndex = [
@@ -2085,7 +2503,7 @@ var docIndex = [
2085
2503
  {
2086
2504
  title: "Browser Client vs Server Client",
2087
2505
  keywords: ["browser", "server", "publishable key", "secret key", "createClient", "createServerClient", "NEXT_PUBLIC_SOFTWARE_PUBLISHABLE_KEY", "SOFTWARE_PUBLISHABLE_KEY", "SOFTWARE_SECRET_KEY", "pk01_", "sk01_", "pat01_", "read-only", "full crud"],
2088
- summary: "createClient() for browser with publishableKey (read-only pk01_), createServerClient() for server with SOFTWARE_SECRET_KEY (usually sk01_, sometimes pat01_ in browser-auth-scoped flows). Never expose SECRET_KEY to the browser.",
2506
+ summary: "createClient() for browser with publishableKey (read-only pk01_), createServerClient() for server with matching SOFTWARE_PUBLISHABLE_KEY + SOFTWARE_SECRET_KEY (usually sk01_, sometimes pat01_ in scoped flows). Never expose SECRET_KEY to the browser.",
2089
2507
  resourceUri: "docs://sdk/getting-started"
2090
2508
  },
2091
2509
  // Query Builder
@@ -2246,11 +2664,11 @@ function searchDocs(query, limit = 5) {
2246
2664
  }
2247
2665
 
2248
2666
  // src/tools/sdk-search-docs.ts
2249
- var schema32 = {
2250
- query: z32.string().min(2).describe('Search keyword or phrase (e.g. "infinite scroll", "webhook", "customer login")'),
2251
- limit: z32.number().min(1).max(10).default(5).describe("Maximum results to return (1-10, default: 5)")
2667
+ var schema27 = {
2668
+ query: z25.string().min(2).describe('Search keyword or phrase (e.g. "infinite scroll", "webhook", "customer login")'),
2669
+ limit: z25.number().min(1).max(10).default(5).describe("Maximum results to return (1-10, default: 5)")
2252
2670
  };
2253
- var metadata32 = {
2671
+ var metadata27 = {
2254
2672
  name: "sdk-search-docs",
2255
2673
  description: "Search SDK documentation by keyword. Returns matching topics with summaries and resource links. Use when looking for specific SDK features or patterns.",
2256
2674
  annotations: {
@@ -2285,9 +2703,9 @@ function handler3({
2285
2703
  }
2286
2704
 
2287
2705
  // src/tools/sdk-get-auth-setup.ts
2288
- import { z as z33 } from "zod";
2289
- var schema33 = {
2290
- scenario: z33.enum([
2706
+ import { z as z26 } from "zod";
2707
+ var schema28 = {
2708
+ scenario: z26.enum([
2291
2709
  "browser-client",
2292
2710
  "server-client",
2293
2711
  "customer-auth",
@@ -2296,7 +2714,7 @@ var schema33 = {
2296
2714
  "webhook-verification"
2297
2715
  ]).describe("Authentication scenario")
2298
2716
  };
2299
- var metadata33 = {
2717
+ var metadata28 = {
2300
2718
  name: "sdk-get-auth-setup",
2301
2719
  description: "Get the current authentication setup for a specific scenario. Returns env var names, code snippets, and security notes.",
2302
2720
  annotations: {
@@ -2450,14 +2868,14 @@ function handler4({
2450
2868
  }
2451
2869
 
2452
2870
  // src/tools/sdk-get-collection-pattern.ts
2453
- import { z as z34 } from "zod";
2454
- import { COLLECTIONS as COLLECTIONS9 } from "@01.software/sdk";
2455
- var schema34 = {
2456
- collection: z34.enum(COLLECTIONS9).describe("Collection name"),
2457
- operation: z34.enum(["read", "write", "full-crud"]).default("read").describe("What operations are needed"),
2458
- surface: z34.enum(["query-builder", "react-query", "server-api"]).default("query-builder").describe("Preferred API surface")
2871
+ import { z as z27 } from "zod";
2872
+ import { COLLECTIONS, SERVER_COLLECTIONS as SERVER_COLLECTIONS4 } from "@01.software/sdk";
2873
+ var schema29 = {
2874
+ collection: z27.enum(SERVER_COLLECTIONS4).describe("Collection name"),
2875
+ operation: z27.enum(["read", "write", "full-crud"]).default("read").describe("What operations are needed"),
2876
+ surface: z27.enum(["query-builder", "react-query", "server-api"]).default("query-builder").describe("Preferred API surface")
2459
2877
  };
2460
- var metadata34 = {
2878
+ var metadata29 = {
2461
2879
  name: "sdk-get-collection-pattern",
2462
2880
  description: "Get the recommended CRUD pattern for a specific collection. Returns code examples for the chosen API surface and operation type.",
2463
2881
  annotations: {
@@ -2468,7 +2886,15 @@ var metadata34 = {
2468
2886
  }
2469
2887
  };
2470
2888
  function generatePattern(collection, operation, surface) {
2889
+ const isPublicCollection = COLLECTIONS.includes(
2890
+ collection
2891
+ );
2471
2892
  if (surface === "react-query") {
2893
+ if (!isPublicCollection) {
2894
+ throw new Error(
2895
+ `${collection} is server-only. Use surface="server-api" with createServerClient().`
2896
+ );
2897
+ }
2472
2898
  const parts2 = [];
2473
2899
  if (operation === "read") {
2474
2900
  parts2.push(
@@ -2580,17 +3006,29 @@ function generatePattern(collection, operation, surface) {
2580
3006
  }
2581
3007
  const parts = [];
2582
3008
  if (operation === "read" || operation === "full-crud") {
2583
- parts.push(
2584
- `// Read with any client (Client or ServerClient)`,
2585
- `const result = await client.collections.from('${collection}').find({`,
2586
- ` where: { status: { equals: 'published' } },`,
2587
- ` limit: 10,`,
2588
- ` sort: '-createdAt'`,
2589
- `})`,
2590
- ``,
2591
- `const item = await client.collections.from('${collection}').findById(id)`,
2592
- `const { totalDocs } = await client.collections.from('${collection}').count()`
2593
- );
3009
+ if (isPublicCollection) {
3010
+ parts.push(
3011
+ `// Read with any client (Client or ServerClient)`,
3012
+ `const result = await client.collections.from('${collection}').find({`,
3013
+ ` where: { status: { equals: 'published' } },`,
3014
+ ` limit: 10,`,
3015
+ ` sort: '-createdAt'`,
3016
+ `})`,
3017
+ ``,
3018
+ `const item = await client.collections.from('${collection}').findById(id)`,
3019
+ `const { totalDocs } = await client.collections.from('${collection}').count()`
3020
+ );
3021
+ } else {
3022
+ parts.push(
3023
+ `// Server-only collection: use ServerClient`,
3024
+ `const result = await serverClient.collections.from('${collection}').find({`,
3025
+ ` limit: 10,`,
3026
+ ` sort: '-createdAt'`,
3027
+ `})`,
3028
+ ``,
3029
+ `const item = await serverClient.collections.from('${collection}').findById(id)`
3030
+ );
3031
+ }
2594
3032
  }
2595
3033
  if (operation === "write" || operation === "full-crud") {
2596
3034
  parts.push(
@@ -2605,6 +3043,7 @@ function generatePattern(collection, operation, surface) {
2605
3043
  code: parts.join("\n"),
2606
3044
  notes: [
2607
3045
  "Query Builder works with both Client and ServerClient for reads",
3046
+ !isPublicCollection ? "This collection is server-only" : "",
2608
3047
  operation !== "read" ? "Write operations require ServerClient" : ""
2609
3048
  ].filter(Boolean)
2610
3049
  };
@@ -2624,7 +3063,6 @@ function handler5({
2624
3063
  relatedTools: [
2625
3064
  "query-collection",
2626
3065
  "get-collection-by-id",
2627
- ...operation !== "read" ? ["create-collection", "update-collection", "delete-collection"] : [],
2628
3066
  "get-collection-schema"
2629
3067
  ],
2630
3068
  relatedResources: [
@@ -2638,14 +3076,14 @@ function handler5({
2638
3076
  }
2639
3077
 
2640
3078
  // src/prompts/sdk-usage-guide.ts
2641
- import { z as z35 } from "zod";
2642
- var schema35 = {
2643
- goal: z35.string().describe('What the user wants to accomplish (e.g., "query product list", "create order")'),
2644
- runtime: z35.enum(["browser", "server"]).optional().describe("Target runtime: browser (React/Next.js client) or server (Node.js)"),
2645
- surface: z35.enum(["query-builder", "react-query", "customer-api", "server-api"]).optional().describe("Preferred API surface"),
2646
- collection: z35.string().optional().describe("Specific collection if relevant")
3079
+ import { z as z28 } from "zod";
3080
+ var schema30 = {
3081
+ goal: z28.string().describe('What the user wants to accomplish (e.g., "query product list", "create order")'),
3082
+ runtime: z28.enum(["browser", "server"]).optional().describe("Target runtime: browser (React/Next.js client) or server (Node.js)"),
3083
+ surface: z28.enum(["query-builder", "react-query", "customer-api", "server-api"]).optional().describe("Preferred API surface"),
3084
+ collection: z28.string().optional().describe("Specific collection if relevant")
2647
3085
  };
2648
- var metadata35 = {
3086
+ var metadata30 = {
2649
3087
  name: "sdk-usage-guide",
2650
3088
  title: "SDK Usage Guide",
2651
3089
  description: "Provides guidance on how to perform a specific task using the 01.software SDK",
@@ -2782,14 +3220,14 @@ You can perform the "${goal}" task by following the patterns above.`;
2782
3220
  }
2783
3221
 
2784
3222
  // src/prompts/collection-query-help.ts
2785
- import { z as z36 } from "zod";
2786
- import { COLLECTIONS as COLLECTIONS10 } from "@01.software/sdk";
2787
- var schema36 = {
2788
- collection: z36.enum(COLLECTIONS10).describe("Collection name"),
2789
- operation: z36.enum(["find", "create", "update", "delete"]).describe("Operation to perform (find, create, update, delete)"),
2790
- filters: z36.string().optional().describe("Filter conditions (JSON string, optional)")
3223
+ import { z as z29 } from "zod";
3224
+ import { COLLECTIONS as COLLECTIONS2, SERVER_COLLECTIONS as SERVER_COLLECTIONS5 } from "@01.software/sdk";
3225
+ var schema31 = {
3226
+ collection: z29.enum(SERVER_COLLECTIONS5).describe("Collection name"),
3227
+ operation: z29.enum(["find", "create", "update", "delete"]).describe("Operation to perform (find, create, update, delete)"),
3228
+ filters: z29.string().optional().describe("Filter conditions (JSON string, optional)")
2791
3229
  };
2792
- var metadata36 = {
3230
+ var metadata31 = {
2793
3231
  name: "collection-query-help",
2794
3232
  title: "Collection Query Help",
2795
3233
  description: "Provides guidance on how to write queries for a specific collection",
@@ -2806,6 +3244,11 @@ Filter conditions:
2806
3244
  \`\`\`json
2807
3245
  ${filters}
2808
3246
  \`\`\`` : "";
3247
+ const isPublicCollection = COLLECTIONS2.includes(
3248
+ collection
3249
+ );
3250
+ const readClientName = isPublicCollection ? "client" : "serverClient";
3251
+ const readClientNote = isPublicCollection ? "Client or ServerClient" : "ServerClient only";
2809
3252
  return `How to perform "${operation}" operation on "${collection}" collection:${filterExample}
2810
3253
 
2811
3254
  ## Collection: ${collection}
@@ -2816,26 +3259,26 @@ ${filters}
2816
3259
  \`\`\`typescript
2817
3260
  import { createClient, createServerClient } from '@01.software/sdk'
2818
3261
 
2819
- // Client (read-only)
3262
+ // Client (read-only public collections)
2820
3263
  const client = createClient({
2821
3264
  publishableKey: process.env.NEXT_PUBLIC_SOFTWARE_PUBLISHABLE_KEY!
2822
3265
  })
2823
3266
 
2824
- // Server client (full CRUD)
3267
+ // Server client (server/public collections, full CRUD)
2825
3268
  const serverClient = createServerClient({
2826
3269
  publishableKey: process.env.SOFTWARE_PUBLISHABLE_KEY!,
2827
3270
  secretKey: process.env.SOFTWARE_SECRET_KEY!
2828
3271
  })
2829
3272
 
2830
- ${operation === "find" ? `// Query ${collection} collection with Query Builder
3273
+ ${operation === "find" ? `// Query ${collection} collection with Query Builder (${readClientNote})
2831
3274
  // find() returns PayloadFindResponse with docs array and pagination
2832
- const result = await client.collections.from('${collection}').find(${filters ? `{
3275
+ const result = await ${readClientName}.collections.from('${collection}').find(${filters ? `{
2833
3276
  where: ${filters}
2834
3277
  }` : ""})
2835
3278
  // result.docs - array of items
2836
3279
  // result.totalDocs, result.page, result.totalPages, result.hasNextPage, ...
2837
3280
 
2838
- // Using React Hook
3281
+ ${isPublicCollection ? `// Using React Hook
2839
3282
  const { data, isLoading, error } = client.query.useQuery({
2840
3283
  collection: '${collection}',
2841
3284
  options: { limit: 10 }
@@ -2845,19 +3288,19 @@ const { data, isLoading, error } = client.query.useQuery({
2845
3288
  const { data } = client.query.useSuspenseQuery({
2846
3289
  collection: '${collection}',
2847
3290
  options: { limit: 10 }
2848
- })` : operation === "create" ? `// Create ${collection} item (ServerClient only)
3291
+ })` : `// React hooks are browser/public only and do not support '${collection}'.`}` : operation === "create" ? `// Create ${collection} item (ServerClient only)
2849
3292
  // create() returns PayloadMutationResponse with doc and message
2850
- const result = await serverClient.from('${collection}').create({
3293
+ const result = await serverClient.collections.from('${collection}').create({
2851
3294
  // Enter fields
2852
3295
  })
2853
3296
  // result.doc - created item, result.message` : operation === "update" ? `// Update ${collection} item (ServerClient only)
2854
3297
  // update() returns PayloadMutationResponse with doc and message
2855
- const result = await serverClient.from('${collection}').update(id, {
3298
+ const result = await serverClient.collections.from('${collection}').update(id, {
2856
3299
  // Fields to update
2857
3300
  })
2858
3301
  // result.doc - updated item, result.message` : `// Delete ${collection} item (ServerClient only)
2859
3302
  // remove() returns the deleted document directly
2860
- await serverClient.from('${collection}').remove(id)`}
3303
+ await serverClient.collections.from('${collection}').remove(id)`}
2861
3304
  \`\`\`
2862
3305
 
2863
3306
  ### Useful Tips
@@ -2865,7 +3308,7 @@ await serverClient.from('${collection}').remove(id)`}
2865
3308
  ${operation === "find" ? `- Use \`where\` option for filtering (Payload query syntax)
2866
3309
  - Use \`limit\` and \`page\` for pagination
2867
3310
  - Use \`sort\` for sorting (prefix with "-" for descending)
2868
- - React Query hooks: useQuery, useSuspenseQuery, useInfiniteQuery
3311
+ - ${isPublicCollection ? "React Query hooks: useQuery, useSuspenseQuery, useInfiniteQuery" : "React Query hooks are browser/public only; use ServerClient for this collection"}
2869
3312
  - Cache utilities: invalidateQueries, prefetchQuery, getQueryData, setQueryData` : operation === "create" ? `- Requires ServerClient with secretKey
2870
3313
  - Check required fields
2871
3314
  - TypeScript recommended for type safety` : operation === "update" ? `- Requires ServerClient with secretKey
@@ -2876,16 +3319,16 @@ ${operation === "find" ? `- Use \`where\` option for filtering (Payload query sy
2876
3319
  }
2877
3320
 
2878
3321
  // src/prompts/order-flow-guide.ts
2879
- import { z as z37 } from "zod";
2880
- var schema37 = {
2881
- scenario: z37.enum([
3322
+ import { z as z30 } from "zod";
3323
+ var schema32 = {
3324
+ scenario: z30.enum([
2882
3325
  "simple-order",
2883
3326
  "cart-checkout",
2884
3327
  "return-refund",
2885
3328
  "fulfillment-tracking"
2886
3329
  ]).describe("Order flow scenario")
2887
3330
  };
2888
- var metadata37 = {
3331
+ var metadata32 = {
2889
3332
  name: "order-flow-guide",
2890
3333
  title: "Order Flow Guide",
2891
3334
  description: "Provides step-by-step guidance for ecommerce order flows including creation, checkout, returns, and fulfillment.",
@@ -2900,8 +3343,8 @@ var SCENARIOS = {
2900
3343
  - Provide: orderNumber, customerSnapshot (email required), shippingAddress, orderItems, totalAmount
2901
3344
  - Optional: pgPaymentId (omit for free orders), shippingAmount, discountCode
2902
3345
 
2903
- 2. **Payment Confirmation** \u2192 \`update-order\` tool
2904
- - Update status to \`paid\` after payment gateway confirms
3346
+ 2. **Payment Confirmation** \u2192 \`update-transaction\` tool
3347
+ - Confirm provider payment with pgPaymentId, paymentKey, and amount
2905
3348
  - Stock is automatically adjusted (stock -= qty, reservedStock += qty)
2906
3349
 
2907
3350
  3. **Fulfillment** \u2192 \`create-fulfillment\` tool
@@ -2928,8 +3371,13 @@ const order = await client.commerce.orders.create({
2928
3371
  pgPaymentId: 'pay_xxx' // omit for free orders
2929
3372
  })
2930
3373
 
2931
- // 2. After payment confirmed
2932
- await client.commerce.orders.update({ orderNumber: 'ORD-240101-001', status: 'paid' })
3374
+ // 2. After payment confirmed by provider
3375
+ await client.commerce.orders.updateTransaction({
3376
+ pgPaymentId: 'pay_xxx',
3377
+ status: 'paid',
3378
+ paymentKey: 'payment_key_xxx',
3379
+ amount: 59800
3380
+ })
2933
3381
 
2934
3382
  // 3. Ship items
2935
3383
  await client.commerce.orders.createFulfillment({
@@ -2947,7 +3395,7 @@ await client.commerce.orders.createFulfillment({
2947
3395
  2. **Apply Discount** (optional) \u2192 \`apply-discount\` tool
2948
3396
  3. **Calculate Shipping** \u2192 \`calculate-shipping\` tool
2949
3397
  4. **Checkout** \u2192 \`checkout\` tool (converts cart to order)
2950
- 5. **Payment** \u2192 \`update-order\` or \`update-transaction\`
3398
+ 5. **Payment** \u2192 \`update-transaction\` for provider-verified paid transitions
2951
3399
 
2952
3400
  ### Key Points
2953
3401
  - Cart has a customer linked \u2014 auto-copied to order on checkout
@@ -2984,7 +3432,7 @@ const order = await client.commerce.orders.checkout({
2984
3432
  1. **Return with Refund** \u2192 \`return-with-refund\` tool
2985
3433
  - Handles return + stock restoration + transaction update in one call
2986
3434
  - Return immediately completed (bypasses FSM)
2987
- - Requires pgPaymentId to identify which transaction to refund
3435
+ - Requires pgPaymentId and paymentKey for provider-verified refund
2988
3436
 
2989
3437
  ### Key Points
2990
3438
  - Full refund: original transaction \u2192 \`canceled\`
@@ -3001,7 +3449,8 @@ await client.commerce.orders.returnWithRefund({
3001
3449
  reasonDetail: 'Product arrived damaged',
3002
3450
  returnItems: [{ orderItem: 'oi-id', quantity: 1 }],
3003
3451
  refundAmount: 29900,
3004
- pgPaymentId: 'pay_xxx'
3452
+ pgPaymentId: 'pay_xxx',
3453
+ paymentKey: 'payment_key_xxx'
3005
3454
  })
3006
3455
  \`\`\``,
3007
3456
  "fulfillment-tracking": `## Fulfillment & Tracking
@@ -3064,9 +3513,9 @@ ${SCENARIOS[scenario] || "Unknown scenario."}
3064
3513
  }
3065
3514
 
3066
3515
  // src/prompts/feature-setup-guide.ts
3067
- import { z as z38 } from "zod";
3068
- var schema38 = {
3069
- feature: z38.enum([
3516
+ import { z as z31 } from "zod";
3517
+ var schema33 = {
3518
+ feature: z31.enum([
3070
3519
  "ecommerce",
3071
3520
  "customers",
3072
3521
  "articles",
@@ -3081,7 +3530,7 @@ var schema38 = {
3081
3530
  "community"
3082
3531
  ]).describe("Feature to get setup guide for")
3083
3532
  };
3084
- var metadata38 = {
3533
+ var metadata33 = {
3085
3534
  name: "feature-setup-guide",
3086
3535
  title: "Feature Setup Guide",
3087
3536
  description: "Setup checklist and remediation guide for a tenant feature. Load before using get-tenant-context to diagnose setup gaps.",
@@ -3094,8 +3543,8 @@ var FEATURES = {
3094
3543
 
3095
3544
  ### Required Collections (count > 0)
3096
3545
 
3097
- 1. **products** \u2014 Use \`create-collection\` with \`collection='products'\`
3098
- - Minimum fields: \`{ title, slug, status: 'active' }\`
3546
+ 1. **products** \u2014 Create via Console UI or SDK \`client.collections.from('products').create({ ... })\`
3547
+ - Minimum fields: \`{ title, slug, status: 'published' }\`
3099
3548
 
3100
3549
  2. **product-variants** \u2014 At least 1 sellable variant per product
3101
3550
  - Minimum fields: \`{ product, title, price, stock }\`
@@ -3128,7 +3577,8 @@ customer-addresses
3128
3577
 
3129
3578
  ### Optional Collections
3130
3579
 
3131
- customer-groups \u2014 Use \`create-collection\` with \`collection='customer-groups'\`, \`{ title }\`
3580
+ - customer-groups \u2014 Console/server-scoped segmentation for VIP coupons and campaigns. Use \`createServerClient().collections.from('customer-groups')\`.
3581
+ - customer-profile-lists \u2014 Public profile display/ranking lists for storefronts. Browser reads may use \`client.collections.from('customer-profile-lists')\`.
3132
3582
 
3133
3583
  ### Config
3134
3584
 
@@ -3139,10 +3589,10 @@ customer-groups \u2014 Use \`create-collection\` with \`collection='customer-gro
3139
3589
  ### Required Collections (count > 0)
3140
3590
 
3141
3591
  1. **articles** \u2014 At least 1 article
3142
- - Minimum fields: \`{ title, slug }\`
3592
+ - Minimum fields: \`{ title, slug, status: 'published' }\`
3143
3593
 
3144
3594
  2. **article-authors** \u2014 At least 1 author
3145
- - Minimum fields: \`{ title, slug }\`
3595
+ - Minimum fields: \`{ title, slug, status: 'published' }\`
3146
3596
  - Link authors to articles via the \`authors\` relationship field
3147
3597
 
3148
3598
  ### Optional Collections
@@ -3157,7 +3607,7 @@ article-categories, article-tags`,
3157
3607
 
3158
3608
  2. **document-types** \u2014 At least 1 type
3159
3609
  - Minimum fields: \`{ title, slug }\`
3160
- - Link document type via \`documentType\` relationship field
3610
+ - Link document type via \`type\` relationship field
3161
3611
 
3162
3612
  ### Optional Collections
3163
3613
 
@@ -3167,10 +3617,10 @@ document-categories`,
3167
3617
  ### Required Collections (count > 0)
3168
3618
 
3169
3619
  1. **playlists** \u2014 At least 1 playlist
3170
- - Minimum fields: \`{ title, slug }\`
3620
+ - Minimum fields: \`{ title, slug, status: 'published' }\`
3171
3621
 
3172
3622
  2. **tracks** \u2014 At least 1 track
3173
- - Minimum fields: \`{ title }\`
3623
+ - Minimum fields: \`{ title, sourceUrl, status: 'published' }\`
3174
3624
 
3175
3625
  3. **playlists.tracks** \u2014 Link at least 1 track from a playlist
3176
3626
  - Minimum fields: \`{ tracks: [trackId] }\`
@@ -3183,11 +3633,11 @@ playlist-categories, playlist-tags, track-categories, track-tags, track-assets`,
3183
3633
  ### Required Collections (count > 0)
3184
3634
 
3185
3635
  1. **galleries** \u2014 At least 1 gallery
3186
- - Minimum fields: \`{ title, slug }\`
3636
+ - Minimum fields: \`{ title, slug, status: 'published' }\`
3187
3637
 
3188
3638
  2. **gallery-items** \u2014 At least 1 item per gallery
3189
3639
  - References \`images\` collection (non-upload)
3190
- - Minimum fields: \`{ gallery, image }\`
3640
+ - Minimum fields: \`{ gallery, image, status: 'published' }\`
3191
3641
 
3192
3642
  ### Optional Collections
3193
3643
 
@@ -3197,7 +3647,7 @@ gallery-categories, gallery-tags`,
3197
3647
  ### Required Collections (count > 0)
3198
3648
 
3199
3649
  1. **links** \u2014 At least 1 link
3200
- - Minimum fields: \`{ title, slug, url }\`
3650
+ - Minimum fields: \`{ title, slug, url, status: 'published' }\`
3201
3651
 
3202
3652
  ### Optional Collections
3203
3653
 
@@ -3269,21 +3719,23 @@ comments, reactions, bookmarks, reports, community-bans
3269
3719
 
3270
3720
  ### Optional Collections
3271
3721
 
3272
- post-categories`
3722
+ post-categories, customer-profile-lists`
3273
3723
  };
3274
- function featureSetupGuide({ feature }) {
3724
+ function featureSetupGuide({
3725
+ feature
3726
+ }) {
3275
3727
  return `# Feature Setup Guide: ${feature}
3276
3728
 
3277
3729
  ${FEATURES[feature] || "Unknown feature."}
3278
3730
 
3279
3731
  ## Related MCP Tools
3280
3732
  - \`get-tenant-context\` \u2014 check current collection counts and feature status
3281
- - \`create-collection\` \u2014 create required collection documents
3282
- - \`query-collection\` \u2014 verify existing documents in a collection`;
3733
+ - \`query-collection\` \u2014 verify existing documents in a collection
3734
+ - \`get-collection-schema\` \u2014 inspect tenant-aware fields before creating data via SDK or Console UI`;
3283
3735
  }
3284
3736
 
3285
3737
  // src/resources/(config)/app.ts
3286
- var metadata39 = {
3738
+ var metadata34 = {
3287
3739
  name: "app-config",
3288
3740
  title: "Application Config",
3289
3741
  description: "01.software SDK and MCP server configuration information"
@@ -3294,7 +3746,8 @@ function handler6() {
3294
3746
  ## Server Info
3295
3747
  - **Name**: 01.software MCP Server
3296
3748
  - **Version**: 0.1.0
3297
- - **Transport**: HTTP (Streamable)
3749
+ - **Hosted transport**: HTTP (Streamable)
3750
+ - **Local transport**: stdio through \`npx @01.software/cli mcp\`
3298
3751
 
3299
3752
  ## Authentication
3300
3753
 
@@ -3305,45 +3758,9 @@ HTTP MCP uses OAuth discovery and Authorization Code + PKCE.
3305
3758
  url = "https://mcp.01.software/mcp"
3306
3759
  \`\`\`
3307
3760
 
3308
- ## Available Tools (34)
3309
-
3310
- ### Generic CRUD (7)
3311
- - \`query-collection\` - Query collection with filters, pagination, sorting
3312
- - \`get-collection-by-id\` - Get single item by ID
3313
- - \`create-collection\` - Create new item
3314
- - \`update-collection\` - Update existing item
3315
- - \`delete-collection\` - Delete item (destructive)
3316
- - \`update-many-collection\` - Bulk update items matching filter
3317
- - \`delete-many-collection\` - Bulk delete items matching filter (destructive)
3318
-
3319
- ### Orders (7)
3320
- - \`create-order\` - Create a new order with products and shipping
3321
- - \`get-order\` - Get order details by order number
3322
- - \`update-order\` - Update order status
3323
- - \`checkout\` - Convert cart to order
3324
- - \`create-fulfillment\` - Create fulfillment for order items
3325
- - \`update-fulfillment\` - Update fulfillment status, carrier, and tracking
3326
- - \`update-transaction\` - Update transaction status
3327
-
3328
- ### Returns (3)
3329
- - \`create-return\` - Create a return request
3330
- - \`update-return\` - Update return status
3331
- - \`return-with-refund\` - Process return with refund atomically
3332
-
3333
- ### Cart (6)
3334
- - \`add-cart-item\` - Add item to cart
3335
- - \`update-cart-item\` - Update cart item quantity
3336
- - \`remove-cart-item\` - Remove item from cart
3337
- - \`apply-discount\` - Apply discount code to cart
3338
- - \`remove-discount\` - Remove discount from cart
3339
- - \`clear-cart\` - Remove all items from cart
3340
-
3341
- ### Validation (2)
3342
- - \`validate-discount\` - Validate discount code
3343
- - \`calculate-shipping\` - Calculate shipping fee
3344
-
3345
- ### Product (1)
3346
- - \`stock-check\` - Check product option stock availability
3761
+ ## Hosted HTTP OAuth Tools (8)
3762
+
3763
+ The hosted HTTP MCP endpoint at https://mcp.01.software/mcp exposes only these OAuth-safe tools:
3347
3764
 
3348
3765
  ### Schema (1)
3349
3766
  - \`get-collection-schema\` - Get authoritative tenant-aware collection schema
@@ -3361,6 +3778,16 @@ url = "https://mcp.01.software/mcp"
3361
3778
  - \`sdk-get-auth-setup\` - Get framework-specific auth setup guidance
3362
3779
  - \`sdk-get-collection-pattern\` - Get collection-specific usage patterns
3363
3780
 
3781
+ ## Local CLI Stdio Surface (29)
3782
+
3783
+ For trusted local server-key workflows, start the stdio server:
3784
+
3785
+ \`\`\`bash
3786
+ npx @01.software/cli mcp
3787
+ \`\`\`
3788
+
3789
+ Local stdio can expose generic read, order, return, cart, validation, stock, schema, tenant context, field config, and guidance tools. Generic collection write tools (create/update/delete/update-many/delete-many) are intentionally absent on every transport; use the SDK server client for generic writes.
3790
+
3364
3791
  ## Rate Limits
3365
3792
 
3366
3793
  Rate limits depend on your tenant plan:
@@ -3372,80 +3799,96 @@ Rate limits depend on your tenant plan:
3372
3799
  }
3373
3800
 
3374
3801
  // src/resources/(collections)/schema.ts
3375
- import { COLLECTIONS as COLLECTIONS11 } from "@01.software/sdk";
3376
- var metadata40 = {
3802
+ import { COLLECTIONS as COLLECTIONS3 } from "@01.software/sdk";
3803
+ var metadata35 = {
3377
3804
  name: "collections-schema",
3378
3805
  title: "Collection Schema Info",
3379
3806
  description: "Available collections and their schema information"
3380
3807
  };
3808
+ var COLLECTIONS_BY_CATEGORY = {
3809
+ "Tenant Management": ["tenants", "tenant-metadata", "tenant-logos"],
3810
+ Products: [
3811
+ "products",
3812
+ "product-variants",
3813
+ "product-options",
3814
+ "product-option-values",
3815
+ "product-categories",
3816
+ "product-tags",
3817
+ "product-collections"
3818
+ ],
3819
+ Brands: ["brands", "brand-logos"],
3820
+ "Orders & Fulfillment": [
3821
+ "orders",
3822
+ "order-items",
3823
+ "transactions",
3824
+ "fulfillments",
3825
+ "fulfillment-items"
3826
+ ],
3827
+ "Shipping & Returns": ["returns", "return-items", "shipping-policies"],
3828
+ Customers: [
3829
+ "customers",
3830
+ "customer-profiles",
3831
+ "customer-profile-lists",
3832
+ "customer-addresses"
3833
+ ],
3834
+ Carts: ["carts", "cart-items"],
3835
+ "Discounts & Promotions": ["discounts", "promotions"],
3836
+ Documents: ["documents", "document-categories", "document-types"],
3837
+ Articles: [
3838
+ "articles",
3839
+ "article-authors",
3840
+ "article-categories",
3841
+ "article-tags"
3842
+ ],
3843
+ Community: [
3844
+ "posts",
3845
+ "comments",
3846
+ "reactions",
3847
+ "reaction-types",
3848
+ "bookmarks",
3849
+ "post-categories",
3850
+ "reports",
3851
+ "community-bans"
3852
+ ],
3853
+ Playlists: [
3854
+ "playlists",
3855
+ "tracks",
3856
+ "playlist-categories",
3857
+ "playlist-tags",
3858
+ "track-categories",
3859
+ "track-tags"
3860
+ ],
3861
+ Galleries: [
3862
+ "galleries",
3863
+ "gallery-items",
3864
+ "gallery-categories",
3865
+ "gallery-tags"
3866
+ ],
3867
+ Links: ["links", "link-categories", "link-tags"],
3868
+ Canvas: [
3869
+ "canvases",
3870
+ "canvas-node-types",
3871
+ "canvas-edge-types",
3872
+ "canvas-categories",
3873
+ "canvas-tags",
3874
+ "canvas-nodes",
3875
+ "canvas-edges"
3876
+ ],
3877
+ Videos: ["videos", "video-categories", "video-tags"],
3878
+ "Live Streams": ["live-streams"],
3879
+ Images: ["images"],
3880
+ Forms: ["forms", "form-submissions"],
3881
+ Events: [
3882
+ "event-calendars",
3883
+ "events",
3884
+ "event-categories",
3885
+ "event-occurrences",
3886
+ "event-tags"
3887
+ ]
3888
+ };
3381
3889
  function handler7() {
3382
- const collectionsByCategory = {
3383
- "Tenant Management": ["tenants", "tenant-metadata", "tenant-logos"],
3384
- Products: [
3385
- "products",
3386
- "product-variants",
3387
- "product-options",
3388
- "product-categories",
3389
- "product-tags",
3390
- "product-collections"
3391
- ],
3392
- Brands: ["brands", "brand-logos"],
3393
- "Orders & Fulfillment": [
3394
- "orders",
3395
- "order-items",
3396
- "transactions",
3397
- "fulfillments",
3398
- "fulfillment-items"
3399
- ],
3400
- "Shipping & Returns": [
3401
- "returns",
3402
- "return-items",
3403
- "shipping-policies"
3404
- ],
3405
- Customers: ["customers", "customer-addresses", "customer-groups"],
3406
- Carts: ["carts", "cart-items"],
3407
- Discounts: ["discounts"],
3408
- Documents: ["documents", "document-categories", "document-types"],
3409
- Articles: ["articles", "article-authors", "article-categories", "article-tags"],
3410
- Community: [
3411
- "posts",
3412
- "comments",
3413
- "reactions",
3414
- "reaction-types",
3415
- "bookmarks",
3416
- "post-categories",
3417
- "reports",
3418
- "community-bans"
3419
- ],
3420
- Playlists: [
3421
- "playlists",
3422
- "tracks",
3423
- "track-assets",
3424
- "playlist-categories",
3425
- "playlist-tags",
3426
- "track-categories",
3427
- "track-tags"
3428
- ],
3429
- Galleries: [
3430
- "galleries",
3431
- "gallery-items",
3432
- "gallery-categories",
3433
- "gallery-tags"
3434
- ],
3435
- Canvas: [
3436
- "canvases",
3437
- "canvas-node-types",
3438
- "canvas-edge-types",
3439
- "canvas-categories",
3440
- "canvas-tags"
3441
- ],
3442
- Videos: ["videos", "video-categories", "video-tags"],
3443
- "Live Streams": ["live-streams"],
3444
- Images: ["images"],
3445
- Forms: ["forms", "form-submissions"]
3446
- };
3447
- const categoryDocs = Object.entries(collectionsByCategory).map(([category, collections]) => {
3448
- const collectionList = collections.filter((c) => COLLECTIONS11.includes(c)).map((c) => `- **${c}**`).join("\n");
3890
+ const categoryDocs = Object.entries(COLLECTIONS_BY_CATEGORY).map(([category, collections]) => {
3891
+ const collectionList = collections.filter((c) => COLLECTIONS3.includes(c)).map((c) => `- **${c}**`).join("\n");
3449
3892
  return `## ${category}
3450
3893
  ${collectionList}`;
3451
3894
  }).join("\n\n");
@@ -3466,6 +3909,10 @@ Each collection supports the following operations:
3466
3909
  - \`updateMany(where, data)\` - Bulk update items matching filter
3467
3910
  - \`removeMany(where)\` - Bulk delete items matching filter
3468
3911
 
3912
+ Status-managed public collections expose only \`status: 'published'\` rows to
3913
+ publishable-key reads unless server-side access explicitly includes
3914
+ unpublished statuses.
3915
+
3469
3916
  ## Query Examples
3470
3917
 
3471
3918
  ### Filtering
@@ -3487,11 +3934,11 @@ Each collection supports the following operations:
3487
3934
  }
3488
3935
  \`\`\`
3489
3936
 
3490
- Total available collections: ${COLLECTIONS11.length}`;
3937
+ Total available collections: ${COLLECTIONS3.length}`;
3491
3938
  }
3492
3939
 
3493
3940
  // src/resources/(docs)/getting-started.ts
3494
- var metadata41 = {
3941
+ var metadata36 = {
3495
3942
  name: "docs-getting-started",
3496
3943
  title: "Getting Started",
3497
3944
  description: "01.software SDK getting started guide"
@@ -3536,7 +3983,7 @@ const result = await client.collections.from('products').find({
3536
3983
  }
3537
3984
 
3538
3985
  // src/resources/(docs)/guides.ts
3539
- var metadata42 = {
3986
+ var metadata37 = {
3540
3987
  name: "docs-guides",
3541
3988
  title: "Guides",
3542
3989
  description: "01.software SDK usage guides"
@@ -3747,7 +4194,7 @@ For more detailed guides, see the [Guides page](/docs/guides).`;
3747
4194
  }
3748
4195
 
3749
4196
  // src/resources/(docs)/api.ts
3750
- var metadata43 = {
4197
+ var metadata38 = {
3751
4198
  name: "docs-api",
3752
4199
  title: "API Reference",
3753
4200
  description: "01.software SDK API reference documentation"
@@ -4033,7 +4480,7 @@ For more details, see the [full API documentation](/docs/api).`;
4033
4480
  }
4034
4481
 
4035
4482
  // src/resources/(docs)/query-builder.ts
4036
- var metadata44 = {
4483
+ var metadata39 = {
4037
4484
  name: "docs-query-builder",
4038
4485
  title: "Query Builder",
4039
4486
  description: "01.software SDK Query Builder API reference (client.collections.from)"
@@ -4227,7 +4674,7 @@ console.log(result.hasNextPage) // true
4227
4674
  }
4228
4675
 
4229
4676
  // src/resources/(docs)/react-query.ts
4230
- var metadata45 = {
4677
+ var metadata40 = {
4231
4678
  name: "docs-react-query",
4232
4679
  title: "React Query Hooks",
4233
4680
  description: "01.software SDK React Query hooks reference (client.query)"
@@ -4475,7 +4922,7 @@ export function ProductList() {
4475
4922
  }
4476
4923
 
4477
4924
  // src/resources/(docs)/server-api.ts
4478
- var metadata46 = {
4925
+ var metadata41 = {
4479
4926
  name: "docs-server-api",
4480
4927
  title: "Server-side API",
4481
4928
  description: "01.software SDK server-side API reference (client.commerce) for orders, fulfillments, returns, carts, and validation"
@@ -4616,7 +5063,7 @@ const ret = await client.commerce.orders.updateReturn({
4616
5063
  \`\`\`
4617
5064
 
4618
5065
  ### returnWithRefund()
4619
- Create a return and process refund in one atomic operation.
5066
+ Create a return and process a provider-verified refund in one atomic operation.
4620
5067
 
4621
5068
  \`\`\`typescript
4622
5069
  const result = await client.commerce.orders.returnWithRefund({
@@ -4628,6 +5075,7 @@ const result = await client.commerce.orders.returnWithRefund({
4628
5075
  ],
4629
5076
  refundAmount: 29900,
4630
5077
  pgPaymentId: 'toss-payment-id', // required
5078
+ paymentKey: 'toss-payment-key', // required for provider refund
4631
5079
  refundReceiptUrl?: 'https://...',
4632
5080
  })
4633
5081
  \`\`\`
@@ -4635,12 +5083,15 @@ const result = await client.commerce.orders.returnWithRefund({
4635
5083
  ## Transaction API
4636
5084
 
4637
5085
  ### updateTransaction()
4638
- Update a transaction status (after PG callback).
5086
+ Confirm or annotate a transaction. Paid transitions require provider
5087
+ verification; non-financial annotations can still update pending transactions.
4639
5088
 
4640
5089
  \`\`\`typescript
4641
5090
  const tx = await client.commerce.orders.updateTransaction({
4642
5091
  pgPaymentId: 'toss-payment-id',
4643
- status: 'paid', // paid | failed | canceled
5092
+ status: 'paid', // pending | paid | failed | canceled
5093
+ paymentKey: 'toss-payment-key', // required when status is paid
5094
+ amount: 29900, // required when status is paid
4644
5095
  })
4645
5096
  \`\`\`
4646
5097
 
@@ -4733,7 +5184,7 @@ const result = await client.commerce.shipping.calculate({
4733
5184
  }
4734
5185
 
4735
5186
  // src/resources/(docs)/customer-auth.ts
4736
- var metadata47 = {
5187
+ var metadata42 = {
4737
5188
  name: "docs-customer-auth",
4738
5189
  title: "Customer Auth API",
4739
5190
  description: "01.software SDK Customer Auth API reference (client.customer)"
@@ -4911,7 +5362,7 @@ async function loadProfile() {
4911
5362
  }
4912
5363
 
4913
5364
  // src/resources/(docs)/browser-vs-server.ts
4914
- var metadata48 = {
5365
+ var metadata43 = {
4915
5366
  name: "docs-browser-vs-server",
4916
5367
  title: "Client vs ServerClient",
4917
5368
  description: "When to use Client (createClient) vs ServerClient (createServerClient) in the 01.software SDK"
@@ -5070,7 +5521,7 @@ export function ProductList() {
5070
5521
  }
5071
5522
 
5072
5523
  // src/resources/(docs)/file-upload.ts
5073
- var metadata49 = {
5524
+ var metadata44 = {
5074
5525
  name: "docs-file-upload",
5075
5526
  title: "File Upload",
5076
5527
  description: "01.software SDK file upload patterns using the images collection"
@@ -5221,7 +5672,7 @@ The platform stores files in Cloudflare R2 and serves via CDN (\`cdn.01.software
5221
5672
  }
5222
5673
 
5223
5674
  // src/resources/(docs)/webhook.ts
5224
- var metadata50 = {
5675
+ var metadata45 = {
5225
5676
  name: "docs-webhook",
5226
5677
  title: "Webhooks",
5227
5678
  description: "01.software SDK webhook verification and event handling"
@@ -5335,28 +5786,71 @@ Configure webhook URLs in the 01.software console under Tenant Settings > Webhoo
5335
5786
  }
5336
5787
 
5337
5788
  // src/server.ts
5338
- function registerTool(server, schema39, meta, handler19) {
5789
+ var REGISTERED_TOOLS_BY_SERVER = /* @__PURE__ */ new WeakMap();
5790
+ function registerTool(server, schema34, meta, handler19) {
5791
+ let registered = REGISTERED_TOOLS_BY_SERVER.get(server);
5792
+ if (!registered) {
5793
+ registered = /* @__PURE__ */ new Set();
5794
+ REGISTERED_TOOLS_BY_SERVER.set(server, registered);
5795
+ }
5796
+ registered.add(meta.name);
5339
5797
  server.registerTool(
5340
5798
  meta.name,
5341
5799
  {
5342
5800
  description: meta.description,
5343
- inputSchema: schema39,
5801
+ inputSchema: schema34,
5344
5802
  annotations: meta.annotations
5345
5803
  },
5346
5804
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
5347
5805
  async (params) => {
5348
- const result = await handler19(params);
5349
- return { content: [{ type: "text", text: result }] };
5806
+ const ctx = tenantAuthContext();
5807
+ if (ctx) {
5808
+ const decision = evaluateToolPolicy(meta.name, ctx.scopes);
5809
+ if (!decision.allowed) {
5810
+ const status = decision.reason === "insufficient_scope" ? 403 : 500;
5811
+ return {
5812
+ content: [
5813
+ {
5814
+ type: "text",
5815
+ text: toolError({
5816
+ status,
5817
+ reason: decision.reason,
5818
+ message: decision.message
5819
+ })
5820
+ }
5821
+ ]
5822
+ };
5823
+ }
5824
+ }
5825
+ const activeSummary = currentMcpTelemetrySummary();
5826
+ const ownSummary = activeSummary || hasRequestContext() ? null : createMcpTelemetrySummary("stdio");
5827
+ const summary = activeSummary ?? ownSummary;
5828
+ let result = null;
5829
+ try {
5830
+ result = await handler19(params);
5831
+ return { content: [{ type: "text", text: result }] };
5832
+ } finally {
5833
+ if (summary) {
5834
+ recordMcpToolResult({
5835
+ resultText: result,
5836
+ summary,
5837
+ toolName: meta.name
5838
+ });
5839
+ }
5840
+ if (ownSummary) {
5841
+ void flushMcpTelemetrySummary(ownSummary);
5842
+ }
5843
+ }
5350
5844
  }
5351
5845
  );
5352
5846
  }
5353
- function registerPrompt(server, schema39, meta, handler19) {
5847
+ function registerPrompt(server, schema34, meta, handler19) {
5354
5848
  server.registerPrompt(
5355
5849
  meta.name,
5356
5850
  {
5357
5851
  title: meta.title,
5358
5852
  description: meta.description,
5359
- argsSchema: schema39
5853
+ argsSchema: schema34
5360
5854
  },
5361
5855
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
5362
5856
  (params) => ({
@@ -5392,70 +5886,58 @@ function createServer(options = {}) {
5392
5886
  if (toolSurface === "full") {
5393
5887
  registerTool(server, schema, metadata, queryCollection);
5394
5888
  registerTool(server, schema2, metadata2, getCollectionById);
5395
- registerTool(server, schema3, metadata3, createCollection);
5396
- registerTool(server, schema4, metadata4, updateCollection);
5397
- registerTool(server, schema5, metadata5, deleteCollection);
5398
- registerTool(server, schema6, metadata6, deleteManyCollection);
5399
- registerTool(server, schema7, metadata7, updateManyCollection);
5400
- registerTool(server, schema8, metadata8, getOrder);
5401
- registerTool(server, schema9, metadata9, createOrder);
5402
- registerTool(server, schema10, metadata10, updateOrder);
5403
- registerTool(server, schema11, metadata11, checkout);
5404
- registerTool(server, schema12, metadata12, createFulfillment);
5405
- registerTool(server, schema13, metadata13, updateFulfillment);
5406
- registerTool(server, schema14, metadata14, updateTransaction);
5407
- registerTool(server, schema15, metadata15, createReturn);
5408
- registerTool(server, schema16, metadata16, updateReturn);
5409
- registerTool(server, schema17, metadata17, returnWithRefund);
5410
- registerTool(server, schema18, metadata18, addCartItem);
5411
- registerTool(server, schema19, metadata19, updateCartItem);
5412
- registerTool(server, schema20, metadata20, removeCartItem);
5413
- registerTool(server, schema21, metadata21, applyDiscount);
5414
- registerTool(server, schema22, metadata22, removeDiscount);
5415
- registerTool(server, schema23, metadata23, clearCart);
5416
- registerTool(server, schema24, metadata24, validateDiscount);
5417
- registerTool(server, schema25, metadata25, calculateShipping);
5418
- registerTool(server, schema26, metadata26, stockCheck);
5419
- }
5420
- registerTool(server, schema27, metadata27, getCollectionSchemaTool);
5421
- registerTool(server, schema28, metadata28, handler);
5422
- registerTool(server, schema29, metadata29, listConfigurableFields);
5423
- registerTool(server, schema30, metadata30, updateFieldConfig);
5424
- registerTool(server, schema31, metadata31, handler2);
5425
- registerTool(server, schema32, metadata32, handler3);
5426
- registerTool(server, schema33, metadata33, handler4);
5427
- registerTool(server, schema34, metadata34, handler5);
5428
- registerPrompt(server, schema35, metadata35, sdkUsageGuide);
5429
- registerPrompt(server, schema36, metadata36, collectionQueryHelp);
5430
- registerPrompt(server, schema37, metadata37, orderFlowGuide);
5431
- registerPrompt(server, schema38, metadata38, featureSetupGuide);
5432
- registerStaticResource(server, "config://app", metadata39, handler6);
5433
- registerStaticResource(server, "collections://schema", metadata40, handler7);
5434
- registerStaticResource(server, "docs://sdk/getting-started", metadata41, handler8);
5435
- registerStaticResource(server, "docs://sdk/guides", metadata42, handler9);
5436
- registerStaticResource(server, "docs://sdk/api", metadata43, handler10);
5437
- registerStaticResource(server, "docs://sdk/query-builder", metadata44, handler11);
5438
- registerStaticResource(server, "docs://sdk/react-query", metadata45, handler12);
5439
- registerStaticResource(server, "docs://sdk/server-api", metadata46, handler13);
5440
- registerStaticResource(server, "docs://sdk/customer-auth", metadata47, handler14);
5441
- registerStaticResource(server, "docs://sdk/browser-vs-server", metadata48, handler15);
5442
- registerStaticResource(server, "docs://sdk/file-upload", metadata49, handler16);
5443
- registerStaticResource(server, "docs://sdk/webhook", metadata50, handler17);
5889
+ registerTool(server, schema3, metadata3, getOrder);
5890
+ registerTool(server, schema4, metadata4, createOrder);
5891
+ registerTool(server, schema5, metadata5, updateOrder);
5892
+ registerTool(server, schema6, metadata6, checkout);
5893
+ registerTool(server, schema7, metadata7, createFulfillment);
5894
+ registerTool(server, schema8, metadata8, updateFulfillment);
5895
+ registerTool(server, schema9, metadata9, updateTransaction);
5896
+ registerTool(server, schema10, metadata10, createReturn);
5897
+ registerTool(server, schema11, metadata11, updateReturn);
5898
+ registerTool(server, schema12, metadata12, returnWithRefund);
5899
+ registerTool(server, schema13, metadata13, addCartItem);
5900
+ registerTool(server, schema14, metadata14, updateCartItem);
5901
+ registerTool(server, schema15, metadata15, removeCartItem);
5902
+ registerTool(server, schema16, metadata16, applyDiscount);
5903
+ registerTool(server, schema17, metadata17, removeDiscount);
5904
+ registerTool(server, schema18, metadata18, clearCart);
5905
+ registerTool(server, schema19, metadata19, validateDiscount);
5906
+ registerTool(server, schema20, metadata20, calculateShipping);
5907
+ registerTool(server, schema21, metadata21, stockCheck);
5908
+ }
5909
+ registerTool(server, schema22, metadata22, getCollectionSchemaTool);
5910
+ registerTool(server, schema23, metadata23, handler);
5911
+ registerTool(server, schema24, metadata24, listConfigurableFields);
5912
+ registerTool(server, schema25, metadata25, updateFieldConfig);
5913
+ registerTool(server, schema26, metadata26, handler2);
5914
+ registerTool(server, schema27, metadata27, handler3);
5915
+ registerTool(server, schema28, metadata28, handler4);
5916
+ registerTool(server, schema29, metadata29, handler5);
5917
+ registerPrompt(server, schema30, metadata30, sdkUsageGuide);
5918
+ registerPrompt(server, schema31, metadata31, collectionQueryHelp);
5919
+ registerPrompt(server, schema32, metadata32, orderFlowGuide);
5920
+ registerPrompt(server, schema33, metadata33, featureSetupGuide);
5921
+ registerStaticResource(server, "config://app", metadata34, handler6);
5922
+ registerStaticResource(server, "collections://schema", metadata35, handler7);
5923
+ registerStaticResource(server, "docs://sdk/getting-started", metadata36, handler8);
5924
+ registerStaticResource(server, "docs://sdk/guides", metadata37, handler9);
5925
+ registerStaticResource(server, "docs://sdk/api", metadata38, handler10);
5926
+ registerStaticResource(server, "docs://sdk/query-builder", metadata39, handler11);
5927
+ registerStaticResource(server, "docs://sdk/react-query", metadata40, handler12);
5928
+ registerStaticResource(server, "docs://sdk/server-api", metadata41, handler13);
5929
+ registerStaticResource(server, "docs://sdk/customer-auth", metadata42, handler14);
5930
+ registerStaticResource(server, "docs://sdk/browser-vs-server", metadata43, handler15);
5931
+ registerStaticResource(server, "docs://sdk/file-upload", metadata44, handler16);
5932
+ registerStaticResource(server, "docs://sdk/webhook", metadata45, handler17);
5444
5933
  return server;
5445
5934
  }
5446
5935
 
5447
5936
  // src/auth.ts
5448
5937
  import { createPublicKey, verify as verifySignature } from "crypto";
5449
- import {
5450
- MCP_OAUTH_ISSUER as MCP_OAUTH_ISSUER2,
5451
- MCP_RESOURCE_AUDIENCE,
5452
- MCP_SCOPES,
5453
- MCP_TENANT_CLAIM as MCP_TENANT_CLAIM2,
5454
- MCP_TENANT_ROLE_CLAIM as MCP_TENANT_ROLE_CLAIM2
5455
- } from "@01.software/auth-contracts";
5456
5938
  var ALLOWED_ALGORITHMS = /* @__PURE__ */ new Set(["RS256", "ES256"]);
5457
5939
  var DEFAULT_CLOCK_SKEW_SECONDS = 30;
5458
- var DEFAULT_JWKS_URI = `${MCP_OAUTH_ISSUER2}/.well-known/jwks.json`;
5940
+ var DEFAULT_JWKS_URI = `${MCP_OAUTH_ISSUER}/.well-known/jwks.json`;
5459
5941
  var MAX_ACCESS_TOKEN_LIFETIME_SECONDS = 300;
5460
5942
  function invalid(errorDescription) {
5461
5943
  return { valid: false, error: "invalid_token", errorDescription };
@@ -5558,7 +6040,7 @@ function validateAccessToken(token, options = {}) {
5558
6040
  if (!verifyJwtSignature(header.alg, jwk, signingInput, signature)) {
5559
6041
  return invalid("Bearer token signature is invalid");
5560
6042
  }
5561
- const issuer = options.issuer ?? MCP_OAUTH_ISSUER2;
6043
+ const issuer = options.issuer ?? MCP_OAUTH_ISSUER;
5562
6044
  if (payload.iss !== issuer) return invalid("Bearer token issuer is invalid");
5563
6045
  const audience = options.audience ?? MCP_RESOURCE_AUDIENCE;
5564
6046
  if (!audienceMatches(payload.aud, audience)) {
@@ -5581,11 +6063,11 @@ function validateAccessToken(token, options = {}) {
5581
6063
  return invalid("Bearer token is not yet valid");
5582
6064
  }
5583
6065
  if (payload.exp < nowSeconds - leeway) return invalid("Bearer token is expired");
5584
- const tenantId = payload[MCP_TENANT_CLAIM2];
6066
+ const tenantId = payload[MCP_TENANT_CLAIM];
5585
6067
  if (typeof tenantId !== "string" || tenantId.length === 0) {
5586
6068
  return invalid("Bearer token tenant_id claim is invalid");
5587
6069
  }
5588
- const tenantRole = payload[MCP_TENANT_ROLE_CLAIM2];
6070
+ const tenantRole = payload[MCP_TENANT_ROLE_CLAIM];
5589
6071
  if (tenantRole !== "tenant-admin" && tenantRole !== "tenant-editor" && tenantRole !== "tenant-viewer") {
5590
6072
  return invalid("Bearer token tenant_role claim is invalid");
5591
6073
  }
@@ -5751,24 +6233,33 @@ Resources (12): config, collections-schema, getting-started, guides, api, query-
5751
6233
  Links
5752
6234
  -----
5753
6235
 
5754
- Docs https://01.software/docs/integrations/mcp
5755
- SDK https://01.software/docs/sdk/client
5756
- API Reference https://01.software/docs/api/rest-api
6236
+ Docs https://docs.01.software/docs/developers/integrations/mcp
6237
+ SDK https://docs.01.software/docs/developers/sdk/client
6238
+ API Reference https://docs.01.software/docs/developers/api/rest-api
5757
6239
  Console https://console.01.software
5758
6240
  `;
5759
6241
  var PROTECTED_RESOURCE_METADATA = JSON.stringify({
5760
- resource: MCP_RESOURCE_AUDIENCE2,
5761
- authorization_servers: [MCP_OAUTH_ISSUER3],
5762
- scopes_supported: [MCP_SCOPES2.read, MCP_SCOPES2.write]
6242
+ resource: MCP_RESOURCE_AUDIENCE,
6243
+ authorization_servers: [MCP_OAUTH_ISSUER],
6244
+ scopes_supported: [MCP_SCOPES.read, MCP_SCOPES.write]
5763
6245
  });
6246
+ var PROTECTED_RESOURCE_METADATA_URL = new URL(
6247
+ MCP_PROTECTED_RESOURCE_METADATA_PATH,
6248
+ MCP_RESOURCE_AUDIENCE
6249
+ ).toString();
5764
6250
  var SERVICE_JWKS_PATH = "/.well-known/service-jwks.json";
5765
6251
  function writeOAuthError(res, status, error, description) {
5766
6252
  res.writeHead(status, {
5767
6253
  "Content-Type": "application/json",
5768
- "WWW-Authenticate": `Bearer resource_metadata="${MCP_PROTECTED_RESOURCE_METADATA_PATH}", error="${error}", error_description="${description}"`
6254
+ "WWW-Authenticate": `Bearer resource_metadata="${PROTECTED_RESOURCE_METADATA_URL}", error="${error}", error_description="${description}"`
5769
6255
  });
5770
6256
  res.end(JSON.stringify({ error, error_description: description }));
5771
6257
  }
6258
+ function acceptsEventStream(req) {
6259
+ const accept = getHeaderValue(req.headers, "accept");
6260
+ if (!accept) return false;
6261
+ return accept.split(",").some((entry) => entry.trim().split(";")[0]?.toLowerCase() === "text/event-stream");
6262
+ }
5772
6263
  async function handler18(req, res) {
5773
6264
  setCors(res);
5774
6265
  if (req.method === "OPTIONS") {
@@ -5777,7 +6268,7 @@ async function handler18(req, res) {
5777
6268
  return;
5778
6269
  }
5779
6270
  if (req.method === "GET") {
5780
- const pathname = new URL(req.url ?? "/", MCP_RESOURCE_AUDIENCE2).pathname;
6271
+ const pathname = new URL(req.url ?? "/", MCP_RESOURCE_AUDIENCE).pathname;
5781
6272
  if (pathname === MCP_PROTECTED_RESOURCE_METADATA_PATH) {
5782
6273
  res.setHeader("Access-Control-Allow-Origin", "*");
5783
6274
  res.writeHead(200, { "Content-Type": "application/json" });
@@ -5801,6 +6292,11 @@ async function handler18(req, res) {
5801
6292
  }
5802
6293
  return;
5803
6294
  }
6295
+ if (acceptsEventStream(req)) {
6296
+ res.writeHead(405, { "Content-Type": "application/json" });
6297
+ res.end(METHOD_NOT_ALLOWED);
6298
+ return;
6299
+ }
5804
6300
  res.writeHead(200, { "Content-Type": "text/plain; charset=utf-8" });
5805
6301
  res.end(HOME_PAGE);
5806
6302
  return;
@@ -5837,20 +6333,37 @@ async function handler18(req, res) {
5837
6333
  if (typeof value === "string") headers.set(key, value);
5838
6334
  else if (Array.isArray(value)) headers.set(key, value.join(", "));
5839
6335
  }
6336
+ const telemetrySummary = createMcpTelemetrySummary("http");
5840
6337
  await requestContext.run({ headers, auth: auth.context }, async () => {
5841
6338
  try {
5842
- const body = req.body ?? JSON.parse(await readBody(req));
5843
- await transport.handleRequest(req, res, body);
5844
- } catch {
5845
- if (!res.headersSent) {
5846
- res.writeHead(500, { "Content-Type": "application/json" });
5847
- res.end(JSON.stringify({ error: "Internal server error" }));
5848
- }
6339
+ await runWithMcpTelemetry(telemetrySummary, async () => {
6340
+ const body = req.body ?? JSON.parse(await readBody(req));
6341
+ await transport.handleRequest(req, res, body);
6342
+ });
6343
+ } catch (err) {
6344
+ writeRequestError(res, err);
5849
6345
  } finally {
6346
+ telemetrySummary.durationMs = Date.now() - telemetrySummary.startedAtMs;
5850
6347
  await close();
6348
+ await flushMcpTelemetrySummary(telemetrySummary);
5851
6349
  }
5852
6350
  });
5853
6351
  }
6352
+ function writeRequestError(res, err) {
6353
+ if (res.headersSent) return;
6354
+ if (err instanceof SyntaxError) {
6355
+ res.writeHead(400, { "Content-Type": "application/json" });
6356
+ res.end(JSON.stringify({ error: "Invalid JSON body" }));
6357
+ return;
6358
+ }
6359
+ if (err instanceof Error && err.message === "Request body too large") {
6360
+ res.writeHead(413, { "Content-Type": "application/json" });
6361
+ res.end(JSON.stringify({ error: "Request body too large" }));
6362
+ return;
6363
+ }
6364
+ res.writeHead(500, { "Content-Type": "application/json" });
6365
+ res.end(JSON.stringify({ error: "Internal server error" }));
6366
+ }
5854
6367
  export {
5855
6368
  handler18 as default
5856
6369
  };