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