@01.software/cli 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +205 -28
- package/dist/index.js.map +1 -1
- package/dist/mcp/{chunk-GJOQ4SE2.js → chunk-CADO6WG6.js} +657 -391
- package/dist/mcp/chunk-CADO6WG6.js.map +1 -0
- package/dist/mcp/http.js +30 -8
- package/dist/mcp/http.js.map +1 -1
- package/dist/mcp/stdio.js +1 -1
- package/dist/mcp/vercel.js +678 -396
- package/package.json +2 -2
- package/dist/mcp/chunk-GJOQ4SE2.js.map +0 -1
package/dist/mcp/vercel.js
CHANGED
|
@@ -91,6 +91,285 @@ 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 COLLECTION_SCHEMA_CONTRACT_VERSION = 1;
|
|
129
|
+
var collectionSchemaEndpointParamsSchema = z.object({
|
|
130
|
+
collectionSlug: z.string().min(1, "collectionSlug is required")
|
|
131
|
+
}).strict();
|
|
132
|
+
function createCollectionSchemaToolInputSchema(collections) {
|
|
133
|
+
return z.object({
|
|
134
|
+
collection: z.enum(collections).describe("Collection name (required)")
|
|
135
|
+
}).strict();
|
|
136
|
+
}
|
|
137
|
+
var collectionFieldOptionSchema = z.object({
|
|
138
|
+
label: z.string(),
|
|
139
|
+
value: z.string()
|
|
140
|
+
}).strict();
|
|
141
|
+
var collectionFieldSchema = z.lazy(
|
|
142
|
+
() => z.object({
|
|
143
|
+
name: z.string(),
|
|
144
|
+
path: z.string(),
|
|
145
|
+
type: z.string(),
|
|
146
|
+
required: z.literal(true).optional(),
|
|
147
|
+
unique: z.literal(true).optional(),
|
|
148
|
+
hasMany: z.literal(true).optional(),
|
|
149
|
+
relationTo: z.union([z.string(), z.array(z.string())]).optional(),
|
|
150
|
+
options: z.array(collectionFieldOptionSchema).optional(),
|
|
151
|
+
hidden: z.literal(true).optional(),
|
|
152
|
+
systemManaged: z.literal(true).optional(),
|
|
153
|
+
writable: z.boolean().optional(),
|
|
154
|
+
fields: z.array(collectionFieldSchema).optional()
|
|
155
|
+
}).strict()
|
|
156
|
+
);
|
|
157
|
+
var collectionSchemaResponseSchema = z.object({
|
|
158
|
+
contractVersion: z.literal(COLLECTION_SCHEMA_CONTRACT_VERSION),
|
|
159
|
+
mode: z.literal("effective"),
|
|
160
|
+
collection: z.object({
|
|
161
|
+
slug: z.string(),
|
|
162
|
+
timestamps: z.boolean(),
|
|
163
|
+
alwaysActive: z.boolean(),
|
|
164
|
+
feature: z.string().nullable(),
|
|
165
|
+
systemFields: z.array(z.string()),
|
|
166
|
+
visibility: z.object({
|
|
167
|
+
collectionHidden: z.boolean(),
|
|
168
|
+
hiddenFields: z.array(z.string())
|
|
169
|
+
}).strict(),
|
|
170
|
+
fields: z.array(collectionFieldSchema)
|
|
171
|
+
}).strict()
|
|
172
|
+
}).strict();
|
|
173
|
+
|
|
174
|
+
// ../../packages/contracts/src/ecommerce/index.ts
|
|
175
|
+
import { z as z2 } from "zod";
|
|
176
|
+
var transactionStatusSchema = z2.enum([
|
|
177
|
+
"pending",
|
|
178
|
+
"paid",
|
|
179
|
+
"failed",
|
|
180
|
+
"canceled"
|
|
181
|
+
]);
|
|
182
|
+
var updateTransactionSchema = z2.object({
|
|
183
|
+
pgPaymentId: z2.string().min(1, "pgPaymentId is required").describe("PG payment ID (required)"),
|
|
184
|
+
status: transactionStatusSchema.describe(
|
|
185
|
+
"New transaction status (required)"
|
|
186
|
+
),
|
|
187
|
+
paymentMethod: z2.string().optional().describe("Payment method (optional)"),
|
|
188
|
+
receiptUrl: z2.string().optional().describe("Receipt URL (optional)"),
|
|
189
|
+
paymentKey: z2.string().min(1).optional().describe("Provider payment key for verified paid confirmation"),
|
|
190
|
+
amount: z2.number().int().positive().optional().describe("Provider-confirmed amount for verified paid confirmation")
|
|
191
|
+
}).strict();
|
|
192
|
+
var UpdateTransactionSchema = updateTransactionSchema;
|
|
193
|
+
var returnReasonSchema = z2.enum([
|
|
194
|
+
"change_of_mind",
|
|
195
|
+
"defective",
|
|
196
|
+
"wrong_delivery",
|
|
197
|
+
"damaged",
|
|
198
|
+
"other"
|
|
199
|
+
]);
|
|
200
|
+
var restockActionSchema = z2.enum(["return_to_stock", "discard"]);
|
|
201
|
+
var returnWithRefundItemSchema = z2.object({
|
|
202
|
+
orderItem: z2.union([z2.string(), z2.number()]).transform(String),
|
|
203
|
+
quantity: z2.number().int().positive("quantity must be a positive integer"),
|
|
204
|
+
restockAction: restockActionSchema.default("return_to_stock")
|
|
205
|
+
}).strict();
|
|
206
|
+
var returnWithRefundSchema = z2.object({
|
|
207
|
+
orderNumber: z2.string().min(1, "orderNumber is required").describe("Order number (required)"),
|
|
208
|
+
reason: returnReasonSchema.optional().describe("Return reason (optional)"),
|
|
209
|
+
reasonDetail: z2.string().optional().describe("Detailed reason text (optional)"),
|
|
210
|
+
returnItems: z2.array(returnWithRefundItemSchema).min(1, "At least one return item is required").max(100, "Too many return items").describe("Array of products to return (required)"),
|
|
211
|
+
refundAmount: z2.number().min(0, "refundAmount must be non-negative").describe("Refund amount (required, min 0)"),
|
|
212
|
+
pgPaymentId: z2.string().min(1, "pgPaymentId is required").describe("PG payment ID for refund (required)"),
|
|
213
|
+
paymentKey: z2.string().min(1).optional().describe("Provider payment key for verified refund"),
|
|
214
|
+
refundReceiptUrl: z2.string().optional().describe("Refund receipt URL (optional)")
|
|
215
|
+
}).strict();
|
|
216
|
+
var ReturnWithRefundSchema = returnWithRefundSchema;
|
|
217
|
+
|
|
218
|
+
// ../../packages/contracts/src/mcp/index.ts
|
|
219
|
+
var MCP_TOOL_CONTRACT = {
|
|
220
|
+
"query-collection": {
|
|
221
|
+
consoleRole: "tenant-viewer",
|
|
222
|
+
oauthScope: "mcp:read",
|
|
223
|
+
readOnly: true
|
|
224
|
+
},
|
|
225
|
+
"get-collection-by-id": {
|
|
226
|
+
consoleRole: "tenant-viewer",
|
|
227
|
+
oauthScope: "mcp:read",
|
|
228
|
+
readOnly: true
|
|
229
|
+
},
|
|
230
|
+
"get-order": {
|
|
231
|
+
consoleRole: "tenant-viewer",
|
|
232
|
+
oauthScope: "mcp:read",
|
|
233
|
+
readOnly: true
|
|
234
|
+
},
|
|
235
|
+
"stock-check": {
|
|
236
|
+
consoleRole: "tenant-viewer",
|
|
237
|
+
oauthScope: "mcp:read",
|
|
238
|
+
readOnly: true
|
|
239
|
+
},
|
|
240
|
+
"validate-discount": {
|
|
241
|
+
consoleRole: "tenant-viewer",
|
|
242
|
+
oauthScope: "mcp:read",
|
|
243
|
+
readOnly: true
|
|
244
|
+
},
|
|
245
|
+
"calculate-shipping": {
|
|
246
|
+
consoleRole: "tenant-viewer",
|
|
247
|
+
oauthScope: "mcp:read",
|
|
248
|
+
readOnly: true
|
|
249
|
+
},
|
|
250
|
+
"get-collection-schema": {
|
|
251
|
+
consoleRole: "tenant-viewer",
|
|
252
|
+
oauthScope: "mcp:read",
|
|
253
|
+
readOnly: true
|
|
254
|
+
},
|
|
255
|
+
"list-configurable-fields": {
|
|
256
|
+
consoleRole: "tenant-viewer",
|
|
257
|
+
oauthScope: "mcp:read",
|
|
258
|
+
readOnly: true
|
|
259
|
+
},
|
|
260
|
+
"get-tenant-context": {
|
|
261
|
+
consoleRole: "tenant-viewer",
|
|
262
|
+
oauthScope: "mcp:read",
|
|
263
|
+
readOnly: true
|
|
264
|
+
},
|
|
265
|
+
"add-cart-item": {
|
|
266
|
+
consoleRole: "tenant-editor",
|
|
267
|
+
oauthScope: "mcp:write",
|
|
268
|
+
readOnly: false
|
|
269
|
+
},
|
|
270
|
+
"update-cart-item": {
|
|
271
|
+
consoleRole: "tenant-editor",
|
|
272
|
+
oauthScope: "mcp:write",
|
|
273
|
+
readOnly: false
|
|
274
|
+
},
|
|
275
|
+
"remove-cart-item": {
|
|
276
|
+
consoleRole: "tenant-editor",
|
|
277
|
+
oauthScope: "mcp:write",
|
|
278
|
+
readOnly: false
|
|
279
|
+
},
|
|
280
|
+
"clear-cart": {
|
|
281
|
+
consoleRole: "tenant-editor",
|
|
282
|
+
oauthScope: "mcp:write",
|
|
283
|
+
readOnly: false
|
|
284
|
+
},
|
|
285
|
+
"apply-discount": {
|
|
286
|
+
consoleRole: "tenant-editor",
|
|
287
|
+
oauthScope: "mcp:write",
|
|
288
|
+
readOnly: false
|
|
289
|
+
},
|
|
290
|
+
"remove-discount": {
|
|
291
|
+
consoleRole: "tenant-editor",
|
|
292
|
+
oauthScope: "mcp:write",
|
|
293
|
+
readOnly: false
|
|
294
|
+
},
|
|
295
|
+
checkout: {
|
|
296
|
+
consoleRole: "tenant-admin",
|
|
297
|
+
oauthScope: "mcp:write",
|
|
298
|
+
readOnly: false
|
|
299
|
+
},
|
|
300
|
+
"create-order": {
|
|
301
|
+
consoleRole: "tenant-admin",
|
|
302
|
+
oauthScope: "mcp:write",
|
|
303
|
+
readOnly: false
|
|
304
|
+
},
|
|
305
|
+
"update-order": {
|
|
306
|
+
consoleRole: "tenant-admin",
|
|
307
|
+
oauthScope: "mcp:write",
|
|
308
|
+
readOnly: false
|
|
309
|
+
},
|
|
310
|
+
"create-fulfillment": {
|
|
311
|
+
consoleRole: "tenant-admin",
|
|
312
|
+
oauthScope: "mcp:write",
|
|
313
|
+
readOnly: false
|
|
314
|
+
},
|
|
315
|
+
"update-fulfillment": {
|
|
316
|
+
consoleRole: "tenant-admin",
|
|
317
|
+
oauthScope: "mcp:write",
|
|
318
|
+
readOnly: false
|
|
319
|
+
},
|
|
320
|
+
"create-return": {
|
|
321
|
+
consoleRole: "tenant-admin",
|
|
322
|
+
oauthScope: "mcp:write",
|
|
323
|
+
readOnly: false
|
|
324
|
+
},
|
|
325
|
+
"update-return": {
|
|
326
|
+
consoleRole: "tenant-admin",
|
|
327
|
+
oauthScope: "mcp:write",
|
|
328
|
+
readOnly: false
|
|
329
|
+
},
|
|
330
|
+
"return-with-refund": {
|
|
331
|
+
consoleRole: "tenant-admin",
|
|
332
|
+
oauthScope: "mcp:write",
|
|
333
|
+
readOnly: false
|
|
334
|
+
},
|
|
335
|
+
"update-transaction": {
|
|
336
|
+
consoleRole: "tenant-admin",
|
|
337
|
+
oauthScope: "mcp:write",
|
|
338
|
+
readOnly: false
|
|
339
|
+
},
|
|
340
|
+
"update-field-config": {
|
|
341
|
+
consoleRole: "tenant-admin",
|
|
342
|
+
oauthScope: "mcp:write",
|
|
343
|
+
readOnly: false
|
|
344
|
+
},
|
|
345
|
+
"sdk-get-recipe": {
|
|
346
|
+
consoleRole: "tenant-viewer",
|
|
347
|
+
oauthScope: "mcp:read",
|
|
348
|
+
readOnly: true
|
|
349
|
+
},
|
|
350
|
+
"sdk-search-docs": {
|
|
351
|
+
consoleRole: "tenant-viewer",
|
|
352
|
+
oauthScope: "mcp:read",
|
|
353
|
+
readOnly: true
|
|
354
|
+
},
|
|
355
|
+
"sdk-get-auth-setup": {
|
|
356
|
+
consoleRole: "tenant-viewer",
|
|
357
|
+
oauthScope: "mcp:read",
|
|
358
|
+
readOnly: true
|
|
359
|
+
},
|
|
360
|
+
"sdk-get-collection-pattern": {
|
|
361
|
+
consoleRole: "tenant-viewer",
|
|
362
|
+
oauthScope: "mcp:read",
|
|
363
|
+
readOnly: true
|
|
364
|
+
}
|
|
365
|
+
};
|
|
366
|
+
var MCP_TOOL_NAMES = Object.keys(
|
|
367
|
+
MCP_TOOL_CONTRACT
|
|
368
|
+
);
|
|
369
|
+
function isMcpToolName(toolName) {
|
|
370
|
+
return Object.prototype.hasOwnProperty.call(MCP_TOOL_CONTRACT, toolName);
|
|
371
|
+
}
|
|
372
|
+
|
|
94
373
|
// src/tool-policy.ts
|
|
95
374
|
var READ_ONLY_ANNOTATION = {
|
|
96
375
|
readOnly: true,
|
|
@@ -347,14 +626,14 @@ var TOOL_POLICY_MANIFEST = {
|
|
|
347
626
|
}
|
|
348
627
|
};
|
|
349
628
|
function evaluateToolPolicy(toolName, scopes) {
|
|
350
|
-
|
|
351
|
-
if (!entry) {
|
|
629
|
+
if (!isMcpToolName(toolName)) {
|
|
352
630
|
return {
|
|
353
631
|
allowed: false,
|
|
354
632
|
reason: "tool_policy_missing",
|
|
355
633
|
message: `No tool-policy entry for ${toolName}`
|
|
356
634
|
};
|
|
357
635
|
}
|
|
636
|
+
const entry = TOOL_POLICY_MANIFEST[toolName];
|
|
358
637
|
if (!scopes.includes(entry.oauthScope)) {
|
|
359
638
|
return {
|
|
360
639
|
allowed: false,
|
|
@@ -365,17 +644,12 @@ function evaluateToolPolicy(toolName, scopes) {
|
|
|
365
644
|
return { allowed: true, entry };
|
|
366
645
|
}
|
|
367
646
|
|
|
368
|
-
// src/
|
|
369
|
-
import {
|
|
647
|
+
// src/lib/mcp-telemetry.ts
|
|
648
|
+
import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
|
|
649
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
370
650
|
|
|
371
|
-
// src/lib/
|
|
372
|
-
import {
|
|
373
|
-
CollectionClient,
|
|
374
|
-
CommunityClient,
|
|
375
|
-
ModerationApi,
|
|
376
|
-
ServerCommerceClient,
|
|
377
|
-
createServerClient
|
|
378
|
-
} from "@01.software/sdk";
|
|
651
|
+
// src/lib/console-api.ts
|
|
652
|
+
import { createHash } from "crypto";
|
|
379
653
|
|
|
380
654
|
// src/service-auth.ts
|
|
381
655
|
import { createPrivateKey, randomUUID, sign as signBytes } from "crypto";
|
|
@@ -504,43 +778,209 @@ function signMcpServiceToken(context) {
|
|
|
504
778
|
return `${signingInput}.${signature.toString("base64url")}`;
|
|
505
779
|
}
|
|
506
780
|
|
|
507
|
-
// src/lib/
|
|
781
|
+
// src/lib/console-api.ts
|
|
782
|
+
var BASE_URL = process.env.SOFTWARE_API_URL || "http://localhost:3000";
|
|
783
|
+
var TIMEOUT_MS = 5e3;
|
|
508
784
|
var MISSING_HTTP_AUTH_CONTEXT_ERROR = "MCP HTTP requests require a validated OAuth tenant context before tool execution.";
|
|
509
|
-
function
|
|
785
|
+
function resolveAuthHeaderContext() {
|
|
510
786
|
const oauthContext = tenantAuthContext();
|
|
511
787
|
if (oauthContext) {
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
commerce: void 0,
|
|
516
|
-
collections: void 0,
|
|
517
|
-
community: void 0
|
|
518
|
-
};
|
|
519
|
-
const onRequestId = (id) => {
|
|
520
|
-
client.lastRequestId = id;
|
|
788
|
+
return {
|
|
789
|
+
apiKey: signMcpServiceToken(oauthContext),
|
|
790
|
+
mode: "oauth"
|
|
521
791
|
};
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
792
|
+
}
|
|
793
|
+
if (hasRequestContext()) throw new Error(MISSING_HTTP_AUTH_CONTEXT_ERROR);
|
|
794
|
+
return {
|
|
795
|
+
apiKey: process.env.SOFTWARE_SECRET_KEY,
|
|
796
|
+
mode: "stdio",
|
|
797
|
+
publishableKey: process.env.SOFTWARE_PUBLISHABLE_KEY ?? process.env.NEXT_PUBLIC_SOFTWARE_PUBLISHABLE_KEY
|
|
798
|
+
};
|
|
799
|
+
}
|
|
800
|
+
function resolveApiKey() {
|
|
801
|
+
const { apiKey } = resolveAuthHeaderContext();
|
|
802
|
+
if (!apiKey || typeof apiKey !== "string") {
|
|
803
|
+
throw new Error(
|
|
804
|
+
"Authentication required. Set SOFTWARE_SECRET_KEY for stdio transport."
|
|
532
805
|
);
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
806
|
+
}
|
|
807
|
+
return apiKey;
|
|
808
|
+
}
|
|
809
|
+
function buildAuthHeaders(apiKey) {
|
|
810
|
+
const { mode, publishableKey } = resolveAuthHeaderContext();
|
|
811
|
+
const headers = {
|
|
812
|
+
Authorization: `Bearer ${apiKey}`
|
|
813
|
+
};
|
|
814
|
+
if (mode === "stdio" && publishableKey) {
|
|
815
|
+
headers["X-Publishable-Key"] = publishableKey;
|
|
816
|
+
}
|
|
817
|
+
return headers;
|
|
818
|
+
}
|
|
819
|
+
function extractErrorMessage(body) {
|
|
820
|
+
if (!body || typeof body !== "object") return void 0;
|
|
821
|
+
const b = body;
|
|
822
|
+
if (typeof b.error === "string") return b.error;
|
|
823
|
+
if (Array.isArray(b.errors) && b.errors[0]?.message) {
|
|
824
|
+
return String(b.errors[0].message);
|
|
825
|
+
}
|
|
826
|
+
if (typeof b.message === "string") return b.message;
|
|
827
|
+
return void 0;
|
|
828
|
+
}
|
|
829
|
+
async function consoleGet(path, apiKey) {
|
|
830
|
+
const authHeaders = buildAuthHeaders(apiKey);
|
|
831
|
+
const controller = new AbortController();
|
|
832
|
+
const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS);
|
|
833
|
+
try {
|
|
834
|
+
const res = await fetch(`${BASE_URL}${path}`, {
|
|
835
|
+
headers: authHeaders,
|
|
836
|
+
signal: controller.signal
|
|
540
837
|
});
|
|
541
|
-
|
|
838
|
+
if (!res.ok) {
|
|
839
|
+
const body = await res.json().catch(() => ({}));
|
|
840
|
+
const msg = extractErrorMessage(body);
|
|
841
|
+
throw new Error(msg || `Console GET ${path} failed: ${res.status}`);
|
|
842
|
+
}
|
|
843
|
+
return res.json();
|
|
844
|
+
} finally {
|
|
845
|
+
clearTimeout(timeoutId);
|
|
542
846
|
}
|
|
543
|
-
|
|
847
|
+
}
|
|
848
|
+
async function consolePost(path, body, apiKey) {
|
|
849
|
+
const authHeaders = buildAuthHeaders(apiKey);
|
|
850
|
+
const controller = new AbortController();
|
|
851
|
+
const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS);
|
|
852
|
+
try {
|
|
853
|
+
const res = await fetch(`${BASE_URL}${path}`, {
|
|
854
|
+
method: "POST",
|
|
855
|
+
headers: { ...authHeaders, "Content-Type": "application/json" },
|
|
856
|
+
body: JSON.stringify(body),
|
|
857
|
+
signal: controller.signal
|
|
858
|
+
});
|
|
859
|
+
if (!res.ok) {
|
|
860
|
+
const errBody = await res.json().catch(() => ({}));
|
|
861
|
+
const msg = extractErrorMessage(errBody);
|
|
862
|
+
throw new Error(msg || `Console POST ${path} failed: ${res.status}`);
|
|
863
|
+
}
|
|
864
|
+
return res.json();
|
|
865
|
+
} finally {
|
|
866
|
+
clearTimeout(timeoutId);
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
async function consolePostTelemetry(path, body, apiKey) {
|
|
870
|
+
const authHeaders = buildAuthHeaders(apiKey);
|
|
871
|
+
const controller = new AbortController();
|
|
872
|
+
const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS);
|
|
873
|
+
try {
|
|
874
|
+
const res = await fetch(`${BASE_URL}${path}`, {
|
|
875
|
+
method: "POST",
|
|
876
|
+
headers: { ...authHeaders, "Content-Type": "application/json" },
|
|
877
|
+
body: JSON.stringify(body),
|
|
878
|
+
signal: controller.signal
|
|
879
|
+
});
|
|
880
|
+
if (!res.ok) {
|
|
881
|
+
const errBody = await res.json().catch(() => ({}));
|
|
882
|
+
const msg = extractErrorMessage(errBody);
|
|
883
|
+
throw new Error(msg || `Console POST ${path} failed: ${res.status}`);
|
|
884
|
+
}
|
|
885
|
+
} finally {
|
|
886
|
+
clearTimeout(timeoutId);
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
// src/lib/mcp-telemetry.ts
|
|
891
|
+
var TELEMETRY_ENDPOINT = "/api/tenants/mcp-telemetry";
|
|
892
|
+
var FLUSH_TIMEOUT_MS = 1500;
|
|
893
|
+
var telemetryContext = new AsyncLocalStorage2();
|
|
894
|
+
function createMcpTelemetrySummary(transport) {
|
|
895
|
+
return {
|
|
896
|
+
sessionId: randomUUID2(),
|
|
897
|
+
startedAtMs: Date.now(),
|
|
898
|
+
successfulWriteCount: 0,
|
|
899
|
+
toolCallCount: 0,
|
|
900
|
+
toolCounts: /* @__PURE__ */ new Map(),
|
|
901
|
+
transport
|
|
902
|
+
};
|
|
903
|
+
}
|
|
904
|
+
function currentMcpTelemetrySummary() {
|
|
905
|
+
return telemetryContext.getStore();
|
|
906
|
+
}
|
|
907
|
+
function runWithMcpTelemetry(summary, fn) {
|
|
908
|
+
return telemetryContext.run(summary, fn);
|
|
909
|
+
}
|
|
910
|
+
function recordMcpToolResult(params) {
|
|
911
|
+
if (!isMcpToolName(params.toolName)) return;
|
|
912
|
+
const toolName = params.toolName;
|
|
913
|
+
params.summary.toolCallCount += 1;
|
|
914
|
+
params.summary.toolCounts.set(
|
|
915
|
+
toolName,
|
|
916
|
+
(params.summary.toolCounts.get(toolName) ?? 0) + 1
|
|
917
|
+
);
|
|
918
|
+
if (!MCP_TOOL_CONTRACT[toolName].readOnly && toolResultSucceeded(params.resultText)) {
|
|
919
|
+
params.summary.successfulWriteCount += 1;
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
function toMcpTelemetryBody(summary) {
|
|
923
|
+
if (summary.toolCallCount <= 0) return null;
|
|
924
|
+
const durationMs = summary.transport === "http" ? Math.max(0, summary.durationMs ?? Date.now() - summary.startedAtMs) : void 0;
|
|
925
|
+
return {
|
|
926
|
+
converted: summary.successfulWriteCount > 0,
|
|
927
|
+
...durationMs !== void 0 ? { durationMs } : {},
|
|
928
|
+
sessionId: summary.sessionId,
|
|
929
|
+
successfulWriteCount: summary.successfulWriteCount,
|
|
930
|
+
toolCallCount: summary.toolCallCount,
|
|
931
|
+
toolCounts: Object.fromEntries(summary.toolCounts),
|
|
932
|
+
transport: summary.transport
|
|
933
|
+
};
|
|
934
|
+
}
|
|
935
|
+
async function flushMcpTelemetrySummary(summary) {
|
|
936
|
+
const body = toMcpTelemetryBody(summary);
|
|
937
|
+
if (!body) return;
|
|
938
|
+
await swallow(
|
|
939
|
+
withTimeout(async () => {
|
|
940
|
+
const apiKey = resolveApiKey();
|
|
941
|
+
await consolePostTelemetry(TELEMETRY_ENDPOINT, body, apiKey);
|
|
942
|
+
}, FLUSH_TIMEOUT_MS)
|
|
943
|
+
);
|
|
944
|
+
}
|
|
945
|
+
function toolResultSucceeded(resultText) {
|
|
946
|
+
if (!resultText) return false;
|
|
947
|
+
try {
|
|
948
|
+
const parsed = JSON.parse(resultText);
|
|
949
|
+
return parsed.success === true;
|
|
950
|
+
} catch {
|
|
951
|
+
return false;
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
async function withTimeout(fn, timeoutMs) {
|
|
955
|
+
let timer;
|
|
956
|
+
await Promise.race([
|
|
957
|
+
fn(),
|
|
958
|
+
new Promise((resolve) => {
|
|
959
|
+
timer = setTimeout(resolve, timeoutMs);
|
|
960
|
+
})
|
|
961
|
+
]);
|
|
962
|
+
if (timer) clearTimeout(timer);
|
|
963
|
+
}
|
|
964
|
+
async function swallow(promise) {
|
|
965
|
+
try {
|
|
966
|
+
await promise;
|
|
967
|
+
} catch {
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
// src/tools/query-collection.ts
|
|
972
|
+
import { z as z3 } from "zod";
|
|
973
|
+
|
|
974
|
+
// src/lib/client.ts
|
|
975
|
+
import { createServerClient } from "@01.software/sdk";
|
|
976
|
+
var MISSING_HTTP_AUTH_CONTEXT_ERROR2 = "MCP HTTP requests require a validated OAuth tenant context before tool execution.";
|
|
977
|
+
var HTTP_OAUTH_SDK_CLIENT_ERROR = "MCP HTTP OAuth requests cannot use SDK-backed tools. Use reviewed Console service endpoints for OAuth transport.";
|
|
978
|
+
function getClient() {
|
|
979
|
+
const oauthContext = tenantAuthContext();
|
|
980
|
+
if (oauthContext) {
|
|
981
|
+
throw new Error(HTTP_OAUTH_SDK_CLIENT_ERROR);
|
|
982
|
+
}
|
|
983
|
+
if (hasRequestContext()) throw new Error(MISSING_HTTP_AUTH_CONTEXT_ERROR2);
|
|
544
984
|
const secretKey = process.env.SOFTWARE_SECRET_KEY;
|
|
545
985
|
const publishableKey = process.env.SOFTWARE_PUBLISHABLE_KEY || process.env.NEXT_PUBLIC_SOFTWARE_PUBLISHABLE_KEY;
|
|
546
986
|
if (!secretKey) {
|
|
@@ -563,15 +1003,18 @@ function getClient() {
|
|
|
563
1003
|
}
|
|
564
1004
|
|
|
565
1005
|
// src/tools/query-collection.ts
|
|
566
|
-
import {
|
|
1006
|
+
import { SERVER_COLLECTIONS } from "@01.software/sdk";
|
|
567
1007
|
var schema = {
|
|
568
|
-
collection:
|
|
569
|
-
where:
|
|
1008
|
+
collection: z3.enum(SERVER_COLLECTIONS).describe("Collection name (required)"),
|
|
1009
|
+
where: z3.string().optional().describe(
|
|
570
1010
|
`Filter conditions (JSON string, optional). Pass the Payload query condition object as a JSON string. Example: '{"title":{"equals":"Product name"}}'`
|
|
571
1011
|
),
|
|
572
|
-
limit:
|
|
573
|
-
page:
|
|
574
|
-
sort:
|
|
1012
|
+
limit: z3.number().min(1).max(100).default(10).describe("Maximum number of items to return (1-100, default: 10)."),
|
|
1013
|
+
page: z3.number().optional().describe("Page number (optional). Starts from 1. Used for pagination."),
|
|
1014
|
+
sort: z3.string().regex(
|
|
1015
|
+
/^-?[a-zA-Z0-9_.]+$/,
|
|
1016
|
+
'Sort must be a field name, optionally prefixed with "-" for descending'
|
|
1017
|
+
).optional().describe(
|
|
575
1018
|
'Sort field (optional). Use "fieldName" for ascending or "-fieldName" for descending. Example: "createdAt" or "-createdAt"'
|
|
576
1019
|
)
|
|
577
1020
|
};
|
|
@@ -625,11 +1068,11 @@ async function queryCollection({
|
|
|
625
1068
|
}
|
|
626
1069
|
|
|
627
1070
|
// src/tools/get-collection-by-id.ts
|
|
628
|
-
import { z as
|
|
629
|
-
import {
|
|
1071
|
+
import { z as z4 } from "zod";
|
|
1072
|
+
import { SERVER_COLLECTIONS as SERVER_COLLECTIONS2 } from "@01.software/sdk";
|
|
630
1073
|
var schema2 = {
|
|
631
|
-
collection:
|
|
632
|
-
id:
|
|
1074
|
+
collection: z4.enum(SERVER_COLLECTIONS2).describe("Collection name (required)"),
|
|
1075
|
+
id: z4.string().min(1).describe("Item ID (required)")
|
|
633
1076
|
};
|
|
634
1077
|
var metadata2 = {
|
|
635
1078
|
name: "get-collection-by-id",
|
|
@@ -655,9 +1098,9 @@ async function getCollectionById({
|
|
|
655
1098
|
}
|
|
656
1099
|
|
|
657
1100
|
// src/tools/get-order.ts
|
|
658
|
-
import { z as
|
|
1101
|
+
import { z as z5 } from "zod";
|
|
659
1102
|
var schema3 = {
|
|
660
|
-
orderNumber:
|
|
1103
|
+
orderNumber: z5.string().min(1).describe("Order number to look up (required)")
|
|
661
1104
|
};
|
|
662
1105
|
var metadata3 = {
|
|
663
1106
|
name: "get-order",
|
|
@@ -687,24 +1130,24 @@ async function getOrder({
|
|
|
687
1130
|
}
|
|
688
1131
|
|
|
689
1132
|
// src/tools/create-order.ts
|
|
690
|
-
import { z as
|
|
1133
|
+
import { z as z6 } from "zod";
|
|
691
1134
|
var schema4 = {
|
|
692
|
-
pgPaymentId:
|
|
693
|
-
orderNumber:
|
|
694
|
-
customerSnapshot:
|
|
695
|
-
name:
|
|
696
|
-
email:
|
|
697
|
-
phone:
|
|
1135
|
+
pgPaymentId: z6.string().optional().describe("PG payment ID (optional \u2014 omit for free orders)"),
|
|
1136
|
+
orderNumber: z6.string().min(1).describe("Unique order number (required)"),
|
|
1137
|
+
customerSnapshot: z6.object({
|
|
1138
|
+
name: z6.string().optional().describe("Customer name"),
|
|
1139
|
+
email: z6.string().describe("Customer email (required)"),
|
|
1140
|
+
phone: z6.string().optional().describe("Customer phone")
|
|
698
1141
|
}).describe("Customer snapshot at time of order (required)"),
|
|
699
|
-
shippingAddress:
|
|
1142
|
+
shippingAddress: z6.record(z6.string(), z6.unknown()).describe(
|
|
700
1143
|
"Shipping address object (required). Fields: postalCode, address1, address2, deliveryMessage, recipientName, phone"
|
|
701
1144
|
),
|
|
702
|
-
orderItems:
|
|
1145
|
+
orderItems: z6.array(z6.record(z6.string(), z6.unknown())).describe(
|
|
703
1146
|
"Array of order item objects (required). Each: { product, variant, option, quantity, unitPrice?, totalPrice? }"
|
|
704
1147
|
),
|
|
705
|
-
totalAmount:
|
|
706
|
-
shippingAmount:
|
|
707
|
-
discountCode:
|
|
1148
|
+
totalAmount: z6.number().nonnegative().describe("Total order amount (required, min 0)"),
|
|
1149
|
+
shippingAmount: z6.number().nonnegative().optional().describe("Shipping amount (optional, default 0)"),
|
|
1150
|
+
discountCode: z6.string().optional().describe("Discount code to apply (optional)")
|
|
708
1151
|
};
|
|
709
1152
|
var metadata4 = {
|
|
710
1153
|
name: "create-order",
|
|
@@ -729,10 +1172,10 @@ async function createOrder(params) {
|
|
|
729
1172
|
}
|
|
730
1173
|
|
|
731
1174
|
// src/tools/update-order.ts
|
|
732
|
-
import { z as
|
|
1175
|
+
import { z as z7 } from "zod";
|
|
733
1176
|
var schema5 = {
|
|
734
|
-
orderNumber:
|
|
735
|
-
status:
|
|
1177
|
+
orderNumber: z7.string().min(1).describe("Order number (required)"),
|
|
1178
|
+
status: z7.enum([
|
|
736
1179
|
"pending",
|
|
737
1180
|
"paid",
|
|
738
1181
|
"failed",
|
|
@@ -769,15 +1212,15 @@ async function updateOrder({
|
|
|
769
1212
|
}
|
|
770
1213
|
|
|
771
1214
|
// src/tools/checkout.ts
|
|
772
|
-
import { z as
|
|
1215
|
+
import { z as z8 } from "zod";
|
|
773
1216
|
var schema6 = {
|
|
774
|
-
cartId:
|
|
775
|
-
pgPaymentId:
|
|
776
|
-
orderNumber:
|
|
777
|
-
customerSnapshot:
|
|
1217
|
+
cartId: z8.string().min(1).describe("Cart ID to convert to order (required)"),
|
|
1218
|
+
pgPaymentId: z8.string().optional().describe("PG payment ID (optional \u2014 omit for free orders)"),
|
|
1219
|
+
orderNumber: z8.string().min(1).describe("Unique order number (required)"),
|
|
1220
|
+
customerSnapshot: z8.record(z8.string(), z8.unknown()).describe(
|
|
778
1221
|
"Customer snapshot object (required). Fields: { name?, email, phone? }"
|
|
779
1222
|
),
|
|
780
|
-
discountCode:
|
|
1223
|
+
discountCode: z8.string().optional().describe("Discount code to apply (optional)")
|
|
781
1224
|
};
|
|
782
1225
|
var metadata6 = {
|
|
783
1226
|
name: "checkout",
|
|
@@ -802,17 +1245,17 @@ async function checkout(params) {
|
|
|
802
1245
|
}
|
|
803
1246
|
|
|
804
1247
|
// src/tools/create-fulfillment.ts
|
|
805
|
-
import { z as
|
|
1248
|
+
import { z as z9 } from "zod";
|
|
806
1249
|
var schema7 = {
|
|
807
|
-
orderNumber:
|
|
808
|
-
carrier:
|
|
809
|
-
trackingNumber:
|
|
1250
|
+
orderNumber: z9.string().min(1).describe("Order number (required)"),
|
|
1251
|
+
carrier: z9.string().optional().describe("Shipping carrier name (optional)"),
|
|
1252
|
+
trackingNumber: z9.string().optional().describe(
|
|
810
1253
|
'Tracking number (optional). Setting carrier + tracking triggers "shipped" status'
|
|
811
1254
|
),
|
|
812
|
-
items:
|
|
813
|
-
|
|
814
|
-
orderItem:
|
|
815
|
-
quantity:
|
|
1255
|
+
items: z9.array(
|
|
1256
|
+
z9.object({
|
|
1257
|
+
orderItem: z9.string().min(1).describe("Order item ID"),
|
|
1258
|
+
quantity: z9.number().int().positive().describe("Quantity to fulfill")
|
|
816
1259
|
})
|
|
817
1260
|
).describe("Array of items to fulfill (required)")
|
|
818
1261
|
};
|
|
@@ -847,16 +1290,16 @@ async function createFulfillment({
|
|
|
847
1290
|
}
|
|
848
1291
|
|
|
849
1292
|
// src/tools/update-fulfillment.ts
|
|
850
|
-
import { z as
|
|
1293
|
+
import { z as z10 } from "zod";
|
|
851
1294
|
var schema8 = {
|
|
852
|
-
fulfillmentId:
|
|
853
|
-
status:
|
|
1295
|
+
fulfillmentId: z10.string().min(1).describe("Fulfillment ID (required)"),
|
|
1296
|
+
status: z10.enum(["packed", "shipped", "delivered", "failed"]).describe(
|
|
854
1297
|
"New fulfillment status (required). FSM: pending\u2192packed/shipped/failed, packed\u2192shipped/failed, shipped\u2192delivered/failed"
|
|
855
1298
|
),
|
|
856
|
-
carrier:
|
|
1299
|
+
carrier: z10.string().optional().describe(
|
|
857
1300
|
"Shipping carrier (optional, changeable only in pending/packed status)"
|
|
858
1301
|
),
|
|
859
|
-
trackingNumber:
|
|
1302
|
+
trackingNumber: z10.string().optional().describe(
|
|
860
1303
|
"Tracking number (optional, changeable only in pending/packed status)"
|
|
861
1304
|
)
|
|
862
1305
|
};
|
|
@@ -890,131 +1333,6 @@ async function updateFulfillment({
|
|
|
890
1333
|
}
|
|
891
1334
|
}
|
|
892
1335
|
|
|
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
1336
|
// src/tools/update-transaction.ts
|
|
1019
1337
|
var schema9 = UpdateTransactionSchema.shape;
|
|
1020
1338
|
var metadata9 = {
|
|
@@ -1452,97 +1770,7 @@ async function stockCheck({
|
|
|
1452
1770
|
}
|
|
1453
1771
|
|
|
1454
1772
|
// src/tools/get-collection-schema.ts
|
|
1455
|
-
import {
|
|
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);
|
|
1523
|
-
}
|
|
1524
|
-
}
|
|
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);
|
|
1529
|
-
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);
|
|
1544
|
-
}
|
|
1545
|
-
}
|
|
1773
|
+
import { SERVER_COLLECTIONS as SERVER_COLLECTIONS3 } from "@01.software/sdk";
|
|
1546
1774
|
|
|
1547
1775
|
// src/lib/collection-schema.ts
|
|
1548
1776
|
async function getCollectionSchema(collection) {
|
|
@@ -1555,7 +1783,7 @@ async function getCollectionSchema(collection) {
|
|
|
1555
1783
|
}
|
|
1556
1784
|
|
|
1557
1785
|
// src/tools/get-collection-schema.ts
|
|
1558
|
-
var schema22 = createCollectionSchemaToolInputSchema(
|
|
1786
|
+
var schema22 = createCollectionSchemaToolInputSchema(SERVER_COLLECTIONS3).shape;
|
|
1559
1787
|
var metadata22 = {
|
|
1560
1788
|
name: "get-collection-schema",
|
|
1561
1789
|
description: "Get the authoritative tenant-aware collection schema from console. Use this before create/update to understand writable fields, hidden fields, required metadata, and collection-level visibility.",
|
|
@@ -2275,7 +2503,7 @@ var docIndex = [
|
|
|
2275
2503
|
{
|
|
2276
2504
|
title: "Browser Client vs Server Client",
|
|
2277
2505
|
keywords: ["browser", "server", "publishable key", "secret key", "createClient", "createServerClient", "NEXT_PUBLIC_SOFTWARE_PUBLISHABLE_KEY", "SOFTWARE_PUBLISHABLE_KEY", "SOFTWARE_SECRET_KEY", "pk01_", "sk01_", "pat01_", "read-only", "full crud"],
|
|
2278
|
-
summary: "createClient() for browser with publishableKey (read-only pk01_), createServerClient() for server with SOFTWARE_SECRET_KEY (usually sk01_, sometimes pat01_ in
|
|
2506
|
+
summary: "createClient() for browser with publishableKey (read-only pk01_), createServerClient() for server with matching SOFTWARE_PUBLISHABLE_KEY + SOFTWARE_SECRET_KEY (usually sk01_, sometimes pat01_ in scoped flows). Never expose SECRET_KEY to the browser.",
|
|
2279
2507
|
resourceUri: "docs://sdk/getting-started"
|
|
2280
2508
|
},
|
|
2281
2509
|
// Query Builder
|
|
@@ -2641,9 +2869,9 @@ function handler4({
|
|
|
2641
2869
|
|
|
2642
2870
|
// src/tools/sdk-get-collection-pattern.ts
|
|
2643
2871
|
import { z as z27 } from "zod";
|
|
2644
|
-
import { COLLECTIONS as
|
|
2872
|
+
import { COLLECTIONS, SERVER_COLLECTIONS as SERVER_COLLECTIONS4 } from "@01.software/sdk";
|
|
2645
2873
|
var schema29 = {
|
|
2646
|
-
collection: z27.enum(
|
|
2874
|
+
collection: z27.enum(SERVER_COLLECTIONS4).describe("Collection name"),
|
|
2647
2875
|
operation: z27.enum(["read", "write", "full-crud"]).default("read").describe("What operations are needed"),
|
|
2648
2876
|
surface: z27.enum(["query-builder", "react-query", "server-api"]).default("query-builder").describe("Preferred API surface")
|
|
2649
2877
|
};
|
|
@@ -2658,7 +2886,15 @@ var metadata29 = {
|
|
|
2658
2886
|
}
|
|
2659
2887
|
};
|
|
2660
2888
|
function generatePattern(collection, operation, surface) {
|
|
2889
|
+
const isPublicCollection = COLLECTIONS.includes(
|
|
2890
|
+
collection
|
|
2891
|
+
);
|
|
2661
2892
|
if (surface === "react-query") {
|
|
2893
|
+
if (!isPublicCollection) {
|
|
2894
|
+
throw new Error(
|
|
2895
|
+
`${collection} is server-only. Use surface="server-api" with createServerClient().`
|
|
2896
|
+
);
|
|
2897
|
+
}
|
|
2662
2898
|
const parts2 = [];
|
|
2663
2899
|
if (operation === "read") {
|
|
2664
2900
|
parts2.push(
|
|
@@ -2770,17 +3006,29 @@ function generatePattern(collection, operation, surface) {
|
|
|
2770
3006
|
}
|
|
2771
3007
|
const parts = [];
|
|
2772
3008
|
if (operation === "read" || operation === "full-crud") {
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
3009
|
+
if (isPublicCollection) {
|
|
3010
|
+
parts.push(
|
|
3011
|
+
`// Read with any client (Client or ServerClient)`,
|
|
3012
|
+
`const result = await client.collections.from('${collection}').find({`,
|
|
3013
|
+
` where: { status: { equals: 'published' } },`,
|
|
3014
|
+
` limit: 10,`,
|
|
3015
|
+
` sort: '-createdAt'`,
|
|
3016
|
+
`})`,
|
|
3017
|
+
``,
|
|
3018
|
+
`const item = await client.collections.from('${collection}').findById(id)`,
|
|
3019
|
+
`const { totalDocs } = await client.collections.from('${collection}').count()`
|
|
3020
|
+
);
|
|
3021
|
+
} else {
|
|
3022
|
+
parts.push(
|
|
3023
|
+
`// Server-only collection: use ServerClient`,
|
|
3024
|
+
`const result = await serverClient.collections.from('${collection}').find({`,
|
|
3025
|
+
` limit: 10,`,
|
|
3026
|
+
` sort: '-createdAt'`,
|
|
3027
|
+
`})`,
|
|
3028
|
+
``,
|
|
3029
|
+
`const item = await serverClient.collections.from('${collection}').findById(id)`
|
|
3030
|
+
);
|
|
3031
|
+
}
|
|
2784
3032
|
}
|
|
2785
3033
|
if (operation === "write" || operation === "full-crud") {
|
|
2786
3034
|
parts.push(
|
|
@@ -2795,6 +3043,7 @@ function generatePattern(collection, operation, surface) {
|
|
|
2795
3043
|
code: parts.join("\n"),
|
|
2796
3044
|
notes: [
|
|
2797
3045
|
"Query Builder works with both Client and ServerClient for reads",
|
|
3046
|
+
!isPublicCollection ? "This collection is server-only" : "",
|
|
2798
3047
|
operation !== "read" ? "Write operations require ServerClient" : ""
|
|
2799
3048
|
].filter(Boolean)
|
|
2800
3049
|
};
|
|
@@ -2972,9 +3221,9 @@ You can perform the "${goal}" task by following the patterns above.`;
|
|
|
2972
3221
|
|
|
2973
3222
|
// src/prompts/collection-query-help.ts
|
|
2974
3223
|
import { z as z29 } from "zod";
|
|
2975
|
-
import { COLLECTIONS as
|
|
3224
|
+
import { COLLECTIONS as COLLECTIONS2, SERVER_COLLECTIONS as SERVER_COLLECTIONS5 } from "@01.software/sdk";
|
|
2976
3225
|
var schema31 = {
|
|
2977
|
-
collection: z29.enum(
|
|
3226
|
+
collection: z29.enum(SERVER_COLLECTIONS5).describe("Collection name"),
|
|
2978
3227
|
operation: z29.enum(["find", "create", "update", "delete"]).describe("Operation to perform (find, create, update, delete)"),
|
|
2979
3228
|
filters: z29.string().optional().describe("Filter conditions (JSON string, optional)")
|
|
2980
3229
|
};
|
|
@@ -2995,6 +3244,11 @@ Filter conditions:
|
|
|
2995
3244
|
\`\`\`json
|
|
2996
3245
|
${filters}
|
|
2997
3246
|
\`\`\`` : "";
|
|
3247
|
+
const isPublicCollection = COLLECTIONS2.includes(
|
|
3248
|
+
collection
|
|
3249
|
+
);
|
|
3250
|
+
const readClientName = isPublicCollection ? "client" : "serverClient";
|
|
3251
|
+
const readClientNote = isPublicCollection ? "Client or ServerClient" : "ServerClient only";
|
|
2998
3252
|
return `How to perform "${operation}" operation on "${collection}" collection:${filterExample}
|
|
2999
3253
|
|
|
3000
3254
|
## Collection: ${collection}
|
|
@@ -3005,26 +3259,26 @@ ${filters}
|
|
|
3005
3259
|
\`\`\`typescript
|
|
3006
3260
|
import { createClient, createServerClient } from '@01.software/sdk'
|
|
3007
3261
|
|
|
3008
|
-
// Client (read-only)
|
|
3262
|
+
// Client (read-only public collections)
|
|
3009
3263
|
const client = createClient({
|
|
3010
3264
|
publishableKey: process.env.NEXT_PUBLIC_SOFTWARE_PUBLISHABLE_KEY!
|
|
3011
3265
|
})
|
|
3012
3266
|
|
|
3013
|
-
// Server client (full CRUD)
|
|
3267
|
+
// Server client (server/public collections, full CRUD)
|
|
3014
3268
|
const serverClient = createServerClient({
|
|
3015
3269
|
publishableKey: process.env.SOFTWARE_PUBLISHABLE_KEY!,
|
|
3016
3270
|
secretKey: process.env.SOFTWARE_SECRET_KEY!
|
|
3017
3271
|
})
|
|
3018
3272
|
|
|
3019
|
-
${operation === "find" ? `// Query ${collection} collection with Query Builder
|
|
3273
|
+
${operation === "find" ? `// Query ${collection} collection with Query Builder (${readClientNote})
|
|
3020
3274
|
// find() returns PayloadFindResponse with docs array and pagination
|
|
3021
|
-
const result = await
|
|
3275
|
+
const result = await ${readClientName}.collections.from('${collection}').find(${filters ? `{
|
|
3022
3276
|
where: ${filters}
|
|
3023
3277
|
}` : ""})
|
|
3024
3278
|
// result.docs - array of items
|
|
3025
3279
|
// result.totalDocs, result.page, result.totalPages, result.hasNextPage, ...
|
|
3026
3280
|
|
|
3027
|
-
|
|
3281
|
+
${isPublicCollection ? `// Using React Hook
|
|
3028
3282
|
const { data, isLoading, error } = client.query.useQuery({
|
|
3029
3283
|
collection: '${collection}',
|
|
3030
3284
|
options: { limit: 10 }
|
|
@@ -3034,19 +3288,19 @@ const { data, isLoading, error } = client.query.useQuery({
|
|
|
3034
3288
|
const { data } = client.query.useSuspenseQuery({
|
|
3035
3289
|
collection: '${collection}',
|
|
3036
3290
|
options: { limit: 10 }
|
|
3037
|
-
})` : operation === "create" ? `// Create ${collection} item (ServerClient only)
|
|
3291
|
+
})` : `// React hooks are browser/public only and do not support '${collection}'.`}` : operation === "create" ? `// Create ${collection} item (ServerClient only)
|
|
3038
3292
|
// create() returns PayloadMutationResponse with doc and message
|
|
3039
|
-
const result = await serverClient.from('${collection}').create({
|
|
3293
|
+
const result = await serverClient.collections.from('${collection}').create({
|
|
3040
3294
|
// Enter fields
|
|
3041
3295
|
})
|
|
3042
3296
|
// result.doc - created item, result.message` : operation === "update" ? `// Update ${collection} item (ServerClient only)
|
|
3043
3297
|
// update() returns PayloadMutationResponse with doc and message
|
|
3044
|
-
const result = await serverClient.from('${collection}').update(id, {
|
|
3298
|
+
const result = await serverClient.collections.from('${collection}').update(id, {
|
|
3045
3299
|
// Fields to update
|
|
3046
3300
|
})
|
|
3047
3301
|
// result.doc - updated item, result.message` : `// Delete ${collection} item (ServerClient only)
|
|
3048
3302
|
// remove() returns the deleted document directly
|
|
3049
|
-
await serverClient.from('${collection}').remove(id)`}
|
|
3303
|
+
await serverClient.collections.from('${collection}').remove(id)`}
|
|
3050
3304
|
\`\`\`
|
|
3051
3305
|
|
|
3052
3306
|
### Useful Tips
|
|
@@ -3054,7 +3308,7 @@ await serverClient.from('${collection}').remove(id)`}
|
|
|
3054
3308
|
${operation === "find" ? `- Use \`where\` option for filtering (Payload query syntax)
|
|
3055
3309
|
- Use \`limit\` and \`page\` for pagination
|
|
3056
3310
|
- Use \`sort\` for sorting (prefix with "-" for descending)
|
|
3057
|
-
- React Query hooks: useQuery, useSuspenseQuery, useInfiniteQuery
|
|
3311
|
+
- ${isPublicCollection ? "React Query hooks: useQuery, useSuspenseQuery, useInfiniteQuery" : "React Query hooks are browser/public only; use ServerClient for this collection"}
|
|
3058
3312
|
- Cache utilities: invalidateQueries, prefetchQuery, getQueryData, setQueryData` : operation === "create" ? `- Requires ServerClient with secretKey
|
|
3059
3313
|
- Check required fields
|
|
3060
3314
|
- TypeScript recommended for type safety` : operation === "update" ? `- Requires ServerClient with secretKey
|
|
@@ -3290,7 +3544,7 @@ var FEATURES = {
|
|
|
3290
3544
|
### Required Collections (count > 0)
|
|
3291
3545
|
|
|
3292
3546
|
1. **products** \u2014 Create via Console UI or SDK \`client.collections.from('products').create({ ... })\`
|
|
3293
|
-
- Minimum fields: \`{ title, slug, status: 'published'
|
|
3547
|
+
- Minimum fields: \`{ title, slug, status: 'published' }\`
|
|
3294
3548
|
|
|
3295
3549
|
2. **product-variants** \u2014 At least 1 sellable variant per product
|
|
3296
3550
|
- Minimum fields: \`{ product, title, price, stock }\`
|
|
@@ -3323,7 +3577,8 @@ customer-addresses
|
|
|
3323
3577
|
|
|
3324
3578
|
### Optional Collections
|
|
3325
3579
|
|
|
3326
|
-
customer-groups \u2014
|
|
3580
|
+
- customer-groups \u2014 Console/server-scoped segmentation for VIP coupons and campaigns. Use \`createServerClient().collections.from('customer-groups')\`.
|
|
3581
|
+
- customer-profile-lists \u2014 Public profile display/ranking lists for storefronts. Browser reads may use \`client.collections.from('customer-profile-lists')\`.
|
|
3327
3582
|
|
|
3328
3583
|
### Config
|
|
3329
3584
|
|
|
@@ -3334,10 +3589,10 @@ customer-groups \u2014 Create via Console UI or SDK \`client.collections.from('c
|
|
|
3334
3589
|
### Required Collections (count > 0)
|
|
3335
3590
|
|
|
3336
3591
|
1. **articles** \u2014 At least 1 article
|
|
3337
|
-
- Minimum fields: \`{ title, slug }\`
|
|
3592
|
+
- Minimum fields: \`{ title, slug, status: 'published' }\`
|
|
3338
3593
|
|
|
3339
3594
|
2. **article-authors** \u2014 At least 1 author
|
|
3340
|
-
- Minimum fields: \`{ title, slug }\`
|
|
3595
|
+
- Minimum fields: \`{ title, slug, status: 'published' }\`
|
|
3341
3596
|
- Link authors to articles via the \`authors\` relationship field
|
|
3342
3597
|
|
|
3343
3598
|
### Optional Collections
|
|
@@ -3352,7 +3607,7 @@ article-categories, article-tags`,
|
|
|
3352
3607
|
|
|
3353
3608
|
2. **document-types** \u2014 At least 1 type
|
|
3354
3609
|
- Minimum fields: \`{ title, slug }\`
|
|
3355
|
-
- Link document type via \`
|
|
3610
|
+
- Link document type via \`type\` relationship field
|
|
3356
3611
|
|
|
3357
3612
|
### Optional Collections
|
|
3358
3613
|
|
|
@@ -3362,10 +3617,10 @@ document-categories`,
|
|
|
3362
3617
|
### Required Collections (count > 0)
|
|
3363
3618
|
|
|
3364
3619
|
1. **playlists** \u2014 At least 1 playlist
|
|
3365
|
-
- Minimum fields: \`{ title, slug, status: 'published'
|
|
3620
|
+
- Minimum fields: \`{ title, slug, status: 'published' }\`
|
|
3366
3621
|
|
|
3367
3622
|
2. **tracks** \u2014 At least 1 track
|
|
3368
|
-
- Minimum fields: \`{ title, sourceUrl, status: 'published'
|
|
3623
|
+
- Minimum fields: \`{ title, sourceUrl, status: 'published' }\`
|
|
3369
3624
|
|
|
3370
3625
|
3. **playlists.tracks** \u2014 Link at least 1 track from a playlist
|
|
3371
3626
|
- Minimum fields: \`{ tracks: [trackId] }\`
|
|
@@ -3378,11 +3633,11 @@ playlist-categories, playlist-tags, track-categories, track-tags, track-assets`,
|
|
|
3378
3633
|
### Required Collections (count > 0)
|
|
3379
3634
|
|
|
3380
3635
|
1. **galleries** \u2014 At least 1 gallery
|
|
3381
|
-
- Minimum fields: \`{ title, slug, status: 'published'
|
|
3636
|
+
- Minimum fields: \`{ title, slug, status: 'published' }\`
|
|
3382
3637
|
|
|
3383
3638
|
2. **gallery-items** \u2014 At least 1 item per gallery
|
|
3384
3639
|
- References \`images\` collection (non-upload)
|
|
3385
|
-
- Minimum fields: \`{ gallery, image,
|
|
3640
|
+
- Minimum fields: \`{ gallery, image, status: 'published' }\`
|
|
3386
3641
|
|
|
3387
3642
|
### Optional Collections
|
|
3388
3643
|
|
|
@@ -3392,7 +3647,7 @@ gallery-categories, gallery-tags`,
|
|
|
3392
3647
|
### Required Collections (count > 0)
|
|
3393
3648
|
|
|
3394
3649
|
1. **links** \u2014 At least 1 link
|
|
3395
|
-
- Minimum fields: \`{ title, slug, url, status: 'published'
|
|
3650
|
+
- Minimum fields: \`{ title, slug, url, status: 'published' }\`
|
|
3396
3651
|
|
|
3397
3652
|
### Optional Collections
|
|
3398
3653
|
|
|
@@ -3464,9 +3719,11 @@ comments, reactions, bookmarks, reports, community-bans
|
|
|
3464
3719
|
|
|
3465
3720
|
### Optional Collections
|
|
3466
3721
|
|
|
3467
|
-
post-categories`
|
|
3722
|
+
post-categories, customer-profile-lists`
|
|
3468
3723
|
};
|
|
3469
|
-
function featureSetupGuide({
|
|
3724
|
+
function featureSetupGuide({
|
|
3725
|
+
feature
|
|
3726
|
+
}) {
|
|
3470
3727
|
return `# Feature Setup Guide: ${feature}
|
|
3471
3728
|
|
|
3472
3729
|
${FEATURES[feature] || "Unknown feature."}
|
|
@@ -3489,7 +3746,8 @@ function handler6() {
|
|
|
3489
3746
|
## Server Info
|
|
3490
3747
|
- **Name**: 01.software MCP Server
|
|
3491
3748
|
- **Version**: 0.1.0
|
|
3492
|
-
- **
|
|
3749
|
+
- **Hosted transport**: HTTP (Streamable)
|
|
3750
|
+
- **Local transport**: stdio through \`npx @01.software/cli mcp\`
|
|
3493
3751
|
|
|
3494
3752
|
## Authentication
|
|
3495
3753
|
|
|
@@ -3500,42 +3758,9 @@ HTTP MCP uses OAuth discovery and Authorization Code + PKCE.
|
|
|
3500
3758
|
url = "https://mcp.01.software/mcp"
|
|
3501
3759
|
\`\`\`
|
|
3502
3760
|
|
|
3503
|
-
##
|
|
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
|
|
3761
|
+
## Hosted HTTP OAuth Tools (8)
|
|
3510
3762
|
|
|
3511
|
-
|
|
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
|
|
3524
|
-
|
|
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
|
|
3763
|
+
The hosted HTTP MCP endpoint at https://mcp.01.software/mcp exposes only these OAuth-safe tools:
|
|
3539
3764
|
|
|
3540
3765
|
### Schema (1)
|
|
3541
3766
|
- \`get-collection-schema\` - Get authoritative tenant-aware collection schema
|
|
@@ -3553,6 +3778,16 @@ url = "https://mcp.01.software/mcp"
|
|
|
3553
3778
|
- \`sdk-get-auth-setup\` - Get framework-specific auth setup guidance
|
|
3554
3779
|
- \`sdk-get-collection-pattern\` - Get collection-specific usage patterns
|
|
3555
3780
|
|
|
3781
|
+
## Local CLI Stdio Surface (29)
|
|
3782
|
+
|
|
3783
|
+
For trusted local server-key workflows, start the stdio server:
|
|
3784
|
+
|
|
3785
|
+
\`\`\`bash
|
|
3786
|
+
npx @01.software/cli mcp
|
|
3787
|
+
\`\`\`
|
|
3788
|
+
|
|
3789
|
+
Local stdio can expose generic read, order, return, cart, validation, stock, schema, tenant context, field config, and guidance tools. Generic collection write tools (create/update/delete/update-many/delete-many) are intentionally absent on every transport; use the SDK server client for generic writes.
|
|
3790
|
+
|
|
3556
3791
|
## Rate Limits
|
|
3557
3792
|
|
|
3558
3793
|
Rate limits depend on your tenant plan:
|
|
@@ -3564,7 +3799,7 @@ Rate limits depend on your tenant plan:
|
|
|
3564
3799
|
}
|
|
3565
3800
|
|
|
3566
3801
|
// src/resources/(collections)/schema.ts
|
|
3567
|
-
import { COLLECTIONS as
|
|
3802
|
+
import { COLLECTIONS as COLLECTIONS3 } from "@01.software/sdk";
|
|
3568
3803
|
var metadata35 = {
|
|
3569
3804
|
name: "collections-schema",
|
|
3570
3805
|
title: "Collection Schema Info",
|
|
@@ -3593,13 +3828,18 @@ var COLLECTIONS_BY_CATEGORY = {
|
|
|
3593
3828
|
Customers: [
|
|
3594
3829
|
"customers",
|
|
3595
3830
|
"customer-profiles",
|
|
3596
|
-
"customer-
|
|
3597
|
-
"customer-
|
|
3831
|
+
"customer-profile-lists",
|
|
3832
|
+
"customer-addresses"
|
|
3598
3833
|
],
|
|
3599
3834
|
Carts: ["carts", "cart-items"],
|
|
3600
3835
|
"Discounts & Promotions": ["discounts", "promotions"],
|
|
3601
3836
|
Documents: ["documents", "document-categories", "document-types"],
|
|
3602
|
-
Articles: [
|
|
3837
|
+
Articles: [
|
|
3838
|
+
"articles",
|
|
3839
|
+
"article-authors",
|
|
3840
|
+
"article-categories",
|
|
3841
|
+
"article-tags"
|
|
3842
|
+
],
|
|
3603
3843
|
Community: [
|
|
3604
3844
|
"posts",
|
|
3605
3845
|
"comments",
|
|
@@ -3618,7 +3858,12 @@ var COLLECTIONS_BY_CATEGORY = {
|
|
|
3618
3858
|
"track-categories",
|
|
3619
3859
|
"track-tags"
|
|
3620
3860
|
],
|
|
3621
|
-
Galleries: [
|
|
3861
|
+
Galleries: [
|
|
3862
|
+
"galleries",
|
|
3863
|
+
"gallery-items",
|
|
3864
|
+
"gallery-categories",
|
|
3865
|
+
"gallery-tags"
|
|
3866
|
+
],
|
|
3622
3867
|
Links: ["links", "link-categories", "link-tags"],
|
|
3623
3868
|
Canvas: [
|
|
3624
3869
|
"canvases",
|
|
@@ -3643,7 +3888,7 @@ var COLLECTIONS_BY_CATEGORY = {
|
|
|
3643
3888
|
};
|
|
3644
3889
|
function handler7() {
|
|
3645
3890
|
const categoryDocs = Object.entries(COLLECTIONS_BY_CATEGORY).map(([category, collections]) => {
|
|
3646
|
-
const collectionList = collections.filter((c) =>
|
|
3891
|
+
const collectionList = collections.filter((c) => COLLECTIONS3.includes(c)).map((c) => `- **${c}**`).join("\n");
|
|
3647
3892
|
return `## ${category}
|
|
3648
3893
|
${collectionList}`;
|
|
3649
3894
|
}).join("\n\n");
|
|
@@ -3664,8 +3909,9 @@ Each collection supports the following operations:
|
|
|
3664
3909
|
- \`updateMany(where, data)\` - Bulk update items matching filter
|
|
3665
3910
|
- \`removeMany(where)\` - Bulk delete items matching filter
|
|
3666
3911
|
|
|
3667
|
-
|
|
3668
|
-
publishable-key reads unless server-side access explicitly includes
|
|
3912
|
+
Status-managed public collections expose only \`status: 'published'\` rows to
|
|
3913
|
+
publishable-key reads unless server-side access explicitly includes
|
|
3914
|
+
unpublished statuses.
|
|
3669
3915
|
|
|
3670
3916
|
## Query Examples
|
|
3671
3917
|
|
|
@@ -3688,7 +3934,7 @@ publishable-key reads unless server-side access explicitly includes drafts.
|
|
|
3688
3934
|
}
|
|
3689
3935
|
\`\`\`
|
|
3690
3936
|
|
|
3691
|
-
Total available collections: ${
|
|
3937
|
+
Total available collections: ${COLLECTIONS3.length}`;
|
|
3692
3938
|
}
|
|
3693
3939
|
|
|
3694
3940
|
// src/resources/(docs)/getting-started.ts
|
|
@@ -5576,8 +5822,25 @@ function registerTool(server, schema34, meta, handler19) {
|
|
|
5576
5822
|
};
|
|
5577
5823
|
}
|
|
5578
5824
|
}
|
|
5579
|
-
const
|
|
5580
|
-
|
|
5825
|
+
const activeSummary = currentMcpTelemetrySummary();
|
|
5826
|
+
const ownSummary = activeSummary || hasRequestContext() ? null : createMcpTelemetrySummary("stdio");
|
|
5827
|
+
const summary = activeSummary ?? ownSummary;
|
|
5828
|
+
let result = null;
|
|
5829
|
+
try {
|
|
5830
|
+
result = await handler19(params);
|
|
5831
|
+
return { content: [{ type: "text", text: result }] };
|
|
5832
|
+
} finally {
|
|
5833
|
+
if (summary) {
|
|
5834
|
+
recordMcpToolResult({
|
|
5835
|
+
resultText: result,
|
|
5836
|
+
summary,
|
|
5837
|
+
toolName: meta.name
|
|
5838
|
+
});
|
|
5839
|
+
}
|
|
5840
|
+
if (ownSummary) {
|
|
5841
|
+
void flushMcpTelemetrySummary(ownSummary);
|
|
5842
|
+
}
|
|
5843
|
+
}
|
|
5581
5844
|
}
|
|
5582
5845
|
);
|
|
5583
5846
|
}
|
|
@@ -5970,9 +6233,9 @@ Resources (12): config, collections-schema, getting-started, guides, api, query-
|
|
|
5970
6233
|
Links
|
|
5971
6234
|
-----
|
|
5972
6235
|
|
|
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
|
|
6236
|
+
Docs https://docs.01.software/docs/developers/integrations/mcp
|
|
6237
|
+
SDK https://docs.01.software/docs/developers/sdk/client
|
|
6238
|
+
API Reference https://docs.01.software/docs/developers/api/rest-api
|
|
5976
6239
|
Console https://console.01.software
|
|
5977
6240
|
`;
|
|
5978
6241
|
var PROTECTED_RESOURCE_METADATA = JSON.stringify({
|
|
@@ -5980,14 +6243,23 @@ var PROTECTED_RESOURCE_METADATA = JSON.stringify({
|
|
|
5980
6243
|
authorization_servers: [MCP_OAUTH_ISSUER],
|
|
5981
6244
|
scopes_supported: [MCP_SCOPES.read, MCP_SCOPES.write]
|
|
5982
6245
|
});
|
|
6246
|
+
var PROTECTED_RESOURCE_METADATA_URL = new URL(
|
|
6247
|
+
MCP_PROTECTED_RESOURCE_METADATA_PATH,
|
|
6248
|
+
MCP_RESOURCE_AUDIENCE
|
|
6249
|
+
).toString();
|
|
5983
6250
|
var SERVICE_JWKS_PATH = "/.well-known/service-jwks.json";
|
|
5984
6251
|
function writeOAuthError(res, status, error, description) {
|
|
5985
6252
|
res.writeHead(status, {
|
|
5986
6253
|
"Content-Type": "application/json",
|
|
5987
|
-
"WWW-Authenticate": `Bearer resource_metadata="${
|
|
6254
|
+
"WWW-Authenticate": `Bearer resource_metadata="${PROTECTED_RESOURCE_METADATA_URL}", error="${error}", error_description="${description}"`
|
|
5988
6255
|
});
|
|
5989
6256
|
res.end(JSON.stringify({ error, error_description: description }));
|
|
5990
6257
|
}
|
|
6258
|
+
function acceptsEventStream(req) {
|
|
6259
|
+
const accept = getHeaderValue(req.headers, "accept");
|
|
6260
|
+
if (!accept) return false;
|
|
6261
|
+
return accept.split(",").some((entry) => entry.trim().split(";")[0]?.toLowerCase() === "text/event-stream");
|
|
6262
|
+
}
|
|
5991
6263
|
async function handler18(req, res) {
|
|
5992
6264
|
setCors(res);
|
|
5993
6265
|
if (req.method === "OPTIONS") {
|
|
@@ -6020,6 +6292,11 @@ async function handler18(req, res) {
|
|
|
6020
6292
|
}
|
|
6021
6293
|
return;
|
|
6022
6294
|
}
|
|
6295
|
+
if (acceptsEventStream(req)) {
|
|
6296
|
+
res.writeHead(405, { "Content-Type": "application/json" });
|
|
6297
|
+
res.end(METHOD_NOT_ALLOWED);
|
|
6298
|
+
return;
|
|
6299
|
+
}
|
|
6023
6300
|
res.writeHead(200, { "Content-Type": "text/plain; charset=utf-8" });
|
|
6024
6301
|
res.end(HOME_PAGE);
|
|
6025
6302
|
return;
|
|
@@ -6056,14 +6333,19 @@ async function handler18(req, res) {
|
|
|
6056
6333
|
if (typeof value === "string") headers.set(key, value);
|
|
6057
6334
|
else if (Array.isArray(value)) headers.set(key, value.join(", "));
|
|
6058
6335
|
}
|
|
6336
|
+
const telemetrySummary = createMcpTelemetrySummary("http");
|
|
6059
6337
|
await requestContext.run({ headers, auth: auth.context }, async () => {
|
|
6060
6338
|
try {
|
|
6061
|
-
|
|
6062
|
-
|
|
6339
|
+
await runWithMcpTelemetry(telemetrySummary, async () => {
|
|
6340
|
+
const body = req.body ?? JSON.parse(await readBody(req));
|
|
6341
|
+
await transport.handleRequest(req, res, body);
|
|
6342
|
+
});
|
|
6063
6343
|
} catch (err) {
|
|
6064
6344
|
writeRequestError(res, err);
|
|
6065
6345
|
} finally {
|
|
6346
|
+
telemetrySummary.durationMs = Date.now() - telemetrySummary.startedAtMs;
|
|
6066
6347
|
await close();
|
|
6348
|
+
await flushMcpTelemetrySummary(telemetrySummary);
|
|
6067
6349
|
}
|
|
6068
6350
|
});
|
|
6069
6351
|
}
|