@01.software/cli 0.9.0 → 0.10.1

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.
@@ -91,6 +91,382 @@ function parseJsonWhere(where) {
91
91
  }
92
92
  }
93
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 tenantFeatureProgressFeatureSchema = z.enum(["ecommerce"]);
129
+ var tenantFeatureProgressInputSchema = z.object({
130
+ feature: tenantFeatureProgressFeatureSchema.describe(
131
+ "Feature to inspect for tenant implementation readiness"
132
+ ),
133
+ includeEvidence: z.boolean().optional().default(false).describe("Include sanitized counts and static surface evidence")
134
+ }).strict();
135
+ var tenantFeatureProgressStatusSchema = z.enum([
136
+ "ready",
137
+ "attention",
138
+ "blocked"
139
+ ]);
140
+ var tenantFeatureProgressItemStateSchema = z.enum([
141
+ "complete",
142
+ "incomplete",
143
+ "blocked",
144
+ "attention",
145
+ "optional",
146
+ "unknown",
147
+ "manual",
148
+ "not-applicable"
149
+ ]);
150
+ var tenantFeatureProgressSeveritySchema = z.enum([
151
+ "required",
152
+ "recommended",
153
+ "optional"
154
+ ]);
155
+ var tenantFeatureProgressEvidenceValueSchema = z.union([
156
+ z.string(),
157
+ z.number(),
158
+ z.boolean(),
159
+ z.null()
160
+ ]);
161
+ var tenantFeatureProgressItemSchema = z.object({
162
+ id: z.string(),
163
+ title: z.string(),
164
+ state: tenantFeatureProgressItemStateSchema,
165
+ severity: tenantFeatureProgressSeveritySchema,
166
+ summary: z.string(),
167
+ evidence: z.record(z.string(), tenantFeatureProgressEvidenceValueSchema).optional()
168
+ }).strict();
169
+ var tenantFeatureProgressGroupSchema = z.object({
170
+ id: z.string(),
171
+ title: z.string(),
172
+ summary: z.string().optional(),
173
+ items: z.array(tenantFeatureProgressItemSchema)
174
+ }).strict();
175
+ var tenantFeatureProgressResponseSchema = z.object({
176
+ schemaVersion: z.literal(1),
177
+ feature: tenantFeatureProgressFeatureSchema,
178
+ status: tenantFeatureProgressStatusSchema,
179
+ generatedAt: z.string(),
180
+ tenant: z.object({
181
+ id: z.string(),
182
+ name: z.string(),
183
+ plan: z.string()
184
+ }).strict(),
185
+ capability: z.object({
186
+ effectiveFeatures: z.array(z.string()),
187
+ planBlocked: z.array(z.string()),
188
+ closureAdded: z.array(z.string())
189
+ }).strict(),
190
+ summary: z.object({
191
+ complete: z.number().int().nonnegative(),
192
+ total: z.number().int().nonnegative(),
193
+ blocking: z.number().int().nonnegative(),
194
+ manual: z.number().int().nonnegative(),
195
+ unknown: z.number().int().nonnegative()
196
+ }).strict(),
197
+ groups: z.array(tenantFeatureProgressGroupSchema)
198
+ }).strict();
199
+ var COLLECTION_SCHEMA_CONTRACT_VERSION = 1;
200
+ var collectionSchemaEndpointParamsSchema = z.object({
201
+ collectionSlug: z.string().min(1, "collectionSlug is required")
202
+ }).strict();
203
+ function createCollectionSchemaToolInputSchema(collections) {
204
+ return z.object({
205
+ collection: z.enum(collections).describe("Collection name (required)")
206
+ }).strict();
207
+ }
208
+ var collectionFieldOptionSchema = z.object({
209
+ label: z.string(),
210
+ value: z.string()
211
+ }).strict();
212
+ var collectionFieldSchema = z.lazy(
213
+ () => z.object({
214
+ name: z.string(),
215
+ path: z.string(),
216
+ type: z.string(),
217
+ required: z.literal(true).optional(),
218
+ unique: z.literal(true).optional(),
219
+ hasMany: z.literal(true).optional(),
220
+ relationTo: z.union([z.string(), z.array(z.string())]).optional(),
221
+ options: z.array(collectionFieldOptionSchema).optional(),
222
+ hidden: z.literal(true).optional(),
223
+ systemManaged: z.literal(true).optional(),
224
+ writable: z.boolean().optional(),
225
+ fields: z.array(collectionFieldSchema).optional()
226
+ }).strict()
227
+ );
228
+ var collectionSchemaResponseSchema = z.object({
229
+ contractVersion: z.literal(COLLECTION_SCHEMA_CONTRACT_VERSION),
230
+ mode: z.literal("effective"),
231
+ collection: z.object({
232
+ slug: z.string(),
233
+ timestamps: z.boolean(),
234
+ alwaysActive: z.boolean(),
235
+ feature: z.string().nullable(),
236
+ systemFields: z.array(z.string()),
237
+ visibility: z.object({
238
+ collectionHidden: z.boolean(),
239
+ hiddenFields: z.array(z.string())
240
+ }).strict(),
241
+ fields: z.array(collectionFieldSchema)
242
+ }).strict()
243
+ }).strict();
244
+
245
+ // ../../packages/contracts/src/ecommerce/index.ts
246
+ import { z as z2 } from "zod";
247
+ var transactionStatusSchema = z2.enum([
248
+ "pending",
249
+ "paid",
250
+ "failed",
251
+ "canceled"
252
+ ]);
253
+ var updateTransactionSchema = z2.object({
254
+ pgPaymentId: z2.string().min(1, "pgPaymentId is required").describe("PG payment ID (required)"),
255
+ status: transactionStatusSchema.describe(
256
+ "New transaction status (required)"
257
+ ),
258
+ paymentMethod: z2.string().optional().describe("Payment method (optional)"),
259
+ receiptUrl: z2.string().optional().describe("Receipt URL (optional)"),
260
+ paymentKey: z2.string().min(1).optional().describe("Provider payment key for verified paid confirmation"),
261
+ amount: z2.number().int().positive().optional().describe("Provider-confirmed amount for verified paid confirmation")
262
+ }).strict();
263
+ var UpdateTransactionSchema = updateTransactionSchema;
264
+ var providerSlugSchema = z2.string().trim().regex(/^[a-z0-9][a-z0-9_-]{0,63}$/, "pgProvider must be lowercase slug");
265
+ var confirmPaymentSchema = z2.object({
266
+ orderNumber: z2.string().min(1).optional(),
267
+ pgPaymentId: z2.string().min(1, "pgPaymentId is required").describe("Provider payment identifier stored on the transaction"),
268
+ pgProvider: providerSlugSchema.describe(
269
+ "Payment provider slug, e.g. toss, portone, stripe"
270
+ ),
271
+ pgOrderId: z2.string().min(1).optional(),
272
+ amount: z2.number().int().nonnegative("amount must be non-negative").describe("Provider-confirmed amount in minor units"),
273
+ currency: z2.string().min(1).optional(),
274
+ paymentMethod: z2.string().optional(),
275
+ receiptUrl: z2.string().url().optional(),
276
+ approvedAt: z2.string().optional(),
277
+ providerStatus: z2.string().optional(),
278
+ providerEventId: z2.string().min(1).optional(),
279
+ confirmationSource: z2.enum([
280
+ "provider_webhook",
281
+ "provider_lookup",
282
+ "provider_api_confirm",
283
+ "manual_server"
284
+ ]).optional(),
285
+ metadata: z2.record(z2.string(), z2.unknown()).optional()
286
+ }).strict();
287
+ var returnReasonSchema = z2.enum([
288
+ "change_of_mind",
289
+ "defective",
290
+ "wrong_delivery",
291
+ "damaged",
292
+ "other"
293
+ ]);
294
+ var restockActionSchema = z2.enum(["return_to_stock", "discard"]);
295
+ var returnWithRefundItemSchema = z2.object({
296
+ orderItem: z2.union([z2.string(), z2.number()]).transform(String),
297
+ quantity: z2.number().int().positive("quantity must be a positive integer"),
298
+ restockAction: restockActionSchema.default("return_to_stock")
299
+ }).strict();
300
+ var returnWithRefundSchema = z2.object({
301
+ orderNumber: z2.string().min(1, "orderNumber is required").describe("Order number (required)"),
302
+ reason: returnReasonSchema.optional().describe("Return reason (optional)"),
303
+ reasonDetail: z2.string().optional().describe("Detailed reason text (optional)"),
304
+ 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)"),
305
+ refundAmount: z2.number().min(0, "refundAmount must be non-negative").describe("Refund amount (required, min 0)"),
306
+ pgPaymentId: z2.string().min(1, "pgPaymentId is required").describe("PG payment ID for refund (required)"),
307
+ paymentKey: z2.string().min(1).optional().describe("Provider payment key for verified refund"),
308
+ refundReceiptUrl: z2.string().optional().describe("Refund receipt URL (optional)")
309
+ }).strict();
310
+ var ReturnWithRefundSchema = returnWithRefundSchema;
311
+
312
+ // ../../packages/contracts/src/mcp/index.ts
313
+ var MCP_TOOL_CONTRACT = {
314
+ "query-collection": {
315
+ consoleRole: "tenant-viewer",
316
+ oauthScope: "mcp:read",
317
+ readOnly: true
318
+ },
319
+ "get-collection-by-id": {
320
+ consoleRole: "tenant-viewer",
321
+ oauthScope: "mcp:read",
322
+ readOnly: true
323
+ },
324
+ "get-order": {
325
+ consoleRole: "tenant-viewer",
326
+ oauthScope: "mcp:read",
327
+ readOnly: true
328
+ },
329
+ "stock-check": {
330
+ consoleRole: "tenant-viewer",
331
+ oauthScope: "mcp:read",
332
+ readOnly: true
333
+ },
334
+ "validate-discount": {
335
+ consoleRole: "tenant-viewer",
336
+ oauthScope: "mcp:read",
337
+ readOnly: true
338
+ },
339
+ "calculate-shipping": {
340
+ consoleRole: "tenant-viewer",
341
+ oauthScope: "mcp:read",
342
+ readOnly: true
343
+ },
344
+ "get-collection-schema": {
345
+ consoleRole: "tenant-viewer",
346
+ oauthScope: "mcp:read",
347
+ readOnly: true
348
+ },
349
+ "list-configurable-fields": {
350
+ consoleRole: "tenant-viewer",
351
+ oauthScope: "mcp:read",
352
+ readOnly: true
353
+ },
354
+ "get-tenant-context": {
355
+ consoleRole: "tenant-viewer",
356
+ oauthScope: "mcp:read",
357
+ readOnly: true
358
+ },
359
+ "check-feature-progress": {
360
+ consoleRole: "tenant-viewer",
361
+ oauthScope: "mcp:read",
362
+ readOnly: true
363
+ },
364
+ "add-cart-item": {
365
+ consoleRole: "tenant-editor",
366
+ oauthScope: "mcp:write",
367
+ readOnly: false
368
+ },
369
+ "update-cart-item": {
370
+ consoleRole: "tenant-editor",
371
+ oauthScope: "mcp:write",
372
+ readOnly: false
373
+ },
374
+ "remove-cart-item": {
375
+ consoleRole: "tenant-editor",
376
+ oauthScope: "mcp:write",
377
+ readOnly: false
378
+ },
379
+ "clear-cart": {
380
+ consoleRole: "tenant-editor",
381
+ oauthScope: "mcp:write",
382
+ readOnly: false
383
+ },
384
+ "apply-discount": {
385
+ consoleRole: "tenant-editor",
386
+ oauthScope: "mcp:write",
387
+ readOnly: false
388
+ },
389
+ "remove-discount": {
390
+ consoleRole: "tenant-editor",
391
+ oauthScope: "mcp:write",
392
+ readOnly: false
393
+ },
394
+ checkout: {
395
+ consoleRole: "tenant-admin",
396
+ oauthScope: "mcp:write",
397
+ readOnly: false
398
+ },
399
+ "create-order": {
400
+ consoleRole: "tenant-admin",
401
+ oauthScope: "mcp:write",
402
+ readOnly: false
403
+ },
404
+ "update-order": {
405
+ consoleRole: "tenant-admin",
406
+ oauthScope: "mcp:write",
407
+ readOnly: false
408
+ },
409
+ "create-fulfillment": {
410
+ consoleRole: "tenant-admin",
411
+ oauthScope: "mcp:write",
412
+ readOnly: false
413
+ },
414
+ "update-fulfillment": {
415
+ consoleRole: "tenant-admin",
416
+ oauthScope: "mcp:write",
417
+ readOnly: false
418
+ },
419
+ "create-return": {
420
+ consoleRole: "tenant-admin",
421
+ oauthScope: "mcp:write",
422
+ readOnly: false
423
+ },
424
+ "update-return": {
425
+ consoleRole: "tenant-admin",
426
+ oauthScope: "mcp:write",
427
+ readOnly: false
428
+ },
429
+ "return-with-refund": {
430
+ consoleRole: "tenant-admin",
431
+ oauthScope: "mcp:write",
432
+ readOnly: false
433
+ },
434
+ "update-transaction": {
435
+ consoleRole: "tenant-admin",
436
+ oauthScope: "mcp:write",
437
+ readOnly: false
438
+ },
439
+ "update-field-config": {
440
+ consoleRole: "tenant-admin",
441
+ oauthScope: "mcp:write",
442
+ readOnly: false
443
+ },
444
+ "sdk-get-recipe": {
445
+ consoleRole: "tenant-viewer",
446
+ oauthScope: "mcp:read",
447
+ readOnly: true
448
+ },
449
+ "sdk-search-docs": {
450
+ consoleRole: "tenant-viewer",
451
+ oauthScope: "mcp:read",
452
+ readOnly: true
453
+ },
454
+ "sdk-get-auth-setup": {
455
+ consoleRole: "tenant-viewer",
456
+ oauthScope: "mcp:read",
457
+ readOnly: true
458
+ },
459
+ "sdk-get-collection-pattern": {
460
+ consoleRole: "tenant-viewer",
461
+ oauthScope: "mcp:read",
462
+ readOnly: true
463
+ }
464
+ };
465
+ var MCP_TOOL_NAMES = Object.keys(MCP_TOOL_CONTRACT);
466
+ function isMcpToolName(toolName) {
467
+ return Object.prototype.hasOwnProperty.call(MCP_TOOL_CONTRACT, toolName);
468
+ }
469
+
94
470
  // src/tool-policy.ts
95
471
  var READ_ONLY_ANNOTATION = {
96
472
  readOnly: true,
@@ -190,6 +566,13 @@ var TOOL_POLICY_MANIFEST = {
190
566
  consoleSurface: "GET /api/tenants/context",
191
567
  annotationPolicy: READ_ONLY_ANNOTATION
192
568
  },
569
+ "check-feature-progress": {
570
+ category: "read-only-tenant",
571
+ oauthScope: MCP_SCOPES.read,
572
+ consoleRole: "tenant-viewer",
573
+ consoleSurface: "GET /api/tenants/feature-progress",
574
+ annotationPolicy: READ_ONLY_ANNOTATION
575
+ },
193
576
  // ── Cart mutations (mcp:write, tenant-editor) ──
194
577
  "add-cart-item": {
195
578
  category: "mutation-cart",
@@ -239,7 +622,7 @@ var TOOL_POLICY_MANIFEST = {
239
622
  exemptionReason: REASON_CART_EPHEMERAL
240
623
  },
241
624
  // ── Order mutations (mcp:write, tenant-admin) ──
242
- "checkout": {
625
+ checkout: {
243
626
  category: "mutation-order",
244
627
  oauthScope: MCP_SCOPES.write,
245
628
  consoleRole: "tenant-admin",
@@ -347,14 +730,14 @@ var TOOL_POLICY_MANIFEST = {
347
730
  }
348
731
  };
349
732
  function evaluateToolPolicy(toolName, scopes) {
350
- const entry = TOOL_POLICY_MANIFEST[toolName];
351
- if (!entry) {
733
+ if (!isMcpToolName(toolName)) {
352
734
  return {
353
735
  allowed: false,
354
736
  reason: "tool_policy_missing",
355
737
  message: `No tool-policy entry for ${toolName}`
356
738
  };
357
739
  }
740
+ const entry = TOOL_POLICY_MANIFEST[toolName];
358
741
  if (!scopes.includes(entry.oauthScope)) {
359
742
  return {
360
743
  allowed: false,
@@ -365,17 +748,12 @@ function evaluateToolPolicy(toolName, scopes) {
365
748
  return { allowed: true, entry };
366
749
  }
367
750
 
368
- // src/tools/query-collection.ts
369
- import { z } from "zod";
751
+ // src/lib/mcp-telemetry.ts
752
+ import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
753
+ import { randomUUID as randomUUID2 } from "crypto";
370
754
 
371
- // src/lib/client.ts
372
- import {
373
- CollectionClient,
374
- CommunityClient,
375
- ModerationApi,
376
- ServerCommerceClient,
377
- createServerClient
378
- } from "@01.software/sdk";
755
+ // src/lib/console-api.ts
756
+ import { createHash } from "crypto";
379
757
 
380
758
  // src/service-auth.ts
381
759
  import { createPrivateKey, randomUUID, sign as signBytes } from "crypto";
@@ -504,43 +882,209 @@ function signMcpServiceToken(context) {
504
882
  return `${signingInput}.${signature.toString("base64url")}`;
505
883
  }
506
884
 
507
- // src/lib/client.ts
885
+ // src/lib/console-api.ts
886
+ var BASE_URL = process.env.SOFTWARE_API_URL || "http://localhost:3000";
887
+ var TIMEOUT_MS = 5e3;
508
888
  var MISSING_HTTP_AUTH_CONTEXT_ERROR = "MCP HTTP requests require a validated OAuth tenant context before tool execution.";
509
- function getClient() {
889
+ function resolveAuthHeaderContext() {
510
890
  const oauthContext = tenantAuthContext();
511
891
  if (oauthContext) {
512
- const serviceToken = signMcpServiceToken(oauthContext);
513
- const client = {
514
- lastRequestId: null,
515
- commerce: void 0,
516
- collections: void 0,
517
- community: void 0
518
- };
519
- const onRequestId = (id) => {
520
- client.lastRequestId = id;
892
+ return {
893
+ apiKey: signMcpServiceToken(oauthContext),
894
+ mode: "oauth"
521
895
  };
522
- client.commerce = new ServerCommerceClient({
523
- secretKey: serviceToken,
524
- onRequestId
525
- });
526
- client.collections = new CollectionClient(
527
- "",
528
- serviceToken,
529
- void 0,
530
- void 0,
531
- onRequestId
896
+ }
897
+ if (hasRequestContext()) throw new Error(MISSING_HTTP_AUTH_CONTEXT_ERROR);
898
+ return {
899
+ apiKey: process.env.SOFTWARE_SECRET_KEY,
900
+ mode: "stdio",
901
+ publishableKey: process.env.SOFTWARE_PUBLISHABLE_KEY ?? process.env.NEXT_PUBLIC_SOFTWARE_PUBLISHABLE_KEY
902
+ };
903
+ }
904
+ function resolveApiKey() {
905
+ const { apiKey } = resolveAuthHeaderContext();
906
+ if (!apiKey || typeof apiKey !== "string") {
907
+ throw new Error(
908
+ "Authentication required. Set SOFTWARE_SECRET_KEY for stdio transport."
532
909
  );
533
- const community = new CommunityClient({ secretKey: serviceToken });
534
- const moderation = new ModerationApi({ secretKey: serviceToken, onRequestId });
535
- client.community = Object.assign(community, {
536
- moderation: {
537
- banCustomer: moderation.banCustomer.bind(moderation),
538
- unbanCustomer: moderation.unbanCustomer.bind(moderation)
539
- }
910
+ }
911
+ return apiKey;
912
+ }
913
+ function buildAuthHeaders(apiKey) {
914
+ const { mode, publishableKey } = resolveAuthHeaderContext();
915
+ const headers = {
916
+ Authorization: `Bearer ${apiKey}`
917
+ };
918
+ if (mode === "stdio" && publishableKey) {
919
+ headers["X-Publishable-Key"] = publishableKey;
920
+ }
921
+ return headers;
922
+ }
923
+ function extractErrorMessage(body) {
924
+ if (!body || typeof body !== "object") return void 0;
925
+ const b = body;
926
+ if (typeof b.error === "string") return b.error;
927
+ if (Array.isArray(b.errors) && b.errors[0]?.message) {
928
+ return String(b.errors[0].message);
929
+ }
930
+ if (typeof b.message === "string") return b.message;
931
+ return void 0;
932
+ }
933
+ async function consoleGet(path, apiKey) {
934
+ const authHeaders = buildAuthHeaders(apiKey);
935
+ const controller = new AbortController();
936
+ const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS);
937
+ try {
938
+ const res = await fetch(`${BASE_URL}${path}`, {
939
+ headers: authHeaders,
940
+ signal: controller.signal
540
941
  });
541
- return client;
942
+ if (!res.ok) {
943
+ const body = await res.json().catch(() => ({}));
944
+ const msg = extractErrorMessage(body);
945
+ throw new Error(msg || `Console GET ${path} failed: ${res.status}`);
946
+ }
947
+ return res.json();
948
+ } finally {
949
+ clearTimeout(timeoutId);
542
950
  }
543
- if (hasRequestContext()) throw new Error(MISSING_HTTP_AUTH_CONTEXT_ERROR);
951
+ }
952
+ async function consolePost(path, body, apiKey) {
953
+ const authHeaders = buildAuthHeaders(apiKey);
954
+ const controller = new AbortController();
955
+ const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS);
956
+ try {
957
+ const res = await fetch(`${BASE_URL}${path}`, {
958
+ method: "POST",
959
+ headers: { ...authHeaders, "Content-Type": "application/json" },
960
+ body: JSON.stringify(body),
961
+ signal: controller.signal
962
+ });
963
+ if (!res.ok) {
964
+ const errBody = await res.json().catch(() => ({}));
965
+ const msg = extractErrorMessage(errBody);
966
+ throw new Error(msg || `Console POST ${path} failed: ${res.status}`);
967
+ }
968
+ return res.json();
969
+ } finally {
970
+ clearTimeout(timeoutId);
971
+ }
972
+ }
973
+ async function consolePostTelemetry(path, body, apiKey) {
974
+ const authHeaders = buildAuthHeaders(apiKey);
975
+ const controller = new AbortController();
976
+ const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS);
977
+ try {
978
+ const res = await fetch(`${BASE_URL}${path}`, {
979
+ method: "POST",
980
+ headers: { ...authHeaders, "Content-Type": "application/json" },
981
+ body: JSON.stringify(body),
982
+ signal: controller.signal
983
+ });
984
+ if (!res.ok) {
985
+ const errBody = await res.json().catch(() => ({}));
986
+ const msg = extractErrorMessage(errBody);
987
+ throw new Error(msg || `Console POST ${path} failed: ${res.status}`);
988
+ }
989
+ } finally {
990
+ clearTimeout(timeoutId);
991
+ }
992
+ }
993
+
994
+ // src/lib/mcp-telemetry.ts
995
+ var TELEMETRY_ENDPOINT = "/api/tenants/mcp-telemetry";
996
+ var FLUSH_TIMEOUT_MS = 1500;
997
+ var telemetryContext = new AsyncLocalStorage2();
998
+ function createMcpTelemetrySummary(transport) {
999
+ return {
1000
+ sessionId: randomUUID2(),
1001
+ startedAtMs: Date.now(),
1002
+ successfulWriteCount: 0,
1003
+ toolCallCount: 0,
1004
+ toolCounts: /* @__PURE__ */ new Map(),
1005
+ transport
1006
+ };
1007
+ }
1008
+ function currentMcpTelemetrySummary() {
1009
+ return telemetryContext.getStore();
1010
+ }
1011
+ function runWithMcpTelemetry(summary, fn) {
1012
+ return telemetryContext.run(summary, fn);
1013
+ }
1014
+ function recordMcpToolResult(params) {
1015
+ if (!isMcpToolName(params.toolName)) return;
1016
+ const toolName = params.toolName;
1017
+ params.summary.toolCallCount += 1;
1018
+ params.summary.toolCounts.set(
1019
+ toolName,
1020
+ (params.summary.toolCounts.get(toolName) ?? 0) + 1
1021
+ );
1022
+ if (!MCP_TOOL_CONTRACT[toolName].readOnly && toolResultSucceeded(params.resultText)) {
1023
+ params.summary.successfulWriteCount += 1;
1024
+ }
1025
+ }
1026
+ function toMcpTelemetryBody(summary) {
1027
+ if (summary.toolCallCount <= 0) return null;
1028
+ const durationMs = summary.transport === "http" ? Math.max(0, summary.durationMs ?? Date.now() - summary.startedAtMs) : void 0;
1029
+ return {
1030
+ converted: summary.successfulWriteCount > 0,
1031
+ ...durationMs !== void 0 ? { durationMs } : {},
1032
+ sessionId: summary.sessionId,
1033
+ successfulWriteCount: summary.successfulWriteCount,
1034
+ toolCallCount: summary.toolCallCount,
1035
+ toolCounts: Object.fromEntries(summary.toolCounts),
1036
+ transport: summary.transport
1037
+ };
1038
+ }
1039
+ async function flushMcpTelemetrySummary(summary) {
1040
+ const body = toMcpTelemetryBody(summary);
1041
+ if (!body) return;
1042
+ await swallow(
1043
+ withTimeout(async () => {
1044
+ const apiKey = resolveApiKey();
1045
+ await consolePostTelemetry(TELEMETRY_ENDPOINT, body, apiKey);
1046
+ }, FLUSH_TIMEOUT_MS)
1047
+ );
1048
+ }
1049
+ function toolResultSucceeded(resultText) {
1050
+ if (!resultText) return false;
1051
+ try {
1052
+ const parsed = JSON.parse(resultText);
1053
+ return parsed.success === true;
1054
+ } catch {
1055
+ return false;
1056
+ }
1057
+ }
1058
+ async function withTimeout(fn, timeoutMs) {
1059
+ let timer;
1060
+ await Promise.race([
1061
+ fn(),
1062
+ new Promise((resolve) => {
1063
+ timer = setTimeout(resolve, timeoutMs);
1064
+ })
1065
+ ]);
1066
+ if (timer) clearTimeout(timer);
1067
+ }
1068
+ async function swallow(promise) {
1069
+ try {
1070
+ await promise;
1071
+ } catch {
1072
+ }
1073
+ }
1074
+
1075
+ // src/tools/query-collection.ts
1076
+ import { z as z3 } from "zod";
1077
+
1078
+ // src/lib/client.ts
1079
+ import { createServerClient } from "@01.software/sdk";
1080
+ var MISSING_HTTP_AUTH_CONTEXT_ERROR2 = "MCP HTTP requests require a validated OAuth tenant context before tool execution.";
1081
+ var HTTP_OAUTH_SDK_CLIENT_ERROR = "MCP HTTP OAuth requests cannot use SDK-backed tools. Use reviewed Console service endpoints for OAuth transport.";
1082
+ function getClient() {
1083
+ const oauthContext = tenantAuthContext();
1084
+ if (oauthContext) {
1085
+ throw new Error(HTTP_OAUTH_SDK_CLIENT_ERROR);
1086
+ }
1087
+ if (hasRequestContext()) throw new Error(MISSING_HTTP_AUTH_CONTEXT_ERROR2);
544
1088
  const secretKey = process.env.SOFTWARE_SECRET_KEY;
545
1089
  const publishableKey = process.env.SOFTWARE_PUBLISHABLE_KEY || process.env.NEXT_PUBLIC_SOFTWARE_PUBLISHABLE_KEY;
546
1090
  if (!secretKey) {
@@ -563,15 +1107,18 @@ function getClient() {
563
1107
  }
564
1108
 
565
1109
  // src/tools/query-collection.ts
566
- import { COLLECTIONS } from "@01.software/sdk";
1110
+ import { SERVER_COLLECTIONS } from "@01.software/sdk";
567
1111
  var schema = {
568
- collection: z.enum(COLLECTIONS).describe("Collection name (required)"),
569
- where: z.string().optional().describe(
1112
+ collection: z3.enum(SERVER_COLLECTIONS).describe("Collection name (required)"),
1113
+ where: z3.string().optional().describe(
570
1114
  `Filter conditions (JSON string, optional). Pass the Payload query condition object as a JSON string. Example: '{"title":{"equals":"Product name"}}'`
571
1115
  ),
572
- limit: z.number().min(1).max(100).default(10).describe("Maximum number of items to return (1-100, default: 10)."),
573
- page: z.number().optional().describe("Page number (optional). Starts from 1. Used for pagination."),
574
- sort: z.string().regex(/^-?[a-zA-Z0-9_.]+$/, 'Sort must be a field name, optionally prefixed with "-" for descending').optional().describe(
1116
+ limit: z3.number().min(1).max(100).default(10).describe("Maximum number of items to return (1-100, default: 10)."),
1117
+ page: z3.number().optional().describe("Page number (optional). Starts from 1. Used for pagination."),
1118
+ sort: z3.string().regex(
1119
+ /^-?[a-zA-Z0-9_.]+$/,
1120
+ 'Sort must be a field name, optionally prefixed with "-" for descending'
1121
+ ).optional().describe(
575
1122
  'Sort field (optional). Use "fieldName" for ascending or "-fieldName" for descending. Example: "createdAt" or "-createdAt"'
576
1123
  )
577
1124
  };
@@ -625,11 +1172,11 @@ async function queryCollection({
625
1172
  }
626
1173
 
627
1174
  // src/tools/get-collection-by-id.ts
628
- import { z as z2 } from "zod";
629
- import { COLLECTIONS as COLLECTIONS2 } from "@01.software/sdk";
1175
+ import { z as z4 } from "zod";
1176
+ import { SERVER_COLLECTIONS as SERVER_COLLECTIONS2 } from "@01.software/sdk";
630
1177
  var schema2 = {
631
- collection: z2.enum(COLLECTIONS2).describe("Collection name (required)"),
632
- id: z2.string().min(1).describe("Item ID (required)")
1178
+ collection: z4.enum(SERVER_COLLECTIONS2).describe("Collection name (required)"),
1179
+ id: z4.string().min(1).describe("Item ID (required)")
633
1180
  };
634
1181
  var metadata2 = {
635
1182
  name: "get-collection-by-id",
@@ -655,9 +1202,9 @@ async function getCollectionById({
655
1202
  }
656
1203
 
657
1204
  // src/tools/get-order.ts
658
- import { z as z3 } from "zod";
1205
+ import { z as z5 } from "zod";
659
1206
  var schema3 = {
660
- orderNumber: z3.string().min(1).describe("Order number to look up (required)")
1207
+ orderNumber: z5.string().min(1).describe("Order number to look up (required)")
661
1208
  };
662
1209
  var metadata3 = {
663
1210
  name: "get-order",
@@ -687,24 +1234,24 @@ async function getOrder({
687
1234
  }
688
1235
 
689
1236
  // src/tools/create-order.ts
690
- import { z as z4 } from "zod";
1237
+ import { z as z6 } from "zod";
691
1238
  var schema4 = {
692
- pgPaymentId: z4.string().optional().describe("PG payment ID (optional \u2014 omit for free orders)"),
693
- orderNumber: z4.string().min(1).describe("Unique order number (required)"),
694
- customerSnapshot: z4.object({
695
- name: z4.string().optional().describe("Customer name"),
696
- email: z4.string().describe("Customer email (required)"),
697
- phone: z4.string().optional().describe("Customer phone")
1239
+ pgPaymentId: z6.string().optional().describe("PG payment ID (optional \u2014 omit for free orders)"),
1240
+ orderNumber: z6.string().min(1).describe("Unique order number (required)"),
1241
+ customerSnapshot: z6.object({
1242
+ name: z6.string().optional().describe("Customer name"),
1243
+ email: z6.string().describe("Customer email (required)"),
1244
+ phone: z6.string().optional().describe("Customer phone")
698
1245
  }).describe("Customer snapshot at time of order (required)"),
699
- shippingAddress: z4.record(z4.string(), z4.unknown()).describe(
1246
+ shippingAddress: z6.record(z6.string(), z6.unknown()).describe(
700
1247
  "Shipping address object (required). Fields: postalCode, address1, address2, deliveryMessage, recipientName, phone"
701
1248
  ),
702
- orderItems: z4.array(z4.record(z4.string(), z4.unknown())).describe(
1249
+ orderItems: z6.array(z6.record(z6.string(), z6.unknown())).describe(
703
1250
  "Array of order item objects (required). Each: { product, variant, option, quantity, unitPrice?, totalPrice? }"
704
1251
  ),
705
- totalAmount: z4.number().nonnegative().describe("Total order amount (required, min 0)"),
706
- shippingAmount: z4.number().nonnegative().optional().describe("Shipping amount (optional, default 0)"),
707
- discountCode: z4.string().optional().describe("Discount code to apply (optional)")
1252
+ totalAmount: z6.number().nonnegative().describe("Total order amount (required, min 0)"),
1253
+ shippingAmount: z6.number().nonnegative().optional().describe("Shipping amount (optional, default 0)"),
1254
+ discountCode: z6.string().optional().describe("Discount code to apply (optional)")
708
1255
  };
709
1256
  var metadata4 = {
710
1257
  name: "create-order",
@@ -729,10 +1276,10 @@ async function createOrder(params) {
729
1276
  }
730
1277
 
731
1278
  // src/tools/update-order.ts
732
- import { z as z5 } from "zod";
1279
+ import { z as z7 } from "zod";
733
1280
  var schema5 = {
734
- orderNumber: z5.string().min(1).describe("Order number (required)"),
735
- status: z5.enum([
1281
+ orderNumber: z7.string().min(1).describe("Order number (required)"),
1282
+ status: z7.enum([
736
1283
  "pending",
737
1284
  "paid",
738
1285
  "failed",
@@ -769,15 +1316,15 @@ async function updateOrder({
769
1316
  }
770
1317
 
771
1318
  // src/tools/checkout.ts
772
- import { z as z6 } from "zod";
1319
+ import { z as z8 } from "zod";
773
1320
  var schema6 = {
774
- cartId: z6.string().min(1).describe("Cart ID to convert to order (required)"),
775
- pgPaymentId: z6.string().optional().describe("PG payment ID (optional \u2014 omit for free orders)"),
776
- orderNumber: z6.string().min(1).describe("Unique order number (required)"),
777
- customerSnapshot: z6.record(z6.string(), z6.unknown()).describe(
1321
+ cartId: z8.string().min(1).describe("Cart ID to convert to order (required)"),
1322
+ pgPaymentId: z8.string().optional().describe("PG payment ID (optional \u2014 omit for free orders)"),
1323
+ orderNumber: z8.string().min(1).describe("Unique order number (required)"),
1324
+ customerSnapshot: z8.record(z8.string(), z8.unknown()).describe(
778
1325
  "Customer snapshot object (required). Fields: { name?, email, phone? }"
779
1326
  ),
780
- discountCode: z6.string().optional().describe("Discount code to apply (optional)")
1327
+ discountCode: z8.string().optional().describe("Discount code to apply (optional)")
781
1328
  };
782
1329
  var metadata6 = {
783
1330
  name: "checkout",
@@ -802,17 +1349,17 @@ async function checkout(params) {
802
1349
  }
803
1350
 
804
1351
  // src/tools/create-fulfillment.ts
805
- import { z as z7 } from "zod";
1352
+ import { z as z9 } from "zod";
806
1353
  var schema7 = {
807
- orderNumber: z7.string().min(1).describe("Order number (required)"),
808
- carrier: z7.string().optional().describe("Shipping carrier name (optional)"),
809
- trackingNumber: z7.string().optional().describe(
1354
+ orderNumber: z9.string().min(1).describe("Order number (required)"),
1355
+ carrier: z9.string().optional().describe("Shipping carrier name (optional)"),
1356
+ trackingNumber: z9.string().optional().describe(
810
1357
  'Tracking number (optional). Setting carrier + tracking triggers "shipped" status'
811
1358
  ),
812
- items: z7.array(
813
- z7.object({
814
- orderItem: z7.string().min(1).describe("Order item ID"),
815
- quantity: z7.number().int().positive().describe("Quantity to fulfill")
1359
+ items: z9.array(
1360
+ z9.object({
1361
+ orderItem: z9.string().min(1).describe("Order item ID"),
1362
+ quantity: z9.number().int().positive().describe("Quantity to fulfill")
816
1363
  })
817
1364
  ).describe("Array of items to fulfill (required)")
818
1365
  };
@@ -847,16 +1394,16 @@ async function createFulfillment({
847
1394
  }
848
1395
 
849
1396
  // src/tools/update-fulfillment.ts
850
- import { z as z8 } from "zod";
1397
+ import { z as z10 } from "zod";
851
1398
  var schema8 = {
852
- fulfillmentId: z8.string().min(1).describe("Fulfillment ID (required)"),
853
- status: z8.enum(["packed", "shipped", "delivered", "failed"]).describe(
1399
+ fulfillmentId: z10.string().min(1).describe("Fulfillment ID (required)"),
1400
+ status: z10.enum(["packed", "shipped", "delivered", "failed"]).describe(
854
1401
  "New fulfillment status (required). FSM: pending\u2192packed/shipped/failed, packed\u2192shipped/failed, shipped\u2192delivered/failed"
855
1402
  ),
856
- carrier: z8.string().optional().describe(
1403
+ carrier: z10.string().optional().describe(
857
1404
  "Shipping carrier (optional, changeable only in pending/packed status)"
858
1405
  ),
859
- trackingNumber: z8.string().optional().describe(
1406
+ trackingNumber: z10.string().optional().describe(
860
1407
  "Tracking number (optional, changeable only in pending/packed status)"
861
1408
  )
862
1409
  };
@@ -890,131 +1437,6 @@ async function updateFulfillment({
890
1437
  }
891
1438
  }
892
1439
 
893
- // ../../packages/contracts/src/tenant/index.ts
894
- import { z as z9 } from "zod";
895
- var tenantFieldConfigStateSchema = z9.object({
896
- hiddenFields: z9.array(z9.string()),
897
- isHidden: z9.boolean()
898
- }).strict();
899
- var tenantContextQuerySchema = z9.object({
900
- counts: z9.literal("true").optional()
901
- }).strict();
902
- var tenantContextToolInputSchema = z9.object({
903
- includeCounts: z9.boolean().optional().default(false).describe(
904
- "Include per-collection document counts and config status (bypasses cache, slower)"
905
- )
906
- }).strict();
907
- var tenantContextResponseSchema = z9.object({
908
- tenant: z9.object({
909
- id: z9.string(),
910
- name: z9.string(),
911
- plan: z9.string(),
912
- planSource: z9.string().optional(),
913
- authoritative: z9.boolean().optional(),
914
- capabilityVersion: z9.string().optional(),
915
- isDevMode: z9.boolean()
916
- }).strict(),
917
- features: z9.array(z9.string()),
918
- collections: z9.object({
919
- active: z9.array(z9.string()),
920
- inactive: z9.array(z9.string())
921
- }).strict(),
922
- fieldConfigs: z9.record(z9.string(), tenantFieldConfigStateSchema),
923
- counts: z9.record(z9.string(), z9.number()).optional(),
924
- config: z9.object({
925
- webhookConfigured: z9.boolean()
926
- }).strict().optional()
927
- }).strict();
928
- var COLLECTION_SCHEMA_CONTRACT_VERSION = 1;
929
- var collectionSchemaEndpointParamsSchema = z9.object({
930
- collectionSlug: z9.string().min(1, "collectionSlug is required")
931
- }).strict();
932
- function createCollectionSchemaToolInputSchema(collections) {
933
- return z9.object({
934
- collection: z9.enum(collections).describe("Collection name (required)")
935
- }).strict();
936
- }
937
- var collectionFieldOptionSchema = z9.object({
938
- label: z9.string(),
939
- value: z9.string()
940
- }).strict();
941
- var collectionFieldSchema = z9.lazy(
942
- () => z9.object({
943
- name: z9.string(),
944
- path: z9.string(),
945
- type: z9.string(),
946
- required: z9.literal(true).optional(),
947
- unique: z9.literal(true).optional(),
948
- hasMany: z9.literal(true).optional(),
949
- relationTo: z9.union([z9.string(), z9.array(z9.string())]).optional(),
950
- options: z9.array(collectionFieldOptionSchema).optional(),
951
- hidden: z9.literal(true).optional(),
952
- systemManaged: z9.literal(true).optional(),
953
- writable: z9.boolean().optional(),
954
- fields: z9.array(collectionFieldSchema).optional()
955
- }).strict()
956
- );
957
- var collectionSchemaResponseSchema = z9.object({
958
- contractVersion: z9.literal(COLLECTION_SCHEMA_CONTRACT_VERSION),
959
- mode: z9.literal("effective"),
960
- collection: z9.object({
961
- slug: z9.string(),
962
- timestamps: z9.boolean(),
963
- alwaysActive: z9.boolean(),
964
- feature: z9.string().nullable(),
965
- systemFields: z9.array(z9.string()),
966
- visibility: z9.object({
967
- collectionHidden: z9.boolean(),
968
- hiddenFields: z9.array(z9.string())
969
- }).strict(),
970
- fields: z9.array(collectionFieldSchema)
971
- }).strict()
972
- }).strict();
973
-
974
- // ../../packages/contracts/src/ecommerce/index.ts
975
- import { z as z10 } from "zod";
976
- var transactionStatusSchema = z10.enum([
977
- "pending",
978
- "paid",
979
- "failed",
980
- "canceled"
981
- ]);
982
- var updateTransactionSchema = z10.object({
983
- pgPaymentId: z10.string().min(1, "pgPaymentId is required").describe("PG payment ID (required)"),
984
- status: transactionStatusSchema.describe(
985
- "New transaction status (required)"
986
- ),
987
- paymentMethod: z10.string().optional().describe("Payment method (optional)"),
988
- receiptUrl: z10.string().optional().describe("Receipt URL (optional)"),
989
- paymentKey: z10.string().min(1).optional().describe("Provider payment key for verified paid confirmation"),
990
- amount: z10.number().int().positive().optional().describe("Provider-confirmed amount for verified paid confirmation")
991
- }).strict();
992
- var UpdateTransactionSchema = updateTransactionSchema;
993
- var returnReasonSchema = z10.enum([
994
- "change_of_mind",
995
- "defective",
996
- "wrong_delivery",
997
- "damaged",
998
- "other"
999
- ]);
1000
- var restockActionSchema = z10.enum(["return_to_stock", "discard"]);
1001
- var returnWithRefundItemSchema = z10.object({
1002
- orderItem: z10.union([z10.string(), z10.number()]).transform(String),
1003
- quantity: z10.number().int().positive("quantity must be a positive integer"),
1004
- restockAction: restockActionSchema.default("return_to_stock")
1005
- }).strict();
1006
- var returnWithRefundSchema = z10.object({
1007
- orderNumber: z10.string().min(1, "orderNumber is required").describe("Order number (required)"),
1008
- reason: returnReasonSchema.optional().describe("Return reason (optional)"),
1009
- reasonDetail: z10.string().optional().describe("Detailed reason text (optional)"),
1010
- returnItems: z10.array(returnWithRefundItemSchema).min(1, "At least one return item is required").max(100, "Too many return items").describe("Array of products to return (required)"),
1011
- refundAmount: z10.number().min(0, "refundAmount must be non-negative").describe("Refund amount (required, min 0)"),
1012
- pgPaymentId: z10.string().min(1, "pgPaymentId is required").describe("PG payment ID for refund (required)"),
1013
- paymentKey: z10.string().min(1).optional().describe("Provider payment key for verified refund"),
1014
- refundReceiptUrl: z10.string().optional().describe("Refund receipt URL (optional)")
1015
- }).strict();
1016
- var ReturnWithRefundSchema = returnWithRefundSchema;
1017
-
1018
1440
  // src/tools/update-transaction.ts
1019
1441
  var schema9 = UpdateTransactionSchema.shape;
1020
1442
  var metadata9 = {
@@ -1409,141 +1831,51 @@ async function calculateShipping({
1409
1831
  const result = await client.commerce.shipping.calculate({
1410
1832
  shippingPolicyId,
1411
1833
  orderAmount,
1412
- postalCode
1413
- });
1414
- return toolSuccess({ data: result });
1415
- } catch (error) {
1416
- return toolError(error);
1417
- }
1418
- }
1419
-
1420
- // src/tools/stock-check.ts
1421
- import { z as z21 } from "zod";
1422
- var schema21 = {
1423
- items: z21.array(
1424
- z21.object({
1425
- variantId: z21.string().describe("Product variant ID"),
1426
- quantity: z21.number().int().positive().describe("Requested quantity")
1427
- })
1428
- ).describe(
1429
- "Array of items to check stock for (required, max 100). Each: { variantId, quantity }"
1430
- )
1431
- };
1432
- var metadata21 = {
1433
- name: "stock-check",
1434
- description: "Batch check product option stock availability. Returns per-item availability and an allAvailable flag.",
1435
- annotations: {
1436
- title: "Check stock availability",
1437
- readOnlyHint: true,
1438
- destructiveHint: false,
1439
- idempotentHint: true
1440
- }
1441
- };
1442
- async function stockCheck({
1443
- items
1444
- }) {
1445
- try {
1446
- const client = getClient();
1447
- const result = await client.commerce.product.stockCheck({ items });
1448
- return toolSuccess({ data: result });
1449
- } catch (error) {
1450
- return toolError(error);
1451
- }
1452
- }
1453
-
1454
- // src/tools/get-collection-schema.ts
1455
- import { COLLECTIONS as COLLECTIONS3 } from "@01.software/sdk";
1456
-
1457
- // src/lib/console-api.ts
1458
- import { createHash } from "crypto";
1459
- var BASE_URL = process.env.SOFTWARE_API_URL || "http://localhost:3000";
1460
- var TIMEOUT_MS = 5e3;
1461
- var MISSING_HTTP_AUTH_CONTEXT_ERROR2 = "MCP HTTP requests require a validated OAuth tenant context before tool execution.";
1462
- function resolveAuthHeaderContext() {
1463
- const oauthContext = tenantAuthContext();
1464
- if (oauthContext) {
1465
- return {
1466
- apiKey: signMcpServiceToken(oauthContext),
1467
- mode: "oauth"
1468
- };
1469
- }
1470
- if (hasRequestContext()) throw new Error(MISSING_HTTP_AUTH_CONTEXT_ERROR2);
1471
- return {
1472
- apiKey: process.env.SOFTWARE_SECRET_KEY,
1473
- mode: "stdio",
1474
- publishableKey: process.env.SOFTWARE_PUBLISHABLE_KEY ?? process.env.NEXT_PUBLIC_SOFTWARE_PUBLISHABLE_KEY
1475
- };
1476
- }
1477
- function resolveApiKey() {
1478
- const { apiKey } = resolveAuthHeaderContext();
1479
- if (!apiKey || typeof apiKey !== "string") {
1480
- throw new Error(
1481
- "Authentication required. Set SOFTWARE_SECRET_KEY for stdio transport."
1482
- );
1483
- }
1484
- return apiKey;
1485
- }
1486
- function buildAuthHeaders(apiKey) {
1487
- const { mode, publishableKey } = resolveAuthHeaderContext();
1488
- const headers = {
1489
- Authorization: `Bearer ${apiKey}`
1490
- };
1491
- if (mode === "stdio" && publishableKey) {
1492
- headers["X-Publishable-Key"] = publishableKey;
1493
- }
1494
- return headers;
1495
- }
1496
- function extractErrorMessage(body) {
1497
- if (!body || typeof body !== "object") return void 0;
1498
- const b = body;
1499
- if (typeof b.error === "string") return b.error;
1500
- if (Array.isArray(b.errors) && b.errors[0]?.message) {
1501
- return String(b.errors[0].message);
1502
- }
1503
- if (typeof b.message === "string") return b.message;
1504
- return void 0;
1505
- }
1506
- async function consoleGet(path, apiKey) {
1507
- const authHeaders = buildAuthHeaders(apiKey);
1508
- const controller = new AbortController();
1509
- const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS);
1510
- try {
1511
- const res = await fetch(`${BASE_URL}${path}`, {
1512
- headers: authHeaders,
1513
- signal: controller.signal
1514
- });
1515
- if (!res.ok) {
1516
- const body = await res.json().catch(() => ({}));
1517
- const msg = extractErrorMessage(body);
1518
- throw new Error(msg || `Console GET ${path} failed: ${res.status}`);
1519
- }
1520
- return res.json();
1521
- } finally {
1522
- clearTimeout(timeoutId);
1834
+ postalCode
1835
+ });
1836
+ return toolSuccess({ data: result });
1837
+ } catch (error) {
1838
+ return toolError(error);
1523
1839
  }
1524
1840
  }
1525
- async function consolePost(path, body, apiKey) {
1526
- const authHeaders = buildAuthHeaders(apiKey);
1527
- const controller = new AbortController();
1528
- const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS);
1841
+
1842
+ // src/tools/stock-check.ts
1843
+ import { z as z21 } from "zod";
1844
+ var schema21 = {
1845
+ items: z21.array(
1846
+ z21.object({
1847
+ variantId: z21.string().describe("Product variant ID"),
1848
+ quantity: z21.number().int().positive().describe("Requested quantity")
1849
+ })
1850
+ ).describe(
1851
+ "Array of items to check stock for (required, max 100). Each: { variantId, quantity }"
1852
+ )
1853
+ };
1854
+ var metadata21 = {
1855
+ name: "stock-check",
1856
+ description: "Batch check product option stock availability. Returns per-item availability and an allAvailable flag.",
1857
+ annotations: {
1858
+ title: "Check stock availability",
1859
+ readOnlyHint: true,
1860
+ destructiveHint: false,
1861
+ idempotentHint: true
1862
+ }
1863
+ };
1864
+ async function stockCheck({
1865
+ items
1866
+ }) {
1529
1867
  try {
1530
- const res = await fetch(`${BASE_URL}${path}`, {
1531
- method: "POST",
1532
- headers: { ...authHeaders, "Content-Type": "application/json" },
1533
- body: JSON.stringify(body),
1534
- signal: controller.signal
1535
- });
1536
- if (!res.ok) {
1537
- const errBody = await res.json().catch(() => ({}));
1538
- const msg = extractErrorMessage(errBody);
1539
- throw new Error(msg || `Console POST ${path} failed: ${res.status}`);
1540
- }
1541
- return res.json();
1542
- } finally {
1543
- clearTimeout(timeoutId);
1868
+ const client = getClient();
1869
+ const result = await client.commerce.product.stockCheck({ items });
1870
+ return toolSuccess({ data: result });
1871
+ } catch (error) {
1872
+ return toolError(error);
1544
1873
  }
1545
1874
  }
1546
1875
 
1876
+ // src/tools/get-collection-schema.ts
1877
+ import { SERVER_COLLECTIONS as SERVER_COLLECTIONS3 } from "@01.software/sdk";
1878
+
1547
1879
  // src/lib/collection-schema.ts
1548
1880
  async function getCollectionSchema(collection) {
1549
1881
  const apiKey = resolveApiKey();
@@ -1555,7 +1887,7 @@ async function getCollectionSchema(collection) {
1555
1887
  }
1556
1888
 
1557
1889
  // src/tools/get-collection-schema.ts
1558
- var schema22 = createCollectionSchemaToolInputSchema(COLLECTIONS3).shape;
1890
+ var schema22 = createCollectionSchemaToolInputSchema(SERVER_COLLECTIONS3).shape;
1559
1891
  var metadata22 = {
1560
1892
  name: "get-collection-schema",
1561
1893
  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.",
@@ -1584,6 +1916,11 @@ async function getCollectionSchemaTool({
1584
1916
  function getTenantContextPath(includeCounts) {
1585
1917
  return includeCounts ? "/api/tenants/context?counts=true" : "/api/tenants/context";
1586
1918
  }
1919
+ function getTenantFeatureProgressPath(feature, includeEvidence) {
1920
+ const search = new URLSearchParams({ feature });
1921
+ if (includeEvidence) search.set("includeEvidence", "true");
1922
+ return `/api/tenants/feature-progress?${search.toString()}`;
1923
+ }
1587
1924
  async function getTenantContext(includeCounts = false) {
1588
1925
  const apiKey = resolveApiKey();
1589
1926
  const data = await consoleGet(
@@ -1592,6 +1929,14 @@ async function getTenantContext(includeCounts = false) {
1592
1929
  );
1593
1930
  return tenantContextResponseSchema.parse(data);
1594
1931
  }
1932
+ async function getTenantFeatureProgress(feature, includeEvidence = false) {
1933
+ const apiKey = resolveApiKey();
1934
+ const data = await consoleGet(
1935
+ getTenantFeatureProgressPath(feature, includeEvidence),
1936
+ apiKey
1937
+ );
1938
+ return tenantFeatureProgressResponseSchema.parse(data);
1939
+ }
1595
1940
 
1596
1941
  // src/tools/get-tenant-context.ts
1597
1942
  var schema23 = tenantContextToolInputSchema.shape;
@@ -1671,6 +2016,30 @@ async function handler({
1671
2016
  }
1672
2017
  }
1673
2018
 
2019
+ // src/tools/check-feature-progress.ts
2020
+ var schema24 = tenantFeatureProgressInputSchema.shape;
2021
+ var metadata24 = {
2022
+ name: "check-feature-progress",
2023
+ description: "Check tenant implementation progress for a supported feature. Start with feature=ecommerce to inspect catalog, cart, checkout, payment result, webhook, and operations readiness without mutating tenant data.",
2024
+ annotations: {
2025
+ title: "Check Feature Progress",
2026
+ readOnlyHint: true,
2027
+ destructiveHint: false,
2028
+ idempotentHint: true
2029
+ }
2030
+ };
2031
+ async function handler2({
2032
+ feature,
2033
+ includeEvidence
2034
+ }) {
2035
+ try {
2036
+ const progress = await getTenantFeatureProgress(feature, includeEvidence);
2037
+ return toolSuccess({ progress });
2038
+ } catch (error) {
2039
+ return toolError(error);
2040
+ }
2041
+ }
2042
+
1674
2043
  // src/tools/list-configurable-fields.ts
1675
2044
  import { z as z22 } from "zod";
1676
2045
 
@@ -1695,12 +2064,12 @@ function invalidateFieldConfigCache() {
1695
2064
  }
1696
2065
 
1697
2066
  // src/tools/list-configurable-fields.ts
1698
- var schema24 = {
2067
+ var schema25 = {
1699
2068
  collection: z22.string().optional().describe(
1700
2069
  "Filter by collection slug (optional \u2014 returns all if omitted). Use this filter to reduce response size when you know which collection to check."
1701
2070
  )
1702
2071
  };
1703
- var metadata24 = {
2072
+ var metadata25 = {
1704
2073
  name: "list-configurable-fields",
1705
2074
  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.",
1706
2075
  annotations: {
@@ -1732,7 +2101,7 @@ async function listConfigurableFields(params) {
1732
2101
 
1733
2102
  // src/tools/update-field-config.ts
1734
2103
  import { z as z23 } from "zod";
1735
- var schema25 = {
2104
+ var schema26 = {
1736
2105
  collection: z23.string().min(1).describe("Collection slug (required)"),
1737
2106
  hiddenFields: z23.array(z23.string().min(1).max(200)).max(300).describe(
1738
2107
  "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."
@@ -1741,7 +2110,7 @@ var schema25 = {
1741
2110
  "Hide the entire collection from Admin Panel (optional). When true, individual hiddenFields are irrelevant."
1742
2111
  )
1743
2112
  };
1744
- var metadata25 = {
2113
+ var metadata26 = {
1745
2114
  name: "update-field-config",
1746
2115
  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.",
1747
2116
  annotations: {
@@ -2201,7 +2570,7 @@ function getRecipe(goal, runtime = "both") {
2201
2570
  }
2202
2571
 
2203
2572
  // src/tools/sdk-get-recipe.ts
2204
- var schema26 = {
2573
+ var schema27 = {
2205
2574
  goal: z24.enum([
2206
2575
  "fetch-list",
2207
2576
  "fetch-by-id",
@@ -2218,7 +2587,7 @@ var schema26 = {
2218
2587
  collection: z24.string().optional().describe("Specific collection name if applicable"),
2219
2588
  includeExample: z24.boolean().default(true).describe("Whether to include a full code example")
2220
2589
  };
2221
- var metadata26 = {
2590
+ var metadata27 = {
2222
2591
  name: "sdk-get-recipe",
2223
2592
  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.",
2224
2593
  annotations: {
@@ -2228,7 +2597,7 @@ var metadata26 = {
2228
2597
  idempotentHint: true
2229
2598
  }
2230
2599
  };
2231
- function handler2({
2600
+ function handler3({
2232
2601
  goal,
2233
2602
  runtime,
2234
2603
  collection,
@@ -2275,7 +2644,7 @@ var docIndex = [
2275
2644
  {
2276
2645
  title: "Browser Client vs Server Client",
2277
2646
  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"],
2278
- 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.",
2647
+ 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.",
2279
2648
  resourceUri: "docs://sdk/getting-started"
2280
2649
  },
2281
2650
  // Query Builder
@@ -2436,11 +2805,11 @@ function searchDocs(query, limit = 5) {
2436
2805
  }
2437
2806
 
2438
2807
  // src/tools/sdk-search-docs.ts
2439
- var schema27 = {
2808
+ var schema28 = {
2440
2809
  query: z25.string().min(2).describe('Search keyword or phrase (e.g. "infinite scroll", "webhook", "customer login")'),
2441
2810
  limit: z25.number().min(1).max(10).default(5).describe("Maximum results to return (1-10, default: 5)")
2442
2811
  };
2443
- var metadata27 = {
2812
+ var metadata28 = {
2444
2813
  name: "sdk-search-docs",
2445
2814
  description: "Search SDK documentation by keyword. Returns matching topics with summaries and resource links. Use when looking for specific SDK features or patterns.",
2446
2815
  annotations: {
@@ -2450,7 +2819,7 @@ var metadata27 = {
2450
2819
  idempotentHint: true
2451
2820
  }
2452
2821
  };
2453
- function handler3({
2822
+ function handler4({
2454
2823
  query,
2455
2824
  limit
2456
2825
  }) {
@@ -2476,7 +2845,7 @@ function handler3({
2476
2845
 
2477
2846
  // src/tools/sdk-get-auth-setup.ts
2478
2847
  import { z as z26 } from "zod";
2479
- var schema28 = {
2848
+ var schema29 = {
2480
2849
  scenario: z26.enum([
2481
2850
  "browser-client",
2482
2851
  "server-client",
@@ -2486,7 +2855,7 @@ var schema28 = {
2486
2855
  "webhook-verification"
2487
2856
  ]).describe("Authentication scenario")
2488
2857
  };
2489
- var metadata28 = {
2858
+ var metadata29 = {
2490
2859
  name: "sdk-get-auth-setup",
2491
2860
  description: "Get the current authentication setup for a specific scenario. Returns env var names, code snippets, and security notes.",
2492
2861
  annotations: {
@@ -2625,7 +2994,7 @@ export async function POST(request: Request) {
2625
2994
  ]
2626
2995
  }
2627
2996
  };
2628
- function handler4({
2997
+ function handler5({
2629
2998
  scenario
2630
2999
  }) {
2631
3000
  try {
@@ -2641,13 +3010,13 @@ function handler4({
2641
3010
 
2642
3011
  // src/tools/sdk-get-collection-pattern.ts
2643
3012
  import { z as z27 } from "zod";
2644
- import { COLLECTIONS as COLLECTIONS4 } from "@01.software/sdk";
2645
- var schema29 = {
2646
- collection: z27.enum(COLLECTIONS4).describe("Collection name"),
3013
+ import { COLLECTIONS, SERVER_COLLECTIONS as SERVER_COLLECTIONS4 } from "@01.software/sdk";
3014
+ var schema30 = {
3015
+ collection: z27.enum(SERVER_COLLECTIONS4).describe("Collection name"),
2647
3016
  operation: z27.enum(["read", "write", "full-crud"]).default("read").describe("What operations are needed"),
2648
3017
  surface: z27.enum(["query-builder", "react-query", "server-api"]).default("query-builder").describe("Preferred API surface")
2649
3018
  };
2650
- var metadata29 = {
3019
+ var metadata30 = {
2651
3020
  name: "sdk-get-collection-pattern",
2652
3021
  description: "Get the recommended CRUD pattern for a specific collection. Returns code examples for the chosen API surface and operation type.",
2653
3022
  annotations: {
@@ -2658,7 +3027,15 @@ var metadata29 = {
2658
3027
  }
2659
3028
  };
2660
3029
  function generatePattern(collection, operation, surface) {
3030
+ const isPublicCollection = COLLECTIONS.includes(
3031
+ collection
3032
+ );
2661
3033
  if (surface === "react-query") {
3034
+ if (!isPublicCollection) {
3035
+ throw new Error(
3036
+ `${collection} is server-only. Use surface="server-api" with createServerClient().`
3037
+ );
3038
+ }
2662
3039
  const parts2 = [];
2663
3040
  if (operation === "read") {
2664
3041
  parts2.push(
@@ -2770,17 +3147,29 @@ function generatePattern(collection, operation, surface) {
2770
3147
  }
2771
3148
  const parts = [];
2772
3149
  if (operation === "read" || operation === "full-crud") {
2773
- parts.push(
2774
- `// Read with any client (Client or ServerClient)`,
2775
- `const result = await client.collections.from('${collection}').find({`,
2776
- ` where: { status: { equals: 'published' } },`,
2777
- ` limit: 10,`,
2778
- ` sort: '-createdAt'`,
2779
- `})`,
2780
- ``,
2781
- `const item = await client.collections.from('${collection}').findById(id)`,
2782
- `const { totalDocs } = await client.collections.from('${collection}').count()`
2783
- );
3150
+ if (isPublicCollection) {
3151
+ parts.push(
3152
+ `// Read with any client (Client or ServerClient)`,
3153
+ `const result = await client.collections.from('${collection}').find({`,
3154
+ ` where: { status: { equals: 'published' } },`,
3155
+ ` limit: 10,`,
3156
+ ` sort: '-createdAt'`,
3157
+ `})`,
3158
+ ``,
3159
+ `const item = await client.collections.from('${collection}').findById(id)`,
3160
+ `const { totalDocs } = await client.collections.from('${collection}').count()`
3161
+ );
3162
+ } else {
3163
+ parts.push(
3164
+ `// Server-only collection: use ServerClient`,
3165
+ `const result = await serverClient.collections.from('${collection}').find({`,
3166
+ ` limit: 10,`,
3167
+ ` sort: '-createdAt'`,
3168
+ `})`,
3169
+ ``,
3170
+ `const item = await serverClient.collections.from('${collection}').findById(id)`
3171
+ );
3172
+ }
2784
3173
  }
2785
3174
  if (operation === "write" || operation === "full-crud") {
2786
3175
  parts.push(
@@ -2795,11 +3184,12 @@ function generatePattern(collection, operation, surface) {
2795
3184
  code: parts.join("\n"),
2796
3185
  notes: [
2797
3186
  "Query Builder works with both Client and ServerClient for reads",
3187
+ !isPublicCollection ? "This collection is server-only" : "",
2798
3188
  operation !== "read" ? "Write operations require ServerClient" : ""
2799
3189
  ].filter(Boolean)
2800
3190
  };
2801
3191
  }
2802
- function handler5({
3192
+ function handler6({
2803
3193
  collection,
2804
3194
  operation,
2805
3195
  surface
@@ -2828,13 +3218,13 @@ function handler5({
2828
3218
 
2829
3219
  // src/prompts/sdk-usage-guide.ts
2830
3220
  import { z as z28 } from "zod";
2831
- var schema30 = {
3221
+ var schema31 = {
2832
3222
  goal: z28.string().describe('What the user wants to accomplish (e.g., "query product list", "create order")'),
2833
3223
  runtime: z28.enum(["browser", "server"]).optional().describe("Target runtime: browser (React/Next.js client) or server (Node.js)"),
2834
3224
  surface: z28.enum(["query-builder", "react-query", "customer-api", "server-api"]).optional().describe("Preferred API surface"),
2835
3225
  collection: z28.string().optional().describe("Specific collection if relevant")
2836
3226
  };
2837
- var metadata30 = {
3227
+ var metadata31 = {
2838
3228
  name: "sdk-usage-guide",
2839
3229
  title: "SDK Usage Guide",
2840
3230
  description: "Provides guidance on how to perform a specific task using the 01.software SDK",
@@ -2972,13 +3362,13 @@ You can perform the "${goal}" task by following the patterns above.`;
2972
3362
 
2973
3363
  // src/prompts/collection-query-help.ts
2974
3364
  import { z as z29 } from "zod";
2975
- import { COLLECTIONS as COLLECTIONS5 } from "@01.software/sdk";
2976
- var schema31 = {
2977
- collection: z29.enum(COLLECTIONS5).describe("Collection name"),
3365
+ import { COLLECTIONS as COLLECTIONS2, SERVER_COLLECTIONS as SERVER_COLLECTIONS5 } from "@01.software/sdk";
3366
+ var schema32 = {
3367
+ collection: z29.enum(SERVER_COLLECTIONS5).describe("Collection name"),
2978
3368
  operation: z29.enum(["find", "create", "update", "delete"]).describe("Operation to perform (find, create, update, delete)"),
2979
3369
  filters: z29.string().optional().describe("Filter conditions (JSON string, optional)")
2980
3370
  };
2981
- var metadata31 = {
3371
+ var metadata32 = {
2982
3372
  name: "collection-query-help",
2983
3373
  title: "Collection Query Help",
2984
3374
  description: "Provides guidance on how to write queries for a specific collection",
@@ -2995,6 +3385,11 @@ Filter conditions:
2995
3385
  \`\`\`json
2996
3386
  ${filters}
2997
3387
  \`\`\`` : "";
3388
+ const isPublicCollection = COLLECTIONS2.includes(
3389
+ collection
3390
+ );
3391
+ const readClientName = isPublicCollection ? "client" : "serverClient";
3392
+ const readClientNote = isPublicCollection ? "Client or ServerClient" : "ServerClient only";
2998
3393
  return `How to perform "${operation}" operation on "${collection}" collection:${filterExample}
2999
3394
 
3000
3395
  ## Collection: ${collection}
@@ -3005,26 +3400,26 @@ ${filters}
3005
3400
  \`\`\`typescript
3006
3401
  import { createClient, createServerClient } from '@01.software/sdk'
3007
3402
 
3008
- // Client (read-only)
3403
+ // Client (read-only public collections)
3009
3404
  const client = createClient({
3010
3405
  publishableKey: process.env.NEXT_PUBLIC_SOFTWARE_PUBLISHABLE_KEY!
3011
3406
  })
3012
3407
 
3013
- // Server client (full CRUD)
3408
+ // Server client (server/public collections, full CRUD)
3014
3409
  const serverClient = createServerClient({
3015
3410
  publishableKey: process.env.SOFTWARE_PUBLISHABLE_KEY!,
3016
3411
  secretKey: process.env.SOFTWARE_SECRET_KEY!
3017
3412
  })
3018
3413
 
3019
- ${operation === "find" ? `// Query ${collection} collection with Query Builder
3414
+ ${operation === "find" ? `// Query ${collection} collection with Query Builder (${readClientNote})
3020
3415
  // find() returns PayloadFindResponse with docs array and pagination
3021
- const result = await client.collections.from('${collection}').find(${filters ? `{
3416
+ const result = await ${readClientName}.collections.from('${collection}').find(${filters ? `{
3022
3417
  where: ${filters}
3023
3418
  }` : ""})
3024
3419
  // result.docs - array of items
3025
3420
  // result.totalDocs, result.page, result.totalPages, result.hasNextPage, ...
3026
3421
 
3027
- // Using React Hook
3422
+ ${isPublicCollection ? `// Using React Hook
3028
3423
  const { data, isLoading, error } = client.query.useQuery({
3029
3424
  collection: '${collection}',
3030
3425
  options: { limit: 10 }
@@ -3034,19 +3429,19 @@ const { data, isLoading, error } = client.query.useQuery({
3034
3429
  const { data } = client.query.useSuspenseQuery({
3035
3430
  collection: '${collection}',
3036
3431
  options: { limit: 10 }
3037
- })` : operation === "create" ? `// Create ${collection} item (ServerClient only)
3432
+ })` : `// React hooks are browser/public only and do not support '${collection}'.`}` : operation === "create" ? `// Create ${collection} item (ServerClient only)
3038
3433
  // create() returns PayloadMutationResponse with doc and message
3039
- const result = await serverClient.from('${collection}').create({
3434
+ const result = await serverClient.collections.from('${collection}').create({
3040
3435
  // Enter fields
3041
3436
  })
3042
3437
  // result.doc - created item, result.message` : operation === "update" ? `// Update ${collection} item (ServerClient only)
3043
3438
  // update() returns PayloadMutationResponse with doc and message
3044
- const result = await serverClient.from('${collection}').update(id, {
3439
+ const result = await serverClient.collections.from('${collection}').update(id, {
3045
3440
  // Fields to update
3046
3441
  })
3047
3442
  // result.doc - updated item, result.message` : `// Delete ${collection} item (ServerClient only)
3048
3443
  // remove() returns the deleted document directly
3049
- await serverClient.from('${collection}').remove(id)`}
3444
+ await serverClient.collections.from('${collection}').remove(id)`}
3050
3445
  \`\`\`
3051
3446
 
3052
3447
  ### Useful Tips
@@ -3054,7 +3449,7 @@ await serverClient.from('${collection}').remove(id)`}
3054
3449
  ${operation === "find" ? `- Use \`where\` option for filtering (Payload query syntax)
3055
3450
  - Use \`limit\` and \`page\` for pagination
3056
3451
  - Use \`sort\` for sorting (prefix with "-" for descending)
3057
- - React Query hooks: useQuery, useSuspenseQuery, useInfiniteQuery
3452
+ - ${isPublicCollection ? "React Query hooks: useQuery, useSuspenseQuery, useInfiniteQuery" : "React Query hooks are browser/public only; use ServerClient for this collection"}
3058
3453
  - Cache utilities: invalidateQueries, prefetchQuery, getQueryData, setQueryData` : operation === "create" ? `- Requires ServerClient with secretKey
3059
3454
  - Check required fields
3060
3455
  - TypeScript recommended for type safety` : operation === "update" ? `- Requires ServerClient with secretKey
@@ -3066,7 +3461,7 @@ ${operation === "find" ? `- Use \`where\` option for filtering (Payload query sy
3066
3461
 
3067
3462
  // src/prompts/order-flow-guide.ts
3068
3463
  import { z as z30 } from "zod";
3069
- var schema32 = {
3464
+ var schema33 = {
3070
3465
  scenario: z30.enum([
3071
3466
  "simple-order",
3072
3467
  "cart-checkout",
@@ -3074,7 +3469,7 @@ var schema32 = {
3074
3469
  "fulfillment-tracking"
3075
3470
  ]).describe("Order flow scenario")
3076
3471
  };
3077
- var metadata32 = {
3472
+ var metadata33 = {
3078
3473
  name: "order-flow-guide",
3079
3474
  title: "Order Flow Guide",
3080
3475
  description: "Provides step-by-step guidance for ecommerce order flows including creation, checkout, returns, and fulfillment.",
@@ -3260,7 +3655,7 @@ ${SCENARIOS[scenario] || "Unknown scenario."}
3260
3655
 
3261
3656
  // src/prompts/feature-setup-guide.ts
3262
3657
  import { z as z31 } from "zod";
3263
- var schema33 = {
3658
+ var schema34 = {
3264
3659
  feature: z31.enum([
3265
3660
  "ecommerce",
3266
3661
  "customers",
@@ -3276,10 +3671,10 @@ var schema33 = {
3276
3671
  "community"
3277
3672
  ]).describe("Feature to get setup guide for")
3278
3673
  };
3279
- var metadata33 = {
3674
+ var metadata34 = {
3280
3675
  name: "feature-setup-guide",
3281
3676
  title: "Feature Setup Guide",
3282
- description: "Setup checklist and remediation guide for a tenant feature. Load before using get-tenant-context to diagnose setup gaps.",
3677
+ description: "Setup checklist and remediation guide for a tenant feature. Load with check-feature-progress and get-tenant-context to diagnose setup gaps.",
3283
3678
  role: "assistant"
3284
3679
  };
3285
3680
  var FEATURES = {
@@ -3290,7 +3685,7 @@ var FEATURES = {
3290
3685
  ### Required Collections (count > 0)
3291
3686
 
3292
3687
  1. **products** \u2014 Create via Console UI or SDK \`client.collections.from('products').create({ ... })\`
3293
- - Minimum fields: \`{ title, slug, status: 'published', _status: 'published' }\`
3688
+ - Minimum fields: \`{ title, slug, status: 'published' }\`
3294
3689
 
3295
3690
  2. **product-variants** \u2014 At least 1 sellable variant per product
3296
3691
  - Minimum fields: \`{ product, title, price, stock }\`
@@ -3309,6 +3704,7 @@ product-options, product-option-values, product-categories, product-tags, produc
3309
3704
  ### Config
3310
3705
 
3311
3706
  - **Webhook URL** must be configured in tenant settings for payment gateway callbacks
3707
+ - Use \`check-feature-progress\` for the tenant-aware ecommerce progress check
3312
3708
  - Use \`get-tenant-context\` to check current webhook configuration`,
3313
3709
  customers: `## Customers Setup Guide
3314
3710
 
@@ -3323,7 +3719,8 @@ customer-addresses
3323
3719
 
3324
3720
  ### Optional Collections
3325
3721
 
3326
- customer-groups \u2014 Create via Console UI or SDK \`client.collections.from('customer-groups').create({ title })\`
3722
+ - customer-groups \u2014 Console/server-scoped segmentation for VIP coupons and campaigns. Use \`createServerClient().collections.from('customer-groups')\`.
3723
+ - customer-profile-lists \u2014 Public profile display/ranking lists for storefronts. Browser reads may use \`client.collections.from('customer-profile-lists')\`.
3327
3724
 
3328
3725
  ### Config
3329
3726
 
@@ -3334,10 +3731,10 @@ customer-groups \u2014 Create via Console UI or SDK \`client.collections.from('c
3334
3731
  ### Required Collections (count > 0)
3335
3732
 
3336
3733
  1. **articles** \u2014 At least 1 article
3337
- - Minimum fields: \`{ title, slug }\`
3734
+ - Minimum fields: \`{ title, slug, status: 'published' }\`
3338
3735
 
3339
3736
  2. **article-authors** \u2014 At least 1 author
3340
- - Minimum fields: \`{ title, slug }\`
3737
+ - Minimum fields: \`{ title, slug, status: 'published' }\`
3341
3738
  - Link authors to articles via the \`authors\` relationship field
3342
3739
 
3343
3740
  ### Optional Collections
@@ -3352,7 +3749,7 @@ article-categories, article-tags`,
3352
3749
 
3353
3750
  2. **document-types** \u2014 At least 1 type
3354
3751
  - Minimum fields: \`{ title, slug }\`
3355
- - Link document type via \`documentType\` relationship field
3752
+ - Link document type via \`type\` relationship field
3356
3753
 
3357
3754
  ### Optional Collections
3358
3755
 
@@ -3362,10 +3759,10 @@ document-categories`,
3362
3759
  ### Required Collections (count > 0)
3363
3760
 
3364
3761
  1. **playlists** \u2014 At least 1 playlist
3365
- - Minimum fields: \`{ title, slug, status: 'published', _status: 'published' }\`
3762
+ - Minimum fields: \`{ title, slug, status: 'published' }\`
3366
3763
 
3367
3764
  2. **tracks** \u2014 At least 1 track
3368
- - Minimum fields: \`{ title, sourceUrl, status: 'published', _status: 'published' }\`
3765
+ - Minimum fields: \`{ title, sourceUrl, status: 'published' }\`
3369
3766
 
3370
3767
  3. **playlists.tracks** \u2014 Link at least 1 track from a playlist
3371
3768
  - Minimum fields: \`{ tracks: [trackId] }\`
@@ -3378,11 +3775,11 @@ playlist-categories, playlist-tags, track-categories, track-tags, track-assets`,
3378
3775
  ### Required Collections (count > 0)
3379
3776
 
3380
3777
  1. **galleries** \u2014 At least 1 gallery
3381
- - Minimum fields: \`{ title, slug, status: 'published', _status: 'published' }\`
3778
+ - Minimum fields: \`{ title, slug, status: 'published' }\`
3382
3779
 
3383
3780
  2. **gallery-items** \u2014 At least 1 item per gallery
3384
3781
  - References \`images\` collection (non-upload)
3385
- - Minimum fields: \`{ gallery, image, _status: 'published' }\`
3782
+ - Minimum fields: \`{ gallery, image, status: 'published' }\`
3386
3783
 
3387
3784
  ### Optional Collections
3388
3785
 
@@ -3392,7 +3789,7 @@ gallery-categories, gallery-tags`,
3392
3789
  ### Required Collections (count > 0)
3393
3790
 
3394
3791
  1. **links** \u2014 At least 1 link
3395
- - Minimum fields: \`{ title, slug, url, status: 'published', _status: 'published' }\`
3792
+ - Minimum fields: \`{ title, slug, url, status: 'published' }\`
3396
3793
 
3397
3794
  ### Optional Collections
3398
3795
 
@@ -3464,32 +3861,36 @@ comments, reactions, bookmarks, reports, community-bans
3464
3861
 
3465
3862
  ### Optional Collections
3466
3863
 
3467
- post-categories`
3864
+ post-categories, customer-profile-lists`
3468
3865
  };
3469
- function featureSetupGuide({ feature }) {
3866
+ function featureSetupGuide({
3867
+ feature
3868
+ }) {
3470
3869
  return `# Feature Setup Guide: ${feature}
3471
3870
 
3472
3871
  ${FEATURES[feature] || "Unknown feature."}
3473
3872
 
3474
3873
  ## Related MCP Tools
3874
+ - \`check-feature-progress\` \u2014 run the tenant-aware ecommerce implementation progress check
3475
3875
  - \`get-tenant-context\` \u2014 check current collection counts and feature status
3476
3876
  - \`query-collection\` \u2014 verify existing documents in a collection
3477
3877
  - \`get-collection-schema\` \u2014 inspect tenant-aware fields before creating data via SDK or Console UI`;
3478
3878
  }
3479
3879
 
3480
3880
  // src/resources/(config)/app.ts
3481
- var metadata34 = {
3881
+ var metadata35 = {
3482
3882
  name: "app-config",
3483
3883
  title: "Application Config",
3484
3884
  description: "01.software SDK and MCP server configuration information"
3485
3885
  };
3486
- function handler6() {
3886
+ function handler7() {
3487
3887
  return `# 01.software MCP Server Configuration
3488
3888
 
3489
3889
  ## Server Info
3490
3890
  - **Name**: 01.software MCP Server
3491
3891
  - **Version**: 0.1.0
3492
- - **Transport**: HTTP (Streamable)
3892
+ - **Hosted transport**: HTTP (Streamable)
3893
+ - **Local transport**: stdio through \`npx @01.software/cli mcp\`
3493
3894
 
3494
3895
  ## Authentication
3495
3896
 
@@ -3500,48 +3901,16 @@ HTTP MCP uses OAuth discovery and Authorization Code + PKCE.
3500
3901
  url = "https://mcp.01.software/mcp"
3501
3902
  \`\`\`
3502
3903
 
3503
- ## Available Tools (29)
3504
-
3505
- > Generic write tools (create/update/delete/update-many/delete-many) are intentionally absent. Use the dedicated workflow tools below or the SDK (\`client.collections.from(slug).create()\` / \`update()\` / \`remove()\` / \`updateMany()\` / \`removeMany()\`) for stateful mutations.
3506
-
3507
- ### Generic Read (2)
3508
- - \`query-collection\` - Query collection with filters, pagination, sorting
3509
- - \`get-collection-by-id\` - Get single item by ID
3510
-
3511
- ### Orders (7)
3512
- - \`create-order\` - Create a new order with products and shipping
3513
- - \`get-order\` - Get order details by order number
3514
- - \`update-order\` - Update order status
3515
- - \`checkout\` - Convert cart to order
3516
- - \`create-fulfillment\` - Create fulfillment for order items
3517
- - \`update-fulfillment\` - Update fulfillment status, carrier, and tracking
3518
- - \`update-transaction\` - Update transaction status
3519
-
3520
- ### Returns (3)
3521
- - \`create-return\` - Create a return request
3522
- - \`update-return\` - Update return status
3523
- - \`return-with-refund\` - Process return with refund atomically
3904
+ ## Hosted HTTP OAuth Tools (9)
3524
3905
 
3525
- ### Cart (6)
3526
- - \`add-cart-item\` - Add item to cart
3527
- - \`update-cart-item\` - Update cart item quantity
3528
- - \`remove-cart-item\` - Remove item from cart
3529
- - \`apply-discount\` - Apply discount code to cart
3530
- - \`remove-discount\` - Remove discount from cart
3531
- - \`clear-cart\` - Remove all items from cart
3532
-
3533
- ### Validation (2)
3534
- - \`validate-discount\` - Validate discount code
3535
- - \`calculate-shipping\` - Calculate shipping fee
3536
-
3537
- ### Product (1)
3538
- - \`stock-check\` - Check product option stock availability
3906
+ The hosted HTTP MCP endpoint at https://mcp.01.software/mcp exposes only these OAuth-safe tools:
3539
3907
 
3540
3908
  ### Schema (1)
3541
3909
  - \`get-collection-schema\` - Get authoritative tenant-aware collection schema
3542
3910
 
3543
- ### Tenant Context (1)
3911
+ ### Tenant Context (2)
3544
3912
  - \`get-tenant-context\` - Get tenant features, active collections, and field config
3913
+ - \`check-feature-progress\` - Check ecommerce implementation progress without mutating tenant data
3545
3914
 
3546
3915
  ### Field Config (2)
3547
3916
  - \`list-configurable-fields\` - List configurable fields and current hidden state
@@ -3553,6 +3922,16 @@ url = "https://mcp.01.software/mcp"
3553
3922
  - \`sdk-get-auth-setup\` - Get framework-specific auth setup guidance
3554
3923
  - \`sdk-get-collection-pattern\` - Get collection-specific usage patterns
3555
3924
 
3925
+ ## Local CLI Stdio Surface (30)
3926
+
3927
+ For trusted local server-key workflows, start the stdio server:
3928
+
3929
+ \`\`\`bash
3930
+ npx @01.software/cli mcp
3931
+ \`\`\`
3932
+
3933
+ Local stdio can expose generic read, order, return, cart, validation, stock, schema, tenant context, feature progress, 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.
3934
+
3556
3935
  ## Rate Limits
3557
3936
 
3558
3937
  Rate limits depend on your tenant plan:
@@ -3564,8 +3943,8 @@ Rate limits depend on your tenant plan:
3564
3943
  }
3565
3944
 
3566
3945
  // src/resources/(collections)/schema.ts
3567
- import { COLLECTIONS as COLLECTIONS6 } from "@01.software/sdk";
3568
- var metadata35 = {
3946
+ import { COLLECTIONS as COLLECTIONS3 } from "@01.software/sdk";
3947
+ var metadata36 = {
3569
3948
  name: "collections-schema",
3570
3949
  title: "Collection Schema Info",
3571
3950
  description: "Available collections and their schema information"
@@ -3593,13 +3972,18 @@ var COLLECTIONS_BY_CATEGORY = {
3593
3972
  Customers: [
3594
3973
  "customers",
3595
3974
  "customer-profiles",
3596
- "customer-addresses",
3597
- "customer-groups"
3975
+ "customer-profile-lists",
3976
+ "customer-addresses"
3598
3977
  ],
3599
3978
  Carts: ["carts", "cart-items"],
3600
3979
  "Discounts & Promotions": ["discounts", "promotions"],
3601
3980
  Documents: ["documents", "document-categories", "document-types"],
3602
- Articles: ["articles", "article-authors", "article-categories", "article-tags"],
3981
+ Articles: [
3982
+ "articles",
3983
+ "article-authors",
3984
+ "article-categories",
3985
+ "article-tags"
3986
+ ],
3603
3987
  Community: [
3604
3988
  "posts",
3605
3989
  "comments",
@@ -3618,7 +4002,12 @@ var COLLECTIONS_BY_CATEGORY = {
3618
4002
  "track-categories",
3619
4003
  "track-tags"
3620
4004
  ],
3621
- Galleries: ["galleries", "gallery-items", "gallery-categories", "gallery-tags"],
4005
+ Galleries: [
4006
+ "galleries",
4007
+ "gallery-items",
4008
+ "gallery-categories",
4009
+ "gallery-tags"
4010
+ ],
3622
4011
  Links: ["links", "link-categories", "link-tags"],
3623
4012
  Canvas: [
3624
4013
  "canvases",
@@ -3641,9 +4030,9 @@ var COLLECTIONS_BY_CATEGORY = {
3641
4030
  "event-tags"
3642
4031
  ]
3643
4032
  };
3644
- function handler7() {
4033
+ function handler8() {
3645
4034
  const categoryDocs = Object.entries(COLLECTIONS_BY_CATEGORY).map(([category, collections]) => {
3646
- const collectionList = collections.filter((c) => COLLECTIONS6.includes(c)).map((c) => `- **${c}**`).join("\n");
4035
+ const collectionList = collections.filter((c) => COLLECTIONS3.includes(c)).map((c) => `- **${c}**`).join("\n");
3647
4036
  return `## ${category}
3648
4037
  ${collectionList}`;
3649
4038
  }).join("\n\n");
@@ -3664,8 +4053,9 @@ Each collection supports the following operations:
3664
4053
  - \`updateMany(where, data)\` - Bulk update items matching filter
3665
4054
  - \`removeMany(where)\` - Bulk delete items matching filter
3666
4055
 
3667
- Draft-enabled public collections expose only \`_status: 'published'\` rows to
3668
- publishable-key reads unless server-side access explicitly includes drafts.
4056
+ Status-managed public collections expose only \`status: 'published'\` rows to
4057
+ publishable-key reads unless server-side access explicitly includes
4058
+ unpublished statuses.
3669
4059
 
3670
4060
  ## Query Examples
3671
4061
 
@@ -3688,16 +4078,16 @@ publishable-key reads unless server-side access explicitly includes drafts.
3688
4078
  }
3689
4079
  \`\`\`
3690
4080
 
3691
- Total available collections: ${COLLECTIONS6.length}`;
4081
+ Total available collections: ${COLLECTIONS3.length}`;
3692
4082
  }
3693
4083
 
3694
4084
  // src/resources/(docs)/getting-started.ts
3695
- var metadata36 = {
4085
+ var metadata37 = {
3696
4086
  name: "docs-getting-started",
3697
4087
  title: "Getting Started",
3698
4088
  description: "01.software SDK getting started guide"
3699
4089
  };
3700
- function handler8() {
4090
+ function handler9() {
3701
4091
  return `# Getting Started
3702
4092
 
3703
4093
  A guide to getting started with the 01.software SDK.
@@ -3731,18 +4121,18 @@ const result = await client.collections.from('products').find({
3731
4121
 
3732
4122
  ## Next Steps
3733
4123
 
3734
- - [Quick Start](/docs/getting-started/quick-start) - Get started in 5 minutes
3735
- - [Configuration](/docs/getting-started/configuration) - Detailed configuration options
3736
- - [API Reference](/docs/api) - Full API documentation`;
4124
+ - [SDK Guide](/developers/sdk) - Install and query workspace content
4125
+ - [Authentication & Keys](/developers/authentication) - Choose the right key for each surface
4126
+ - [API](/developers/api) - Use the HTTP API when SDKs are not a fit`;
3737
4127
  }
3738
4128
 
3739
4129
  // src/resources/(docs)/guides.ts
3740
- var metadata37 = {
4130
+ var metadata38 = {
3741
4131
  name: "docs-guides",
3742
4132
  title: "Guides",
3743
4133
  description: "01.software SDK usage guides"
3744
4134
  };
3745
- function handler9() {
4135
+ function handler10() {
3746
4136
  return `# Guides
3747
4137
 
3748
4138
  Comprehensive guides to master the 01.software SDK.
@@ -3944,16 +4334,16 @@ Payload query syntax operators:
3944
4334
 
3945
4335
  For ecommerce collections, \`products.listing.*\` is the browse/search projection. Authoritative sellable price and stock remain on \`product-variants\`.
3946
4336
 
3947
- For more detailed guides, see the [Guides page](/docs/guides).`;
4337
+ For more implementation guidance, see the [SDK Guide](/developers/sdk).`;
3948
4338
  }
3949
4339
 
3950
4340
  // src/resources/(docs)/api.ts
3951
- var metadata38 = {
4341
+ var metadata39 = {
3952
4342
  name: "docs-api",
3953
4343
  title: "API Reference",
3954
4344
  description: "01.software SDK API reference documentation"
3955
4345
  };
3956
- function handler10() {
4346
+ function handler11() {
3957
4347
  return `# API Reference
3958
4348
 
3959
4349
  Comprehensive documentation for all methods and types in the 01.software SDK.
@@ -4230,16 +4620,16 @@ client.customer.isAuthenticated() // Check auth status
4230
4620
  client.customer.logout() // Clear token
4231
4621
  \`\`\`
4232
4622
 
4233
- For more details, see the [full API documentation](/docs/api).`;
4623
+ For more details, see the [API documentation](/developers/api).`;
4234
4624
  }
4235
4625
 
4236
4626
  // src/resources/(docs)/query-builder.ts
4237
- var metadata39 = {
4627
+ var metadata40 = {
4238
4628
  name: "docs-query-builder",
4239
4629
  title: "Query Builder",
4240
4630
  description: "01.software SDK Query Builder API reference (client.collections.from)"
4241
4631
  };
4242
- function handler11() {
4632
+ function handler12() {
4243
4633
  return `# Query Builder API
4244
4634
 
4245
4635
  The Query Builder provides a fluent interface for querying collections via \`client.collections.from(collection)\`.
@@ -4428,12 +4818,12 @@ console.log(result.hasNextPage) // true
4428
4818
  }
4429
4819
 
4430
4820
  // src/resources/(docs)/react-query.ts
4431
- var metadata40 = {
4821
+ var metadata41 = {
4432
4822
  name: "docs-react-query",
4433
4823
  title: "React Query Hooks",
4434
4824
  description: "01.software SDK React Query hooks reference (client.query)"
4435
4825
  };
4436
- function handler12() {
4826
+ function handler13() {
4437
4827
  return `# React Query Hooks
4438
4828
 
4439
4829
  React Query hooks are available on the browser-side \`Client\` via \`client.query\`. They provide automatic caching, background refetching, and cache invalidation.
@@ -4676,12 +5066,12 @@ export function ProductList() {
4676
5066
  }
4677
5067
 
4678
5068
  // src/resources/(docs)/server-api.ts
4679
- var metadata41 = {
5069
+ var metadata42 = {
4680
5070
  name: "docs-server-api",
4681
5071
  title: "Server-side API",
4682
5072
  description: "01.software SDK server-side API reference (client.commerce) for orders, fulfillments, returns, carts, and validation"
4683
5073
  };
4684
- function handler13() {
5074
+ function handler14() {
4685
5075
  return `# Server-side API
4686
5076
 
4687
5077
  Server-side operations are available via \`client.commerce\` on \`ServerClient\`. Use \`createServerClient\` with both \`publishableKey\` and \`secretKey\`.
@@ -4938,12 +5328,12 @@ const result = await client.commerce.shipping.calculate({
4938
5328
  }
4939
5329
 
4940
5330
  // src/resources/(docs)/customer-auth.ts
4941
- var metadata42 = {
5331
+ var metadata43 = {
4942
5332
  name: "docs-customer-auth",
4943
5333
  title: "Customer Auth API",
4944
5334
  description: "01.software SDK Customer Auth API reference (client.customer)"
4945
5335
  };
4946
- function handler14() {
5336
+ function handler15() {
4947
5337
  return `# Customer Auth API
4948
5338
 
4949
5339
  Customer authentication and profile management is available via \`client.customer\` on the browser-side \`Client\`.
@@ -5116,12 +5506,12 @@ async function loadProfile() {
5116
5506
  }
5117
5507
 
5118
5508
  // src/resources/(docs)/browser-vs-server.ts
5119
- var metadata43 = {
5509
+ var metadata44 = {
5120
5510
  name: "docs-browser-vs-server",
5121
5511
  title: "Client vs ServerClient",
5122
5512
  description: "When to use Client (createClient) vs ServerClient (createServerClient) in the 01.software SDK"
5123
5513
  };
5124
- function handler15() {
5514
+ function handler16() {
5125
5515
  return `# Client vs ServerClient
5126
5516
 
5127
5517
  The SDK provides two client types for different execution environments.
@@ -5275,12 +5665,12 @@ export function ProductList() {
5275
5665
  }
5276
5666
 
5277
5667
  // src/resources/(docs)/file-upload.ts
5278
- var metadata44 = {
5668
+ var metadata45 = {
5279
5669
  name: "docs-file-upload",
5280
5670
  title: "File Upload",
5281
5671
  description: "01.software SDK file upload patterns using the images collection"
5282
5672
  };
5283
- function handler16() {
5673
+ function handler17() {
5284
5674
  return `# File Upload
5285
5675
 
5286
5676
  Upload files using the \`images\` collection (tenant-scoped, unified image store) or \`system-media\` (global, non-tenant).
@@ -5426,12 +5816,12 @@ The platform stores files in Cloudflare R2 and serves via CDN (\`cdn.01.software
5426
5816
  }
5427
5817
 
5428
5818
  // src/resources/(docs)/webhook.ts
5429
- var metadata45 = {
5819
+ var metadata46 = {
5430
5820
  name: "docs-webhook",
5431
5821
  title: "Webhooks",
5432
5822
  description: "01.software SDK webhook verification and event handling"
5433
5823
  };
5434
- function handler17() {
5824
+ function handler18() {
5435
5825
  return `# Webhooks
5436
5826
 
5437
5827
  The platform dispatches HMAC-SHA256 signed webhook events to your registered URLs. Tenant developers own routing inside their webhook handler.
@@ -5541,7 +5931,7 @@ Configure webhook URLs in the 01.software console under Tenant Settings > Webhoo
5541
5931
 
5542
5932
  // src/server.ts
5543
5933
  var REGISTERED_TOOLS_BY_SERVER = /* @__PURE__ */ new WeakMap();
5544
- function registerTool(server, schema34, meta, handler19) {
5934
+ function registerTool(server, schema35, meta, handler20) {
5545
5935
  let registered = REGISTERED_TOOLS_BY_SERVER.get(server);
5546
5936
  if (!registered) {
5547
5937
  registered = /* @__PURE__ */ new Set();
@@ -5552,7 +5942,7 @@ function registerTool(server, schema34, meta, handler19) {
5552
5942
  meta.name,
5553
5943
  {
5554
5944
  description: meta.description,
5555
- inputSchema: schema34,
5945
+ inputSchema: schema35,
5556
5946
  annotations: meta.annotations
5557
5947
  },
5558
5948
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -5576,31 +5966,48 @@ function registerTool(server, schema34, meta, handler19) {
5576
5966
  };
5577
5967
  }
5578
5968
  }
5579
- const result = await handler19(params);
5580
- return { content: [{ type: "text", text: result }] };
5969
+ const activeSummary = currentMcpTelemetrySummary();
5970
+ const ownSummary = activeSummary || hasRequestContext() ? null : createMcpTelemetrySummary("stdio");
5971
+ const summary = activeSummary ?? ownSummary;
5972
+ let result = null;
5973
+ try {
5974
+ result = await handler20(params);
5975
+ return { content: [{ type: "text", text: result }] };
5976
+ } finally {
5977
+ if (summary) {
5978
+ recordMcpToolResult({
5979
+ resultText: result,
5980
+ summary,
5981
+ toolName: meta.name
5982
+ });
5983
+ }
5984
+ if (ownSummary) {
5985
+ void flushMcpTelemetrySummary(ownSummary);
5986
+ }
5987
+ }
5581
5988
  }
5582
5989
  );
5583
5990
  }
5584
- function registerPrompt(server, schema34, meta, handler19) {
5991
+ function registerPrompt(server, schema35, meta, handler20) {
5585
5992
  server.registerPrompt(
5586
5993
  meta.name,
5587
5994
  {
5588
5995
  title: meta.title,
5589
5996
  description: meta.description,
5590
- argsSchema: schema34
5997
+ argsSchema: schema35
5591
5998
  },
5592
5999
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
5593
6000
  (params) => ({
5594
6001
  messages: [
5595
6002
  {
5596
6003
  role: meta.role ?? "assistant",
5597
- content: { type: "text", text: handler19(params) }
6004
+ content: { type: "text", text: handler20(params) }
5598
6005
  }
5599
6006
  ]
5600
6007
  })
5601
6008
  );
5602
6009
  }
5603
- function registerStaticResource(server, uri, meta, handler19) {
6010
+ function registerStaticResource(server, uri, meta, handler20) {
5604
6011
  server.registerResource(
5605
6012
  meta.name,
5606
6013
  uri,
@@ -5610,7 +6017,7 @@ function registerStaticResource(server, uri, meta, handler19) {
5610
6017
  mimeType: meta.mimeType ?? "text/plain"
5611
6018
  },
5612
6019
  async (url) => ({
5613
- contents: [{ uri: url.href, text: handler19() }]
6020
+ contents: [{ uri: url.href, text: handler20() }]
5614
6021
  })
5615
6022
  );
5616
6023
  }
@@ -5621,52 +6028,238 @@ function createServer(options = {}) {
5621
6028
  version: "0.1.0"
5622
6029
  });
5623
6030
  if (toolSurface === "full") {
5624
- registerTool(server, schema, metadata, queryCollection);
5625
- registerTool(server, schema2, metadata2, getCollectionById);
6031
+ registerTool(
6032
+ server,
6033
+ schema,
6034
+ metadata,
6035
+ queryCollection
6036
+ );
6037
+ registerTool(
6038
+ server,
6039
+ schema2,
6040
+ metadata2,
6041
+ getCollectionById
6042
+ );
5626
6043
  registerTool(server, schema3, metadata3, getOrder);
5627
6044
  registerTool(server, schema4, metadata4, createOrder);
5628
6045
  registerTool(server, schema5, metadata5, updateOrder);
5629
6046
  registerTool(server, schema6, metadata6, checkout);
5630
- registerTool(server, schema7, metadata7, createFulfillment);
5631
- registerTool(server, schema8, metadata8, updateFulfillment);
5632
- registerTool(server, schema9, metadata9, updateTransaction);
5633
- registerTool(server, schema10, metadata10, createReturn);
5634
- registerTool(server, schema11, metadata11, updateReturn);
5635
- registerTool(server, schema12, metadata12, returnWithRefund);
6047
+ registerTool(
6048
+ server,
6049
+ schema7,
6050
+ metadata7,
6051
+ createFulfillment
6052
+ );
6053
+ registerTool(
6054
+ server,
6055
+ schema8,
6056
+ metadata8,
6057
+ updateFulfillment
6058
+ );
6059
+ registerTool(
6060
+ server,
6061
+ schema9,
6062
+ metadata9,
6063
+ updateTransaction
6064
+ );
6065
+ registerTool(
6066
+ server,
6067
+ schema10,
6068
+ metadata10,
6069
+ createReturn
6070
+ );
6071
+ registerTool(
6072
+ server,
6073
+ schema11,
6074
+ metadata11,
6075
+ updateReturn
6076
+ );
6077
+ registerTool(
6078
+ server,
6079
+ schema12,
6080
+ metadata12,
6081
+ returnWithRefund
6082
+ );
5636
6083
  registerTool(server, schema13, metadata13, addCartItem);
5637
- registerTool(server, schema14, metadata14, updateCartItem);
5638
- registerTool(server, schema15, metadata15, removeCartItem);
5639
- registerTool(server, schema16, metadata16, applyDiscount);
5640
- registerTool(server, schema17, metadata17, removeDiscount);
6084
+ registerTool(
6085
+ server,
6086
+ schema14,
6087
+ metadata14,
6088
+ updateCartItem
6089
+ );
6090
+ registerTool(
6091
+ server,
6092
+ schema15,
6093
+ metadata15,
6094
+ removeCartItem
6095
+ );
6096
+ registerTool(
6097
+ server,
6098
+ schema16,
6099
+ metadata16,
6100
+ applyDiscount
6101
+ );
6102
+ registerTool(
6103
+ server,
6104
+ schema17,
6105
+ metadata17,
6106
+ removeDiscount
6107
+ );
5641
6108
  registerTool(server, schema18, metadata18, clearCart);
5642
- registerTool(server, schema19, metadata19, validateDiscount);
5643
- registerTool(server, schema20, metadata20, calculateShipping);
6109
+ registerTool(
6110
+ server,
6111
+ schema19,
6112
+ metadata19,
6113
+ validateDiscount
6114
+ );
6115
+ registerTool(
6116
+ server,
6117
+ schema20,
6118
+ metadata20,
6119
+ calculateShipping
6120
+ );
5644
6121
  registerTool(server, schema21, metadata21, stockCheck);
5645
6122
  }
5646
- registerTool(server, schema22, metadata22, getCollectionSchemaTool);
5647
- registerTool(server, schema23, metadata23, handler);
5648
- registerTool(server, schema24, metadata24, listConfigurableFields);
5649
- registerTool(server, schema25, metadata25, updateFieldConfig);
5650
- registerTool(server, schema26, metadata26, handler2);
5651
- registerTool(server, schema27, metadata27, handler3);
5652
- registerTool(server, schema28, metadata28, handler4);
5653
- registerTool(server, schema29, metadata29, handler5);
5654
- registerPrompt(server, schema30, metadata30, sdkUsageGuide);
5655
- registerPrompt(server, schema31, metadata31, collectionQueryHelp);
5656
- registerPrompt(server, schema32, metadata32, orderFlowGuide);
5657
- registerPrompt(server, schema33, metadata33, featureSetupGuide);
5658
- registerStaticResource(server, "config://app", metadata34, handler6);
5659
- registerStaticResource(server, "collections://schema", metadata35, handler7);
5660
- registerStaticResource(server, "docs://sdk/getting-started", metadata36, handler8);
5661
- registerStaticResource(server, "docs://sdk/guides", metadata37, handler9);
5662
- registerStaticResource(server, "docs://sdk/api", metadata38, handler10);
5663
- registerStaticResource(server, "docs://sdk/query-builder", metadata39, handler11);
5664
- registerStaticResource(server, "docs://sdk/react-query", metadata40, handler12);
5665
- registerStaticResource(server, "docs://sdk/server-api", metadata41, handler13);
5666
- registerStaticResource(server, "docs://sdk/customer-auth", metadata42, handler14);
5667
- registerStaticResource(server, "docs://sdk/browser-vs-server", metadata43, handler15);
5668
- registerStaticResource(server, "docs://sdk/file-upload", metadata44, handler16);
5669
- registerStaticResource(server, "docs://sdk/webhook", metadata45, handler17);
6123
+ registerTool(
6124
+ server,
6125
+ schema22,
6126
+ metadata22,
6127
+ getCollectionSchemaTool
6128
+ );
6129
+ registerTool(
6130
+ server,
6131
+ schema23,
6132
+ metadata23,
6133
+ handler
6134
+ );
6135
+ registerTool(
6136
+ server,
6137
+ schema24,
6138
+ metadata24,
6139
+ handler2
6140
+ );
6141
+ registerTool(
6142
+ server,
6143
+ schema25,
6144
+ metadata25,
6145
+ listConfigurableFields
6146
+ );
6147
+ registerTool(
6148
+ server,
6149
+ schema26,
6150
+ metadata26,
6151
+ updateFieldConfig
6152
+ );
6153
+ registerTool(
6154
+ server,
6155
+ schema27,
6156
+ metadata27,
6157
+ handler3
6158
+ );
6159
+ registerTool(
6160
+ server,
6161
+ schema28,
6162
+ metadata28,
6163
+ handler4
6164
+ );
6165
+ registerTool(
6166
+ server,
6167
+ schema29,
6168
+ metadata29,
6169
+ handler5
6170
+ );
6171
+ registerTool(
6172
+ server,
6173
+ schema30,
6174
+ metadata30,
6175
+ handler6
6176
+ );
6177
+ registerPrompt(
6178
+ server,
6179
+ schema31,
6180
+ metadata31,
6181
+ sdkUsageGuide
6182
+ );
6183
+ registerPrompt(
6184
+ server,
6185
+ schema32,
6186
+ metadata32,
6187
+ collectionQueryHelp
6188
+ );
6189
+ registerPrompt(
6190
+ server,
6191
+ schema33,
6192
+ metadata33,
6193
+ orderFlowGuide
6194
+ );
6195
+ registerPrompt(
6196
+ server,
6197
+ schema34,
6198
+ metadata34,
6199
+ featureSetupGuide
6200
+ );
6201
+ registerStaticResource(
6202
+ server,
6203
+ "config://app",
6204
+ metadata35,
6205
+ handler7
6206
+ );
6207
+ registerStaticResource(
6208
+ server,
6209
+ "collections://schema",
6210
+ metadata36,
6211
+ handler8
6212
+ );
6213
+ registerStaticResource(
6214
+ server,
6215
+ "docs://sdk/getting-started",
6216
+ metadata37,
6217
+ handler9
6218
+ );
6219
+ registerStaticResource(server, "docs://sdk/guides", metadata38, handler10);
6220
+ registerStaticResource(server, "docs://sdk/api", metadata39, handler11);
6221
+ registerStaticResource(
6222
+ server,
6223
+ "docs://sdk/query-builder",
6224
+ metadata40,
6225
+ handler12
6226
+ );
6227
+ registerStaticResource(
6228
+ server,
6229
+ "docs://sdk/react-query",
6230
+ metadata41,
6231
+ handler13
6232
+ );
6233
+ registerStaticResource(
6234
+ server,
6235
+ "docs://sdk/server-api",
6236
+ metadata42,
6237
+ handler14
6238
+ );
6239
+ registerStaticResource(
6240
+ server,
6241
+ "docs://sdk/customer-auth",
6242
+ metadata43,
6243
+ handler15
6244
+ );
6245
+ registerStaticResource(
6246
+ server,
6247
+ "docs://sdk/browser-vs-server",
6248
+ metadata44,
6249
+ handler16
6250
+ );
6251
+ registerStaticResource(
6252
+ server,
6253
+ "docs://sdk/file-upload",
6254
+ metadata45,
6255
+ handler17
6256
+ );
6257
+ registerStaticResource(
6258
+ server,
6259
+ "docs://sdk/webhook",
6260
+ metadata46,
6261
+ handler18
6262
+ );
5670
6263
  return server;
5671
6264
  }
5672
6265
 
@@ -5871,7 +6464,10 @@ function setCors(res) {
5871
6464
  "Access-Control-Allow-Headers",
5872
6465
  "Authorization, Content-Type, mcp-session-id"
5873
6466
  );
5874
- res.setHeader("Access-Control-Expose-Headers", "Mcp-Session-Id, Mcp-Protocol-Version");
6467
+ res.setHeader(
6468
+ "Access-Control-Expose-Headers",
6469
+ "Mcp-Session-Id, Mcp-Protocol-Version"
6470
+ );
5875
6471
  }
5876
6472
  function getHeaderValue(headers, name) {
5877
6473
  const value = headers[name.toLowerCase()];
@@ -5951,7 +6547,7 @@ HTTP OAuth Tools
5951
6547
  ----------------
5952
6548
 
5953
6549
  Schema get-collection-schema
5954
- Context get-tenant-context
6550
+ Context get-tenant-context, check-feature-progress
5955
6551
  Field Config list-configurable-fields, update-field-config
5956
6552
  Guidance sdk-get-recipe, sdk-search-docs, sdk-get-auth-setup, sdk-get-collection-pattern
5957
6553
 
@@ -5970,9 +6566,9 @@ Resources (12): config, collections-schema, getting-started, guides, api, query-
5970
6566
  Links
5971
6567
  -----
5972
6568
 
5973
- Docs https://01.software/docs/integrations/mcp
5974
- SDK https://01.software/docs/sdk/client
5975
- API Reference https://01.software/docs/api/rest-api
6569
+ Integrations https://docs.01.software/integrations
6570
+ Readiness https://docs.01.software/readiness
6571
+ OpenAPI https://docs.01.software/api/openapi
5976
6572
  Console https://console.01.software
5977
6573
  `;
5978
6574
  var PROTECTED_RESOURCE_METADATA = JSON.stringify({
@@ -5980,15 +6576,26 @@ var PROTECTED_RESOURCE_METADATA = JSON.stringify({
5980
6576
  authorization_servers: [MCP_OAUTH_ISSUER],
5981
6577
  scopes_supported: [MCP_SCOPES.read, MCP_SCOPES.write]
5982
6578
  });
6579
+ var PROTECTED_RESOURCE_METADATA_URL = new URL(
6580
+ MCP_PROTECTED_RESOURCE_METADATA_PATH,
6581
+ MCP_RESOURCE_AUDIENCE
6582
+ ).toString();
5983
6583
  var SERVICE_JWKS_PATH = "/.well-known/service-jwks.json";
5984
6584
  function writeOAuthError(res, status, error, description) {
5985
6585
  res.writeHead(status, {
5986
6586
  "Content-Type": "application/json",
5987
- "WWW-Authenticate": `Bearer resource_metadata="${MCP_PROTECTED_RESOURCE_METADATA_PATH}", error="${error}", error_description="${description}"`
6587
+ "WWW-Authenticate": `Bearer resource_metadata="${PROTECTED_RESOURCE_METADATA_URL}", error="${error}", error_description="${description}"`
5988
6588
  });
5989
6589
  res.end(JSON.stringify({ error, error_description: description }));
5990
6590
  }
5991
- async function handler18(req, res) {
6591
+ function acceptsEventStream(req) {
6592
+ const accept = getHeaderValue(req.headers, "accept");
6593
+ if (!accept) return false;
6594
+ return accept.split(",").some(
6595
+ (entry) => entry.trim().split(";")[0]?.toLowerCase() === "text/event-stream"
6596
+ );
6597
+ }
6598
+ async function handler19(req, res) {
5992
6599
  setCors(res);
5993
6600
  if (req.method === "OPTIONS") {
5994
6601
  res.writeHead(204);
@@ -6020,6 +6627,11 @@ async function handler18(req, res) {
6020
6627
  }
6021
6628
  return;
6022
6629
  }
6630
+ if (acceptsEventStream(req)) {
6631
+ res.writeHead(405, { "Content-Type": "application/json" });
6632
+ res.end(METHOD_NOT_ALLOWED);
6633
+ return;
6634
+ }
6023
6635
  res.writeHead(200, { "Content-Type": "text/plain; charset=utf-8" });
6024
6636
  res.end(HOME_PAGE);
6025
6637
  return;
@@ -6033,7 +6645,12 @@ async function handler18(req, res) {
6033
6645
  getHeaderValue(req.headers, "authorization")
6034
6646
  );
6035
6647
  if (!auth.valid) {
6036
- writeOAuthError(res, auth.error === "insufficient_scope" ? 403 : 401, auth.error, auth.errorDescription);
6648
+ writeOAuthError(
6649
+ res,
6650
+ auth.error === "insufficient_scope" ? 403 : 401,
6651
+ auth.error,
6652
+ auth.errorDescription
6653
+ );
6037
6654
  return;
6038
6655
  }
6039
6656
  const server = createServer({ toolSurface: "oauth" });
@@ -6056,14 +6673,19 @@ async function handler18(req, res) {
6056
6673
  if (typeof value === "string") headers.set(key, value);
6057
6674
  else if (Array.isArray(value)) headers.set(key, value.join(", "));
6058
6675
  }
6676
+ const telemetrySummary = createMcpTelemetrySummary("http");
6059
6677
  await requestContext.run({ headers, auth: auth.context }, async () => {
6060
6678
  try {
6061
- const body = req.body ?? JSON.parse(await readBody(req));
6062
- await transport.handleRequest(req, res, body);
6679
+ await runWithMcpTelemetry(telemetrySummary, async () => {
6680
+ const body = req.body ?? JSON.parse(await readBody(req));
6681
+ await transport.handleRequest(req, res, body);
6682
+ });
6063
6683
  } catch (err) {
6064
6684
  writeRequestError(res, err);
6065
6685
  } finally {
6686
+ telemetrySummary.durationMs = Date.now() - telemetrySummary.startedAtMs;
6066
6687
  await close();
6688
+ await flushMcpTelemetrySummary(telemetrySummary);
6067
6689
  }
6068
6690
  });
6069
6691
  }
@@ -6083,5 +6705,5 @@ function writeRequestError(res, err) {
6083
6705
  res.end(JSON.stringify({ error: "Internal server error" }));
6084
6706
  }
6085
6707
  export {
6086
- handler18 as default
6708
+ handler19 as default
6087
6709
  };