@lumibase/mcp-server 0.12.0 → 0.14.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.
Files changed (3) hide show
  1. package/dist/index.cjs +464 -442
  2. package/dist/index.js +464 -442
  3. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -110,10 +110,10 @@ function configFromEnv() {
110
110
  }
111
111
 
112
112
  // src/tools/access.ts
113
- var import_zod2 = require("zod");
113
+ var import_zod3 = require("zod");
114
114
 
115
115
  // src/tools/_crud.ts
116
- var import_zod = require("zod");
116
+ var import_zod2 = require("zod");
117
117
 
118
118
  // src/tools/_shared.ts
119
119
  function formatError(err) {
@@ -155,6 +155,20 @@ async function run(fn) {
155
155
  }
156
156
  var confirmDescription = "Must be true to confirm the destructive operation";
157
157
 
158
+ // src/tools/path.ts
159
+ var import_zod = require("zod");
160
+ var namePattern = /^[a-z][a-z0-9_]{0,62}$/;
161
+ var collectionNameSchema = import_zod.z.string().min(1).max(63).regex(namePattern, "Must be lowercase, start with a letter, only a-z0-9_");
162
+ var fieldNameSchema = import_zod.z.string().min(1).max(63).regex(namePattern, "Must be lowercase snake_case, start with a letter");
163
+ var idPathSegmentSchema = import_zod.z.string().min(1).refine((value) => value !== "." && value !== "..", "Must not be . or ..").refine((value) => !/[\\/]/.test(value), "Must not contain path separators");
164
+ function encodePathSegment(segment) {
165
+ return encodeURIComponent(segment);
166
+ }
167
+ var mediaKeySchema = import_zod.z.string().min(1).refine((value) => !value.includes(".."), 'Must not contain ".."').refine((value) => !value.startsWith("/"), 'Must not start with "/"').refine((value) => !value.includes("\\"), "Must not contain backslashes");
168
+ function encodeMediaKey(key) {
169
+ return key.split("/").map((segment) => encodeURIComponent(segment)).join("/");
170
+ }
171
+
158
172
  // src/tools/_crud.ts
159
173
  function registerCrud(server, client, opts) {
160
174
  const {
@@ -185,9 +199,9 @@ function registerCrud(server, client, opts) {
185
199
  `get_${namePrefix}`,
186
200
  {
187
201
  description: `Get a single ${resource} by ${idParam}.`,
188
- inputSchema: { [idParam]: import_zod.z.string().min(1) }
202
+ inputSchema: { [idParam]: idPathSegmentSchema }
189
203
  },
190
- async (args) => run(() => client.get(`${basePath}/${String(args[idParam])}`))
204
+ async (args) => run(() => client.get(`${basePath}/${encodePathSegment(String(args[idParam]))}`))
191
205
  );
192
206
  }
193
207
  if (createSchema) {
@@ -205,11 +219,11 @@ function registerCrud(server, client, opts) {
205
219
  `update_${namePrefix}`,
206
220
  {
207
221
  description: `Update an existing ${resource} (partial PATCH).`,
208
- inputSchema: { [idParam]: import_zod.z.string().min(1), ...updateSchema }
222
+ inputSchema: { [idParam]: idPathSegmentSchema, ...updateSchema }
209
223
  },
210
224
  async (args) => {
211
225
  const { [idParam]: id, ...patch } = args;
212
- return run(() => client.patch(`${basePath}/${String(id)}`, patch));
226
+ return run(() => client.patch(`${basePath}/${encodePathSegment(String(id))}`, patch));
213
227
  }
214
228
  );
215
229
  }
@@ -219,14 +233,14 @@ function registerCrud(server, client, opts) {
219
233
  {
220
234
  description: `Delete a ${resource}. DESTRUCTIVE \u2014 warn the user first and pass confirm=true.`,
221
235
  inputSchema: {
222
- [idParam]: import_zod.z.string().min(1),
223
- confirm: import_zod.z.literal(true).describe(confirmDescription)
236
+ [idParam]: idPathSegmentSchema,
237
+ confirm: import_zod2.z.literal(true).describe(confirmDescription)
224
238
  }
225
239
  },
226
240
  async (args) => {
227
241
  const id = String(args[idParam]);
228
242
  return run(async () => {
229
- await client.delete(`${basePath}/${id}`);
243
+ await client.delete(`${basePath}/${encodePathSegment(id)}`);
230
244
  return okText(`${resource} "${id}" deleted.`);
231
245
  });
232
246
  }
@@ -235,37 +249,37 @@ function registerCrud(server, client, opts) {
235
249
  }
236
250
 
237
251
  // src/tools/access.ts
238
- var roleSchema = import_zod2.z.object({
239
- key: import_zod2.z.string().min(1).max(96).optional(),
240
- systemKey: import_zod2.z.string().min(1).max(96).optional(),
241
- name: import_zod2.z.string().min(1).max(64),
242
- description: import_zod2.z.string().max(512).optional(),
243
- icon: import_zod2.z.string().max(64).optional(),
244
- parentId: import_zod2.z.string().nullable().optional(),
245
- adminAccess: import_zod2.z.boolean().optional(),
246
- appAccess: import_zod2.z.boolean().optional()
252
+ var roleSchema = import_zod3.z.object({
253
+ key: import_zod3.z.string().min(1).max(96).optional(),
254
+ systemKey: import_zod3.z.string().min(1).max(96).optional(),
255
+ name: import_zod3.z.string().min(1).max(64),
256
+ description: import_zod3.z.string().max(512).optional(),
257
+ icon: import_zod3.z.string().max(64).optional(),
258
+ parentId: import_zod3.z.string().nullable().optional(),
259
+ adminAccess: import_zod3.z.boolean().optional(),
260
+ appAccess: import_zod3.z.boolean().optional()
247
261
  });
248
- var policySchema = import_zod2.z.object({
249
- key: import_zod2.z.string().min(1).max(96).optional(),
250
- name: import_zod2.z.string().min(1).max(64),
251
- icon: import_zod2.z.string().max(64).optional(),
252
- description: import_zod2.z.string().max(512).optional(),
253
- adminAccess: import_zod2.z.boolean().optional(),
254
- appAccess: import_zod2.z.boolean().optional(),
255
- enforceTfa: import_zod2.z.boolean().optional(),
256
- ipAllow: import_zod2.z.array(import_zod2.z.string()).optional(),
257
- ipDeny: import_zod2.z.array(import_zod2.z.string()).optional(),
258
- validFrom: import_zod2.z.string().datetime().nullable().optional(),
259
- validUntil: import_zod2.z.string().datetime().nullable().optional(),
260
- rules: import_zod2.z.record(import_zod2.z.unknown()).optional()
262
+ var policySchema = import_zod3.z.object({
263
+ key: import_zod3.z.string().min(1).max(96).optional(),
264
+ name: import_zod3.z.string().min(1).max(64),
265
+ icon: import_zod3.z.string().max(64).optional(),
266
+ description: import_zod3.z.string().max(512).optional(),
267
+ adminAccess: import_zod3.z.boolean().optional(),
268
+ appAccess: import_zod3.z.boolean().optional(),
269
+ enforceTfa: import_zod3.z.boolean().optional(),
270
+ ipAllow: import_zod3.z.array(import_zod3.z.string()).optional(),
271
+ ipDeny: import_zod3.z.array(import_zod3.z.string()).optional(),
272
+ validFrom: import_zod3.z.string().datetime().nullable().optional(),
273
+ validUntil: import_zod3.z.string().datetime().nullable().optional(),
274
+ rules: import_zod3.z.record(import_zod3.z.unknown()).optional()
261
275
  });
262
- var permissionSchema = import_zod2.z.object({
263
- collection: import_zod2.z.string().min(1).max(64),
264
- action: import_zod2.z.enum(["create", "read", "update", "delete", "share"]),
265
- permissions: import_zod2.z.record(import_zod2.z.unknown()).optional(),
266
- validation: import_zod2.z.record(import_zod2.z.unknown()).optional(),
267
- presets: import_zod2.z.record(import_zod2.z.unknown()).optional(),
268
- fields: import_zod2.z.array(import_zod2.z.string()).optional()
276
+ var permissionSchema = import_zod3.z.object({
277
+ collection: import_zod3.z.string().min(1).max(64),
278
+ action: import_zod3.z.enum(["create", "read", "update", "delete", "share"]),
279
+ permissions: import_zod3.z.record(import_zod3.z.unknown()).optional(),
280
+ validation: import_zod3.z.record(import_zod3.z.unknown()).optional(),
281
+ presets: import_zod3.z.record(import_zod3.z.unknown()).optional(),
282
+ fields: import_zod3.z.array(import_zod3.z.string()).optional()
269
283
  });
270
284
  function registerAccessTools(server, client) {
271
285
  registerCrud(server, client, {
@@ -280,26 +294,26 @@ function registerAccessTools(server, client) {
280
294
  {
281
295
  description: "Attach a policy to a role. Conflicts/warnings may require overrideWarnings=true.",
282
296
  inputSchema: {
283
- id: import_zod2.z.string().min(1).describe("Role id."),
284
- policyId: import_zod2.z.string().min(1),
285
- priority: import_zod2.z.number().int().optional(),
286
- overrideWarnings: import_zod2.z.boolean().optional()
297
+ id: idPathSegmentSchema.describe("Role id."),
298
+ policyId: idPathSegmentSchema,
299
+ priority: import_zod3.z.number().int().optional(),
300
+ overrideWarnings: import_zod3.z.boolean().optional()
287
301
  }
288
302
  },
289
- async ({ id, ...body }) => run(() => client.post(`/roles/${id}/policies`, body))
303
+ async ({ id, ...body }) => run(() => client.post(`/roles/${encodePathSegment(id)}/policies`, body))
290
304
  );
291
305
  server.registerTool(
292
306
  "detach_role_policy",
293
307
  {
294
308
  description: "Detach a policy from a role. DESTRUCTIVE \u2014 pass confirm=true.",
295
309
  inputSchema: {
296
- id: import_zod2.z.string().min(1).describe("Role id."),
297
- policyId: import_zod2.z.string().min(1),
298
- confirm: import_zod2.z.literal(true).describe(confirmDescription)
310
+ id: idPathSegmentSchema.describe("Role id."),
311
+ policyId: idPathSegmentSchema,
312
+ confirm: import_zod3.z.literal(true).describe(confirmDescription)
299
313
  }
300
314
  },
301
315
  async ({ id, policyId }) => run(async () => {
302
- await client.delete(`/roles/${id}/policies/${policyId}`);
316
+ await client.delete(`/roles/${encodePathSegment(id)}/policies/${encodePathSegment(policyId)}`);
303
317
  return okText(`Policy "${policyId}" detached from role "${id}".`);
304
318
  })
305
319
  );
@@ -307,22 +321,22 @@ function registerAccessTools(server, client) {
307
321
  "assign_role_user",
308
322
  {
309
323
  description: "Assign a role to a user (sets the user's primary role for this site).",
310
- inputSchema: { id: import_zod2.z.string().min(1).describe("Role id."), userId: import_zod2.z.string().min(1) }
324
+ inputSchema: { id: idPathSegmentSchema.describe("Role id."), userId: idPathSegmentSchema }
311
325
  },
312
- async ({ id, userId }) => run(() => client.post(`/roles/${id}/users`, { userId }))
326
+ async ({ id, userId }) => run(() => client.post(`/roles/${encodePathSegment(id)}/users`, { userId }))
313
327
  );
314
328
  server.registerTool(
315
329
  "remove_role_user",
316
330
  {
317
331
  description: "Remove a user's role assignment. DESTRUCTIVE \u2014 pass confirm=true.",
318
332
  inputSchema: {
319
- id: import_zod2.z.string().min(1).describe("Role id."),
320
- userId: import_zod2.z.string().min(1),
321
- confirm: import_zod2.z.literal(true).describe(confirmDescription)
333
+ id: idPathSegmentSchema.describe("Role id."),
334
+ userId: idPathSegmentSchema,
335
+ confirm: import_zod3.z.literal(true).describe(confirmDescription)
322
336
  }
323
337
  },
324
338
  async ({ id, userId }) => run(async () => {
325
- await client.delete(`/roles/${id}/users/${userId}`);
339
+ await client.delete(`/roles/${encodePathSegment(id)}/users/${encodePathSegment(userId)}`);
326
340
  return okText(`User "${userId}" removed from role "${id}".`);
327
341
  })
328
342
  );
@@ -338,34 +352,34 @@ function registerAccessTools(server, client) {
338
352
  "add_policy_permission",
339
353
  {
340
354
  description: "Add a permission row (collection + action) to a policy.",
341
- inputSchema: { id: import_zod2.z.string().min(1).describe("Policy id."), ...permissionSchema.shape }
355
+ inputSchema: { id: idPathSegmentSchema.describe("Policy id."), ...permissionSchema.shape }
342
356
  },
343
- async ({ id, ...body }) => run(() => client.post(`/policies/${id}/permissions`, body))
357
+ async ({ id, ...body }) => run(() => client.post(`/policies/${encodePathSegment(id)}/permissions`, body))
344
358
  );
345
359
  server.registerTool(
346
360
  "update_policy_permission",
347
361
  {
348
362
  description: "Update a permission row on a policy (partial PATCH).",
349
363
  inputSchema: {
350
- id: import_zod2.z.string().min(1).describe("Policy id."),
351
- permId: import_zod2.z.string().min(1).describe("Permission row id."),
364
+ id: idPathSegmentSchema.describe("Policy id."),
365
+ permId: idPathSegmentSchema.describe("Permission row id."),
352
366
  ...permissionSchema.partial().shape
353
367
  }
354
368
  },
355
- async ({ id, permId, ...body }) => run(() => client.patch(`/policies/${id}/permissions/${permId}`, body))
369
+ async ({ id, permId, ...body }) => run(() => client.patch(`/policies/${encodePathSegment(id)}/permissions/${encodePathSegment(permId)}`, body))
356
370
  );
357
371
  server.registerTool(
358
372
  "delete_policy_permission",
359
373
  {
360
374
  description: "Delete a permission row from a policy. DESTRUCTIVE \u2014 pass confirm=true.",
361
375
  inputSchema: {
362
- id: import_zod2.z.string().min(1).describe("Policy id."),
363
- permId: import_zod2.z.string().min(1).describe("Permission row id."),
364
- confirm: import_zod2.z.literal(true).describe(confirmDescription)
376
+ id: idPathSegmentSchema.describe("Policy id."),
377
+ permId: idPathSegmentSchema.describe("Permission row id."),
378
+ confirm: import_zod3.z.literal(true).describe(confirmDescription)
365
379
  }
366
380
  },
367
381
  async ({ id, permId }) => run(async () => {
368
- await client.delete(`/policies/${id}/permissions/${permId}`);
382
+ await client.delete(`/policies/${encodePathSegment(id)}/permissions/${encodePathSegment(permId)}`);
369
383
  return okText(`Permission "${permId}" deleted from policy "${id}".`);
370
384
  })
371
385
  );
@@ -374,26 +388,26 @@ function registerAccessTools(server, client) {
374
388
  {
375
389
  description: "Attach a policy directly to a user. Warnings may require overrideWarnings=true.",
376
390
  inputSchema: {
377
- id: import_zod2.z.string().min(1).describe("Policy id."),
378
- userId: import_zod2.z.string().min(1),
379
- priority: import_zod2.z.number().int().optional(),
380
- overrideWarnings: import_zod2.z.boolean().optional()
391
+ id: idPathSegmentSchema.describe("Policy id."),
392
+ userId: idPathSegmentSchema,
393
+ priority: import_zod3.z.number().int().optional(),
394
+ overrideWarnings: import_zod3.z.boolean().optional()
381
395
  }
382
396
  },
383
- async ({ id, ...body }) => run(() => client.post(`/policies/${id}/users`, body))
397
+ async ({ id, ...body }) => run(() => client.post(`/policies/${encodePathSegment(id)}/users`, body))
384
398
  );
385
399
  server.registerTool(
386
400
  "detach_policy_user",
387
401
  {
388
402
  description: "Detach a policy from a user. DESTRUCTIVE \u2014 pass confirm=true.",
389
403
  inputSchema: {
390
- id: import_zod2.z.string().min(1).describe("Policy id."),
391
- userId: import_zod2.z.string().min(1),
392
- confirm: import_zod2.z.literal(true).describe(confirmDescription)
404
+ id: idPathSegmentSchema.describe("Policy id."),
405
+ userId: idPathSegmentSchema,
406
+ confirm: import_zod3.z.literal(true).describe(confirmDescription)
393
407
  }
394
408
  },
395
409
  async ({ id, userId }) => run(async () => {
396
- await client.delete(`/policies/${id}/users/${userId}`);
410
+ await client.delete(`/policies/${encodePathSegment(id)}/users/${encodePathSegment(userId)}`);
397
411
  return okText(`Policy "${id}" detached from user "${userId}".`);
398
412
  })
399
413
  );
@@ -406,7 +420,7 @@ function registerAccessTools(server, client) {
406
420
  "dry_run_access_import",
407
421
  {
408
422
  description: "Validate an RBAC manifest import without applying it. Returns the planned changes.",
409
- inputSchema: { manifest: import_zod2.z.record(import_zod2.z.unknown()).describe("RBAC manifest from export_access.") }
423
+ inputSchema: { manifest: import_zod3.z.record(import_zod3.z.unknown()).describe("RBAC manifest from export_access.") }
410
424
  },
411
425
  async ({ manifest }) => run(() => client.post("/access/import?dryRun=true", manifest))
412
426
  );
@@ -415,9 +429,9 @@ function registerAccessTools(server, client) {
415
429
  {
416
430
  description: "Apply an RBAC manifest import. High-impact \u2014 changes roles/policies/permissions. Pass confirm=true.",
417
431
  inputSchema: {
418
- manifest: import_zod2.z.record(import_zod2.z.unknown()).describe("RBAC manifest from export_access."),
419
- mode: import_zod2.z.enum(["merge", "replace-managed", "replace-all"]).optional().describe("Import mode (default merge)."),
420
- confirm: import_zod2.z.literal(true).describe(confirmDescription)
432
+ manifest: import_zod3.z.record(import_zod3.z.unknown()).describe("RBAC manifest from export_access."),
433
+ mode: import_zod3.z.enum(["merge", "replace-managed", "replace-all"]).optional().describe("Import mode (default merge)."),
434
+ confirm: import_zod3.z.literal(true).describe(confirmDescription)
421
435
  }
422
436
  },
423
437
  async ({ manifest, mode }) => run(() => client.post(`/access/import${mode ? `?mode=${mode}` : ""}`, manifest))
@@ -427,9 +441,9 @@ function registerAccessTools(server, client) {
427
441
  {
428
442
  description: "Check for permission conflicts before attaching/detaching policies on a target.",
429
443
  inputSchema: {
430
- target: import_zod2.z.object({ type: import_zod2.z.enum(["role", "user", "api_key"]), id: import_zod2.z.string().min(1) }).describe("The role/user/api_key the policies would apply to."),
431
- addPolicies: import_zod2.z.array(import_zod2.z.string()).optional(),
432
- removePolicies: import_zod2.z.array(import_zod2.z.string()).optional()
444
+ target: import_zod3.z.object({ type: import_zod3.z.enum(["role", "user", "api_key"]), id: import_zod3.z.string().min(1) }).describe("The role/user/api_key the policies would apply to."),
445
+ addPolicies: import_zod3.z.array(import_zod3.z.string()).optional(),
446
+ removePolicies: import_zod3.z.array(import_zod3.z.string()).optional()
433
447
  }
434
448
  },
435
449
  async (input) => run(() => client.post("/access/conflicts/check", input))
@@ -437,14 +451,14 @@ function registerAccessTools(server, client) {
437
451
  }
438
452
 
439
453
  // src/tools/admin.ts
440
- var import_zod3 = require("zod");
441
- var materializeSchema = import_zod3.z.object({
442
- collection: import_zod3.z.string().min(1).describe("Source collection name."),
443
- target: import_zod3.z.string().regex(/^[a-z][a-z0-9_]{0,62}$/).describe("Physical table name (snake_case)."),
444
- refreshStrategy: import_zod3.z.enum(["auto", "cron", "manual"]).optional(),
445
- refreshCron: import_zod3.z.string().optional(),
446
- projection: import_zod3.z.object({ fields: import_zod3.z.array(import_zod3.z.string()).optional(), orderBy: import_zod3.z.string().optional() }).optional(),
447
- filter: import_zod3.z.record(import_zod3.z.unknown()).optional()
454
+ var import_zod4 = require("zod");
455
+ var materializeSchema = import_zod4.z.object({
456
+ collection: import_zod4.z.string().min(1).describe("Source collection name."),
457
+ target: import_zod4.z.string().regex(/^[a-z][a-z0-9_]{0,62}$/).describe("Physical table name (snake_case)."),
458
+ refreshStrategy: import_zod4.z.enum(["auto", "cron", "manual"]).optional(),
459
+ refreshCron: import_zod4.z.string().optional(),
460
+ projection: import_zod4.z.object({ fields: import_zod4.z.array(import_zod4.z.string()).optional(), orderBy: import_zod4.z.string().optional() }).optional(),
461
+ filter: import_zod4.z.record(import_zod4.z.unknown()).optional()
448
462
  });
449
463
  function registerAdminTools(server, client) {
450
464
  server.registerTool(
@@ -460,8 +474,8 @@ function registerAdminTools(server, client) {
460
474
  {
461
475
  description: "Restore a site configuration from an NDJSON bundle (as produced by export_backup). Existing rows are skipped (idempotent). DESTRUCTIVE / high-impact \u2014 pass confirm=true.",
462
476
  inputSchema: {
463
- ndjson: import_zod3.z.string().min(1).describe("Raw NDJSON backup content, one JSON object per line."),
464
- confirm: import_zod3.z.literal(true).describe(confirmDescription)
477
+ ndjson: import_zod4.z.string().min(1).describe("Raw NDJSON backup content, one JSON object per line."),
478
+ confirm: import_zod4.z.literal(true).describe(confirmDescription)
465
479
  }
466
480
  },
467
481
  async ({ ndjson }) => run(() => client.postRaw("/admin/restore", ndjson))
@@ -483,58 +497,58 @@ function registerAdminTools(server, client) {
483
497
  "refresh_materialization",
484
498
  {
485
499
  description: "Refresh a materialized collection (truncate + re-insert from source).",
486
- inputSchema: { id: import_zod3.z.string().min(1) }
500
+ inputSchema: { id: idPathSegmentSchema }
487
501
  },
488
- async ({ id }) => run(() => client.post(`/materialize/${id}/refresh`, {}))
502
+ async ({ id }) => run(() => client.post(`/materialize/${encodePathSegment(id)}/refresh`, {}))
489
503
  );
490
504
  server.registerTool(
491
505
  "query_materialization",
492
506
  {
493
507
  description: "Query the physical table of a materialized collection directly.",
494
- inputSchema: { id: import_zod3.z.string().min(1) }
508
+ inputSchema: { id: idPathSegmentSchema }
495
509
  },
496
- async ({ id }) => run(() => client.get(`/materialize/${id}/data`))
510
+ async ({ id }) => run(() => client.get(`/materialize/${encodePathSegment(id)}/data`))
497
511
  );
498
512
  server.registerTool(
499
513
  "drop_materialization",
500
514
  {
501
515
  description: "Drop a materialized collection (physical table + metadata). DESTRUCTIVE \u2014 pass confirm=true.",
502
- inputSchema: { id: import_zod3.z.string().min(1), confirm: import_zod3.z.literal(true).describe(confirmDescription) }
516
+ inputSchema: { id: idPathSegmentSchema, confirm: import_zod4.z.literal(true).describe(confirmDescription) }
503
517
  },
504
518
  async ({ id }) => run(async () => {
505
- await client.delete(`/materialize/${id}`);
519
+ await client.delete(`/materialize/${encodePathSegment(id)}`);
506
520
  return okText(`Materialization "${id}" dropped.`);
507
521
  })
508
522
  );
509
523
  }
510
524
 
511
525
  // src/tools/agent.ts
512
- var import_zod4 = require("zod");
513
- var intentSchema = import_zod4.z.object({
514
- name: import_zod4.z.string().min(1).max(120),
515
- collection: import_zod4.z.string().min(1).max(120),
516
- rules: import_zod4.z.array(import_zod4.z.record(import_zod4.z.unknown())).describe("SLO rules (required_fields, freshness, translations, link_health, \u2026)."),
517
- schedule: import_zod4.z.string().describe("5-field cron expression for reconciliation cadence."),
518
- budget: import_zod4.z.record(import_zod4.z.unknown()).optional(),
519
- autonomyCap: import_zod4.z.number().int().min(0).max(4).optional().describe("Max autonomy level L0\u2013L4 for this intent."),
520
- maintenanceWindow: import_zod4.z.record(import_zod4.z.unknown()).nullable().optional()
526
+ var import_zod5 = require("zod");
527
+ var intentSchema = import_zod5.z.object({
528
+ name: import_zod5.z.string().min(1).max(120),
529
+ collection: import_zod5.z.string().min(1).max(120),
530
+ rules: import_zod5.z.array(import_zod5.z.record(import_zod5.z.unknown())).describe("SLO rules (required_fields, freshness, translations, link_health, \u2026)."),
531
+ schedule: import_zod5.z.string().describe("5-field cron expression for reconciliation cadence."),
532
+ budget: import_zod5.z.record(import_zod5.z.unknown()).optional(),
533
+ autonomyCap: import_zod5.z.number().int().min(0).max(4).optional().describe("Max autonomy level L0\u2013L4 for this intent."),
534
+ maintenanceWindow: import_zod5.z.record(import_zod5.z.unknown()).nullable().optional()
521
535
  });
522
- var flowNode = import_zod4.z.object({
523
- id: import_zod4.z.string(),
524
- key: import_zod4.z.string(),
525
- options: import_zod4.z.record(import_zod4.z.unknown()).optional(),
526
- next: import_zod4.z.string().nullable().optional(),
527
- onError: import_zod4.z.string().nullable().optional()
536
+ var flowNode = import_zod5.z.object({
537
+ id: import_zod5.z.string(),
538
+ key: import_zod5.z.string(),
539
+ options: import_zod5.z.record(import_zod5.z.unknown()).optional(),
540
+ next: import_zod5.z.string().nullable().optional(),
541
+ onError: import_zod5.z.string().nullable().optional()
528
542
  });
529
- var flowSchema = import_zod4.z.object({
530
- name: import_zod4.z.string().min(1),
531
- description: import_zod4.z.string().optional(),
532
- status: import_zod4.z.enum(["active", "inactive", "draft"]).optional(),
533
- triggerType: import_zod4.z.enum(["webhook", "event", "schedule", "manual"]),
534
- triggerOptions: import_zod4.z.record(import_zod4.z.unknown()).optional(),
535
- graph: import_zod4.z.object({
536
- entry: import_zod4.z.string().optional(),
537
- nodes: import_zod4.z.array(flowNode).optional()
543
+ var flowSchema = import_zod5.z.object({
544
+ name: import_zod5.z.string().min(1),
545
+ description: import_zod5.z.string().optional(),
546
+ status: import_zod5.z.enum(["active", "inactive", "draft"]).optional(),
547
+ triggerType: import_zod5.z.enum(["webhook", "event", "schedule", "manual"]),
548
+ triggerOptions: import_zod5.z.record(import_zod5.z.unknown()).optional(),
549
+ graph: import_zod5.z.object({
550
+ entry: import_zod5.z.string().optional(),
551
+ nodes: import_zod5.z.array(flowNode).optional()
538
552
  })
539
553
  });
540
554
  function registerAgentTools(server, client) {
@@ -547,31 +561,31 @@ function registerAgentTools(server, client) {
547
561
  });
548
562
  server.registerTool(
549
563
  "pause_intent",
550
- { description: "Pause an intent (stops scheduled reconciliation).", inputSchema: { id: import_zod4.z.string().min(1) } },
551
- async ({ id }) => run(() => client.post(`/agent/intents/${id}/pause`, {}))
564
+ { description: "Pause an intent (stops scheduled reconciliation).", inputSchema: { id: idPathSegmentSchema } },
565
+ async ({ id }) => run(() => client.post(`/agent/intents/${encodePathSegment(id)}/pause`, {}))
552
566
  );
553
567
  server.registerTool(
554
568
  "resume_intent",
555
- { description: "Resume a paused intent.", inputSchema: { id: import_zod4.z.string().min(1) } },
556
- async ({ id }) => run(() => client.post(`/agent/intents/${id}/resume`, {}))
569
+ { description: "Resume a paused intent.", inputSchema: { id: idPathSegmentSchema } },
570
+ async ({ id }) => run(() => client.post(`/agent/intents/${encodePathSegment(id)}/resume`, {}))
557
571
  );
558
572
  server.registerTool(
559
573
  "list_intent_drifts",
560
- { description: "List detected drifts (intent violations) for an intent.", inputSchema: { id: import_zod4.z.string().min(1) } },
561
- async ({ id }) => run(() => client.get(`/agent/intents/${id}/drifts`))
574
+ { description: "List detected drifts (intent violations) for an intent.", inputSchema: { id: idPathSegmentSchema } },
575
+ async ({ id }) => run(() => client.get(`/agent/intents/${encodePathSegment(id)}/drifts`))
562
576
  );
563
577
  server.registerTool(
564
578
  "scan_intent",
565
- { description: "Trigger an on-demand drift scan for an intent.", inputSchema: { id: import_zod4.z.string().min(1) } },
566
- async ({ id }) => run(() => client.post(`/agent/intents/${id}/scan`, {}))
579
+ { description: "Trigger an on-demand drift scan for an intent.", inputSchema: { id: idPathSegmentSchema } },
580
+ async ({ id }) => run(() => client.post(`/agent/intents/${encodePathSegment(id)}/scan`, {}))
567
581
  );
568
582
  server.registerTool(
569
583
  "compile_intent",
570
584
  {
571
585
  description: "Compile a natural-language description into structured intent rules (preview, does not persist).",
572
586
  inputSchema: {
573
- description: import_zod4.z.string().min(1).max(4e3),
574
- collection: import_zod4.z.string().min(1).max(120)
587
+ description: import_zod5.z.string().min(1).max(4e3),
588
+ collection: import_zod5.z.string().min(1).max(120)
575
589
  }
576
590
  },
577
591
  async (input) => run(() => client.post("/agent/intents/compile", input))
@@ -588,21 +602,21 @@ function registerAgentTools(server, client) {
588
602
  {
589
603
  description: "Trigger a manual run of a flow with an optional input payload.",
590
604
  inputSchema: {
591
- id: import_zod4.z.string().min(1),
592
- input: import_zod4.z.record(import_zod4.z.unknown()).optional().describe("Initial context passed to the flow.")
605
+ id: idPathSegmentSchema,
606
+ input: import_zod5.z.record(import_zod5.z.unknown()).optional().describe("Initial context passed to the flow.")
593
607
  }
594
608
  },
595
- async ({ id, input }) => run(() => client.post(`/flows/${id}/run`, input ?? {}))
609
+ async ({ id, input }) => run(() => client.post(`/flows/${encodePathSegment(id)}/run`, input ?? {}))
596
610
  );
597
611
  server.registerTool(
598
612
  "list_flow_runs",
599
- { description: "List recent runs of a flow.", inputSchema: { id: import_zod4.z.string().min(1) } },
600
- async ({ id }) => run(() => client.get(`/flows/${id}/runs`))
613
+ { description: "List recent runs of a flow.", inputSchema: { id: idPathSegmentSchema } },
614
+ async ({ id }) => run(() => client.get(`/flows/${encodePathSegment(id)}/runs`))
601
615
  );
602
616
  }
603
617
 
604
618
  // src/tools/api-keys.ts
605
- var import_zod5 = require("zod");
619
+ var import_zod6 = require("zod");
606
620
  function registerApiKeyTools(server, client) {
607
621
  server.registerTool(
608
622
  "list_api_keys",
@@ -611,18 +625,18 @@ function registerApiKeyTools(server, client) {
611
625
  );
612
626
  server.registerTool(
613
627
  "get_api_key",
614
- { description: "Get a single API key by id.", inputSchema: { id: import_zod5.z.string().min(1) } },
615
- async ({ id }) => run(() => client.get(`/api-keys/${id}`))
628
+ { description: "Get a single API key by id.", inputSchema: { id: idPathSegmentSchema } },
629
+ async ({ id }) => run(() => client.get(`/api-keys/${encodePathSegment(id)}`))
616
630
  );
617
631
  server.registerTool(
618
632
  "create_api_key",
619
633
  {
620
634
  description: "Create a new API key. The plaintext token is returned ONCE in the response \u2014 surface it to the user and tell them it cannot be retrieved again.",
621
635
  inputSchema: {
622
- name: import_zod5.z.string().min(1).max(96),
623
- description: import_zod5.z.string().max(512).optional(),
624
- expiresAt: import_zod5.z.string().datetime().nullable().optional(),
625
- metadata: import_zod5.z.record(import_zod5.z.unknown()).optional()
636
+ name: import_zod6.z.string().min(1).max(96),
637
+ description: import_zod6.z.string().max(512).optional(),
638
+ expiresAt: import_zod6.z.string().datetime().nullable().optional(),
639
+ metadata: import_zod6.z.record(import_zod6.z.unknown()).optional()
626
640
  }
627
641
  },
628
642
  async (input) => run(() => client.post("/api-keys", input))
@@ -632,46 +646,46 @@ function registerApiKeyTools(server, client) {
632
646
  {
633
647
  description: "Rotate an API key \u2014 issues a new token (returned once) and invalidates the old one. DESTRUCTIVE for existing integrations \u2014 pass confirm=true.",
634
648
  inputSchema: {
635
- id: import_zod5.z.string().min(1),
636
- expiresAt: import_zod5.z.string().datetime().nullable().optional(),
637
- confirm: import_zod5.z.literal(true).describe(confirmDescription)
649
+ id: idPathSegmentSchema,
650
+ expiresAt: import_zod6.z.string().datetime().nullable().optional(),
651
+ confirm: import_zod6.z.literal(true).describe(confirmDescription)
638
652
  }
639
653
  },
640
- async ({ id, expiresAt }) => run(() => client.post(`/api-keys/${id}/rotate`, expiresAt !== void 0 ? { expiresAt } : {}))
654
+ async ({ id, expiresAt }) => run(() => client.post(`/api-keys/${encodePathSegment(id)}/rotate`, expiresAt !== void 0 ? { expiresAt } : {}))
641
655
  );
642
656
  server.registerTool(
643
657
  "revoke_api_key",
644
658
  {
645
659
  description: "Revoke an API key permanently. DESTRUCTIVE \u2014 pass confirm=true.",
646
- inputSchema: { id: import_zod5.z.string().min(1), confirm: import_zod5.z.literal(true).describe(confirmDescription) }
660
+ inputSchema: { id: idPathSegmentSchema, confirm: import_zod6.z.literal(true).describe(confirmDescription) }
647
661
  },
648
- async ({ id }) => run(() => client.post(`/api-keys/${id}/revoke`, {}))
662
+ async ({ id }) => run(() => client.post(`/api-keys/${encodePathSegment(id)}/revoke`, {}))
649
663
  );
650
664
  server.registerTool(
651
665
  "attach_api_key_role",
652
666
  {
653
667
  description: "Attach a role to an API key (grants the role\u2019s policies to the key).",
654
668
  inputSchema: {
655
- id: import_zod5.z.string().min(1).describe("API key id."),
656
- roleId: import_zod5.z.string().min(1),
657
- priority: import_zod5.z.number().int().optional(),
658
- overrideWarnings: import_zod5.z.boolean().optional()
669
+ id: idPathSegmentSchema.describe("API key id."),
670
+ roleId: idPathSegmentSchema,
671
+ priority: import_zod6.z.number().int().optional(),
672
+ overrideWarnings: import_zod6.z.boolean().optional()
659
673
  }
660
674
  },
661
- async ({ id, ...body }) => run(() => client.post(`/api-keys/${id}/roles`, body))
675
+ async ({ id, ...body }) => run(() => client.post(`/api-keys/${encodePathSegment(id)}/roles`, body))
662
676
  );
663
677
  server.registerTool(
664
678
  "detach_api_key_role",
665
679
  {
666
680
  description: "Detach a role from an API key. DESTRUCTIVE \u2014 pass confirm=true.",
667
681
  inputSchema: {
668
- id: import_zod5.z.string().min(1).describe("API key id."),
669
- roleId: import_zod5.z.string().min(1),
670
- confirm: import_zod5.z.literal(true).describe(confirmDescription)
682
+ id: idPathSegmentSchema.describe("API key id."),
683
+ roleId: idPathSegmentSchema,
684
+ confirm: import_zod6.z.literal(true).describe(confirmDescription)
671
685
  }
672
686
  },
673
687
  async ({ id, roleId }) => run(async () => {
674
- await client.delete(`/api-keys/${id}/roles/${roleId}`);
688
+ await client.delete(`/api-keys/${encodePathSegment(id)}/roles/${encodePathSegment(roleId)}`);
675
689
  return okText(`Role "${roleId}" detached from API key "${id}".`);
676
690
  })
677
691
  );
@@ -680,73 +694,72 @@ function registerApiKeyTools(server, client) {
680
694
  {
681
695
  description: "Attach a policy directly to an API key.",
682
696
  inputSchema: {
683
- id: import_zod5.z.string().min(1).describe("API key id."),
684
- policyId: import_zod5.z.string().min(1),
685
- priority: import_zod5.z.number().int().optional(),
686
- overrideWarnings: import_zod5.z.boolean().optional()
697
+ id: idPathSegmentSchema.describe("API key id."),
698
+ policyId: idPathSegmentSchema,
699
+ priority: import_zod6.z.number().int().optional(),
700
+ overrideWarnings: import_zod6.z.boolean().optional()
687
701
  }
688
702
  },
689
- async ({ id, ...body }) => run(() => client.post(`/api-keys/${id}/policies`, body))
703
+ async ({ id, ...body }) => run(() => client.post(`/api-keys/${encodePathSegment(id)}/policies`, body))
690
704
  );
691
705
  server.registerTool(
692
706
  "detach_api_key_policy",
693
707
  {
694
708
  description: "Detach a policy from an API key. DESTRUCTIVE \u2014 pass confirm=true.",
695
709
  inputSchema: {
696
- id: import_zod5.z.string().min(1).describe("API key id."),
697
- policyId: import_zod5.z.string().min(1),
698
- confirm: import_zod5.z.literal(true).describe(confirmDescription)
710
+ id: idPathSegmentSchema.describe("API key id."),
711
+ policyId: idPathSegmentSchema,
712
+ confirm: import_zod6.z.literal(true).describe(confirmDescription)
699
713
  }
700
714
  },
701
715
  async ({ id, policyId }) => run(async () => {
702
- await client.delete(`/api-keys/${id}/policies/${policyId}`);
716
+ await client.delete(`/api-keys/${encodePathSegment(id)}/policies/${encodePathSegment(policyId)}`);
703
717
  return okText(`Policy "${policyId}" detached from API key "${id}".`);
704
718
  })
705
719
  );
706
720
  }
707
721
 
708
722
  // src/tools/collections.ts
709
- var import_zod6 = require("zod");
710
- var collectionNameSchema = import_zod6.z.string().min(1).max(63).regex(/^[a-z][a-z0-9_]{0,62}$/, "Must be lowercase, start with a letter, only a-z0-9_");
711
- var collectionInputSchema = import_zod6.z.object({
723
+ var import_zod7 = require("zod");
724
+ var collectionInputSchema = import_zod7.z.object({
712
725
  name: collectionNameSchema,
713
- label: import_zod6.z.string().optional(),
714
- pluralLabel: import_zod6.z.string().optional(),
715
- hidden: import_zod6.z.boolean().optional(),
716
- singleton: import_zod6.z.boolean().optional(),
717
- icon: import_zod6.z.string().optional(),
718
- color: import_zod6.z.string().optional(),
719
- note: import_zod6.z.string().optional(),
720
- primaryKeyField: import_zod6.z.string().optional(),
721
- primaryKeyType: import_zod6.z.enum(["nanoid", "uuid", "integer", "bigInteger", "string"]).optional(),
722
- storageMode: import_zod6.z.enum(["jsonb", "materialized", "physical", "external"]).optional(),
723
- displayTemplate: import_zod6.z.string().optional(),
724
- sortField: import_zod6.z.string().optional(),
725
- archiveField: import_zod6.z.string().optional(),
726
- archiveValue: import_zod6.z.string().optional(),
727
- unarchiveValue: import_zod6.z.string().optional(),
728
- accountability: import_zod6.z.enum(["all", "activity", "none"]).optional(),
729
- versioning: import_zod6.z.boolean().optional()
726
+ label: import_zod7.z.string().optional(),
727
+ pluralLabel: import_zod7.z.string().optional(),
728
+ hidden: import_zod7.z.boolean().optional(),
729
+ singleton: import_zod7.z.boolean().optional(),
730
+ icon: import_zod7.z.string().optional(),
731
+ color: import_zod7.z.string().optional(),
732
+ note: import_zod7.z.string().optional(),
733
+ primaryKeyField: import_zod7.z.string().optional(),
734
+ primaryKeyType: import_zod7.z.enum(["nanoid", "uuid", "integer", "bigInteger", "string"]).optional(),
735
+ storageMode: import_zod7.z.enum(["jsonb", "materialized", "physical", "external"]).optional(),
736
+ displayTemplate: import_zod7.z.string().optional(),
737
+ sortField: import_zod7.z.string().optional(),
738
+ archiveField: import_zod7.z.string().optional(),
739
+ archiveValue: import_zod7.z.string().optional(),
740
+ unarchiveValue: import_zod7.z.string().optional(),
741
+ accountability: import_zod7.z.enum(["all", "activity", "none"]).optional(),
742
+ versioning: import_zod7.z.boolean().optional()
730
743
  });
731
- var fieldInputSchema = import_zod6.z.object({
732
- name: collectionNameSchema,
733
- type: import_zod6.z.string().min(1),
734
- interface: import_zod6.z.string().min(1),
735
- display: import_zod6.z.string().optional(),
736
- label: import_zod6.z.string().optional(),
737
- note: import_zod6.z.string().optional(),
738
- nullable: import_zod6.z.boolean().optional(),
739
- unique: import_zod6.z.boolean().optional(),
740
- indexed: import_zod6.z.boolean().optional(),
741
- searchable: import_zod6.z.boolean().optional(),
742
- required: import_zod6.z.boolean().optional(),
743
- readonly: import_zod6.z.boolean().optional(),
744
- hidden: import_zod6.z.boolean().optional(),
745
- width: import_zod6.z.enum(["half", "full", "fill"]).optional(),
746
- sortOrder: import_zod6.z.number().int().optional(),
747
- group: import_zod6.z.string().optional(),
748
- options: import_zod6.z.record(import_zod6.z.unknown()).optional(),
749
- defaultValue: import_zod6.z.unknown().optional()
744
+ var fieldInputSchema = import_zod7.z.object({
745
+ name: fieldNameSchema,
746
+ type: import_zod7.z.string().min(1),
747
+ interface: import_zod7.z.string().min(1),
748
+ display: import_zod7.z.string().optional(),
749
+ label: import_zod7.z.string().optional(),
750
+ note: import_zod7.z.string().optional(),
751
+ nullable: import_zod7.z.boolean().optional(),
752
+ unique: import_zod7.z.boolean().optional(),
753
+ indexed: import_zod7.z.boolean().optional(),
754
+ searchable: import_zod7.z.boolean().optional(),
755
+ required: import_zod7.z.boolean().optional(),
756
+ readonly: import_zod7.z.boolean().optional(),
757
+ hidden: import_zod7.z.boolean().optional(),
758
+ width: import_zod7.z.enum(["half", "full", "fill"]).optional(),
759
+ sortOrder: import_zod7.z.number().int().optional(),
760
+ group: import_zod7.z.string().optional(),
761
+ options: import_zod7.z.record(import_zod7.z.unknown()).optional(),
762
+ defaultValue: import_zod7.z.unknown().optional()
750
763
  });
751
764
  function formatError2(err) {
752
765
  if (err instanceof LumiBaseApiError) {
@@ -774,11 +787,11 @@ function registerCollectionTools(server, client) {
774
787
  "get_collection",
775
788
  {
776
789
  description: "Get a collection with its compiled schema (all fields, system fields, meta).",
777
- inputSchema: { name: import_zod6.z.string().min(1) }
790
+ inputSchema: { name: collectionNameSchema }
778
791
  },
779
792
  async ({ name }) => {
780
793
  try {
781
- const data = await client.get(`/collections/${name}/compiled`);
794
+ const data = await client.get(`/collections/${encodePathSegment(name)}/compiled`);
782
795
  return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
783
796
  } catch (err) {
784
797
  return { content: [{ type: "text", text: `Error: ${formatError2(err)}` }], isError: true };
@@ -805,13 +818,13 @@ function registerCollectionTools(server, client) {
805
818
  {
806
819
  description: "Update metadata on an existing collection (label, icon, note, accountability, etc.).",
807
820
  inputSchema: {
808
- name: import_zod6.z.string().min(1),
821
+ name: collectionNameSchema,
809
822
  patch: collectionInputSchema.omit({ name: true }).partial()
810
823
  }
811
824
  },
812
825
  async ({ name, patch }) => {
813
826
  try {
814
- const data = await client.patch(`/collections/${name}`, patch);
827
+ const data = await client.patch(`/collections/${encodePathSegment(name)}`, patch);
815
828
  return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
816
829
  } catch (err) {
817
830
  return { content: [{ type: "text", text: `Error: ${formatError2(err)}` }], isError: true };
@@ -823,13 +836,13 @@ function registerCollectionTools(server, client) {
823
836
  {
824
837
  description: "Delete a collection and all its items. DESTRUCTIVE \u2014 cannot be undone. You MUST pass confirm=true explicitly after warning the user.",
825
838
  inputSchema: {
826
- name: import_zod6.z.string().min(1),
827
- confirm: import_zod6.z.literal(true).describe("Must be true to confirm destructive operation")
839
+ name: collectionNameSchema,
840
+ confirm: import_zod7.z.literal(true).describe("Must be true to confirm destructive operation")
828
841
  }
829
842
  },
830
843
  async ({ name, confirm: _ }) => {
831
844
  try {
832
- await client.delete(`/collections/${name}`);
845
+ await client.delete(`/collections/${encodePathSegment(name)}`);
833
846
  return { content: [{ type: "text", text: `Collection "${name}" deleted.` }] };
834
847
  } catch (err) {
835
848
  return { content: [{ type: "text", text: `Error: ${formatError2(err)}` }], isError: true };
@@ -841,10 +854,10 @@ function registerCollectionTools(server, client) {
841
854
  {
842
855
  description: "Preview what would change if you applied a schema update. Returns added/modified/removed fields and any risky changes. Always call this before apply_schema to check for breaking changes.",
843
856
  inputSchema: {
844
- name: import_zod6.z.string().min(1),
845
- fields: import_zod6.z.array(fieldInputSchema).optional(),
846
- label: import_zod6.z.string().optional(),
847
- note: import_zod6.z.string().optional()
857
+ name: collectionNameSchema,
858
+ fields: import_zod7.z.array(fieldInputSchema).optional(),
859
+ label: import_zod7.z.string().optional(),
860
+ note: import_zod7.z.string().optional()
848
861
  }
849
862
  },
850
863
  async (input) => {
@@ -861,23 +874,26 @@ function registerCollectionTools(server, client) {
861
874
  {
862
875
  description: "Atomically apply a schema migration to a collection (add/update/remove fields and relations). Call diff_schema first to preview changes. Pass confirmRiskyChange=true on field inputs that have risky changes.",
863
876
  inputSchema: {
864
- name: import_zod6.z.string().min(1),
865
- fields: import_zod6.z.array(
877
+ name: collectionNameSchema,
878
+ fields: import_zod7.z.array(
866
879
  fieldInputSchema.extend({
867
- renameFrom: import_zod6.z.string().optional(),
868
- confirmRiskyChange: import_zod6.z.boolean().optional()
880
+ renameFrom: fieldNameSchema.optional(),
881
+ confirmRiskyChange: import_zod7.z.boolean().optional()
869
882
  })
870
883
  ).optional(),
871
- label: import_zod6.z.string().optional(),
872
- note: import_zod6.z.string().optional(),
873
- accountability: import_zod6.z.enum(["all", "activity", "none"]).optional(),
874
- versioning: import_zod6.z.boolean().optional()
884
+ label: import_zod7.z.string().optional(),
885
+ note: import_zod7.z.string().optional(),
886
+ accountability: import_zod7.z.enum(["all", "activity", "none"]).optional(),
887
+ versioning: import_zod7.z.boolean().optional()
875
888
  }
876
889
  },
877
890
  async (input) => {
878
891
  try {
879
892
  const { name, ...rest } = input;
880
- const data = await client.put(`/collections/${name}/schema`, rest);
893
+ const data = await client.put(
894
+ `/collections/${encodePathSegment(name)}/schema`,
895
+ rest
896
+ );
881
897
  return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
882
898
  } catch (err) {
883
899
  return { content: [{ type: "text", text: `Error: ${formatError2(err)}` }], isError: true };
@@ -887,34 +903,34 @@ function registerCollectionTools(server, client) {
887
903
  }
888
904
 
889
905
  // src/tools/content-config.ts
890
- var import_zod7 = require("zod");
891
- var presetSchema = import_zod7.z.object({
892
- bookmark: import_zod7.z.string().nullable().optional(),
893
- collection: import_zod7.z.string(),
894
- userId: import_zod7.z.string().nullable().optional(),
895
- roleId: import_zod7.z.string().nullable().optional(),
896
- layout: import_zod7.z.string().optional(),
897
- layoutQuery: import_zod7.z.record(import_zod7.z.unknown()).optional(),
898
- layoutOptions: import_zod7.z.record(import_zod7.z.unknown()).optional(),
899
- search: import_zod7.z.string().nullable().optional(),
900
- filter: import_zod7.z.record(import_zod7.z.unknown()).optional(),
901
- icon: import_zod7.z.string().nullable().optional(),
902
- color: import_zod7.z.string().nullable().optional(),
903
- refreshInterval: import_zod7.z.number().int().min(0).optional()
906
+ var import_zod8 = require("zod");
907
+ var presetSchema = import_zod8.z.object({
908
+ bookmark: import_zod8.z.string().nullable().optional(),
909
+ collection: import_zod8.z.string(),
910
+ userId: import_zod8.z.string().nullable().optional(),
911
+ roleId: import_zod8.z.string().nullable().optional(),
912
+ layout: import_zod8.z.string().optional(),
913
+ layoutQuery: import_zod8.z.record(import_zod8.z.unknown()).optional(),
914
+ layoutOptions: import_zod8.z.record(import_zod8.z.unknown()).optional(),
915
+ search: import_zod8.z.string().nullable().optional(),
916
+ filter: import_zod8.z.record(import_zod8.z.unknown()).optional(),
917
+ icon: import_zod8.z.string().nullable().optional(),
918
+ color: import_zod8.z.string().nullable().optional(),
919
+ refreshInterval: import_zod8.z.number().int().min(0).optional()
904
920
  });
905
- var translationSchema = import_zod7.z.object({
906
- language: import_zod7.z.string(),
907
- namespace: import_zod7.z.string(),
908
- key: import_zod7.z.string(),
909
- value: import_zod7.z.string(),
910
- status: import_zod7.z.string().optional()
921
+ var translationSchema = import_zod8.z.object({
922
+ language: import_zod8.z.string(),
923
+ namespace: import_zod8.z.string(),
924
+ key: import_zod8.z.string(),
925
+ value: import_zod8.z.string(),
926
+ status: import_zod8.z.string().optional()
911
927
  });
912
928
  function registerContentConfigTools(server, client) {
913
929
  registerCrud(server, client, {
914
930
  basePath: "/presets",
915
931
  resource: "preset",
916
932
  namePrefix: "preset",
917
- listQuery: { collection: import_zod7.z.string().optional() },
933
+ listQuery: { collection: import_zod8.z.string().optional() },
918
934
  createSchema: presetSchema.shape,
919
935
  updateSchema: presetSchema.partial().shape
920
936
  });
@@ -923,8 +939,8 @@ function registerContentConfigTools(server, client) {
923
939
  resource: "translation",
924
940
  namePrefix: "translation",
925
941
  listQuery: {
926
- namespace: import_zod7.z.string().optional(),
927
- language: import_zod7.z.string().optional()
942
+ namespace: import_zod8.z.string().optional(),
943
+ language: import_zod8.z.string().optional()
928
944
  },
929
945
  createSchema: translationSchema.shape,
930
946
  updateSchema: translationSchema.partial().shape
@@ -933,7 +949,7 @@ function registerContentConfigTools(server, client) {
933
949
  "list_settings",
934
950
  {
935
951
  description: "List site settings, optionally filtered by scope.",
936
- inputSchema: { scope: import_zod7.z.string().optional() }
952
+ inputSchema: { scope: import_zod8.z.string().optional() }
937
953
  },
938
954
  async ({ scope }) => run(() => client.get(`/settings${scope ? `?scope=${encodeURIComponent(scope)}` : ""}`))
939
955
  );
@@ -941,18 +957,18 @@ function registerContentConfigTools(server, client) {
941
957
  "get_setting",
942
958
  {
943
959
  description: "Get a single setting by key.",
944
- inputSchema: { key: import_zod7.z.string().min(1) }
960
+ inputSchema: { key: idPathSegmentSchema }
945
961
  },
946
- async ({ key }) => run(() => client.get(`/settings/${encodeURIComponent(key)}`))
962
+ async ({ key }) => run(() => client.get(`/settings/${encodePathSegment(key)}`))
947
963
  );
948
964
  server.registerTool(
949
965
  "upsert_setting",
950
966
  {
951
967
  description: "Create or update a setting (upsert by key).",
952
968
  inputSchema: {
953
- key: import_zod7.z.string().min(1),
954
- value: import_zod7.z.record(import_zod7.z.unknown()).describe("Arbitrary JSON value object for the setting."),
955
- scope: import_zod7.z.string().optional()
969
+ key: idPathSegmentSchema,
970
+ value: import_zod8.z.record(import_zod8.z.unknown()).describe("Arbitrary JSON value object for the setting."),
971
+ scope: import_zod8.z.string().optional()
956
972
  }
957
973
  },
958
974
  async (input) => run(() => client.post("/settings", input))
@@ -962,29 +978,29 @@ function registerContentConfigTools(server, client) {
962
978
  {
963
979
  description: "Delete a setting by key. DESTRUCTIVE \u2014 warn the user first and pass confirm=true.",
964
980
  inputSchema: {
965
- key: import_zod7.z.string().min(1),
966
- confirm: import_zod7.z.literal(true).describe(confirmDescription)
981
+ key: idPathSegmentSchema,
982
+ confirm: import_zod8.z.literal(true).describe(confirmDescription)
967
983
  }
968
984
  },
969
985
  async ({ key }) => run(async () => {
970
- await client.delete(`/settings/${encodeURIComponent(key)}`);
986
+ await client.delete(`/settings/${encodePathSegment(key)}`);
971
987
  return okText(`Setting "${key}" deleted.`);
972
988
  })
973
989
  );
974
990
  }
975
991
 
976
992
  // src/tools/extensions.ts
977
- var import_zod8 = require("zod");
993
+ var import_zod9 = require("zod");
978
994
  var EXTENSION_TYPES = ["interface", "display", "layout", "panel", "module", "hook", "endpoint"];
979
- var extensionSchema = import_zod8.z.object({
980
- key: import_zod8.z.string().regex(/^[a-z0-9_:-]+$/).optional(),
981
- name: import_zod8.z.string().min(1),
982
- version: import_zod8.z.string().min(1),
983
- type: import_zod8.z.enum(EXTENSION_TYPES),
984
- enabled: import_zod8.z.boolean().optional(),
985
- bundleUrl: import_zod8.z.string().min(1).describe("https:, http:, or data:text/javascript bundle URL."),
986
- manifest: import_zod8.z.record(import_zod8.z.string()).optional(),
987
- capabilities: import_zod8.z.array(import_zod8.z.string()).optional()
995
+ var extensionSchema = import_zod9.z.object({
996
+ key: import_zod9.z.string().regex(/^[a-z0-9_:-]+$/).optional(),
997
+ name: import_zod9.z.string().min(1),
998
+ version: import_zod9.z.string().min(1),
999
+ type: import_zod9.z.enum(EXTENSION_TYPES),
1000
+ enabled: import_zod9.z.boolean().optional(),
1001
+ bundleUrl: import_zod9.z.string().min(1).describe("https:, http:, or data:text/javascript bundle URL."),
1002
+ manifest: import_zod9.z.record(import_zod9.z.string()).optional(),
1003
+ capabilities: import_zod9.z.array(import_zod9.z.string()).optional()
988
1004
  });
989
1005
  function registerExtensionTools(server, client) {
990
1006
  server.registerTool(
@@ -1004,18 +1020,18 @@ function registerExtensionTools(server, client) {
1004
1020
  "update_extension",
1005
1021
  {
1006
1022
  description: "Update an installed extension (enable/disable, version, config). Partial PATCH.",
1007
- inputSchema: { id: import_zod8.z.string().min(1), ...extensionSchema.partial().shape }
1023
+ inputSchema: { id: idPathSegmentSchema, ...extensionSchema.partial().shape }
1008
1024
  },
1009
- async ({ id, ...patch }) => run(() => client.patch(`/extensions/${id}`, patch))
1025
+ async ({ id, ...patch }) => run(() => client.patch(`/extensions/${encodePathSegment(id)}`, patch))
1010
1026
  );
1011
1027
  server.registerTool(
1012
1028
  "uninstall_extension",
1013
1029
  {
1014
1030
  description: "Uninstall an extension from the site. DESTRUCTIVE \u2014 pass confirm=true.",
1015
- inputSchema: { id: import_zod8.z.string().min(1), confirm: import_zod8.z.literal(true).describe(confirmDescription) }
1031
+ inputSchema: { id: idPathSegmentSchema, confirm: import_zod9.z.literal(true).describe(confirmDescription) }
1016
1032
  },
1017
1033
  async ({ id }) => run(async () => {
1018
- await client.delete(`/extensions/${id}`);
1034
+ await client.delete(`/extensions/${encodePathSegment(id)}`);
1019
1035
  return okText(`Extension "${id}" uninstalled.`);
1020
1036
  })
1021
1037
  );
@@ -1024,12 +1040,12 @@ function registerExtensionTools(server, client) {
1024
1040
  {
1025
1041
  description: "Browse the published extension marketplace.",
1026
1042
  inputSchema: {
1027
- q: import_zod8.z.string().optional(),
1028
- category: import_zod8.z.string().optional(),
1029
- tags: import_zod8.z.string().optional().describe("Comma-separated tags."),
1030
- sort: import_zod8.z.string().optional(),
1031
- page: import_zod8.z.number().int().min(1).optional(),
1032
- perPage: import_zod8.z.number().int().min(1).optional()
1043
+ q: import_zod9.z.string().optional(),
1044
+ category: import_zod9.z.string().optional(),
1045
+ tags: import_zod9.z.string().optional().describe("Comma-separated tags."),
1046
+ sort: import_zod9.z.string().optional(),
1047
+ page: import_zod9.z.number().int().min(1).optional(),
1048
+ perPage: import_zod9.z.number().int().min(1).optional()
1033
1049
  }
1034
1050
  },
1035
1051
  async (args) => run(
@@ -1042,9 +1058,9 @@ function registerExtensionTools(server, client) {
1042
1058
  "get_marketplace_extension",
1043
1059
  {
1044
1060
  description: "Get a single marketplace extension by slug.",
1045
- inputSchema: { slug: import_zod8.z.string().min(1) }
1061
+ inputSchema: { slug: idPathSegmentSchema }
1046
1062
  },
1047
- async ({ slug }) => run(() => client.get(`/marketplace/extensions/${slug}`))
1063
+ async ({ slug }) => run(() => client.get(`/marketplace/extensions/${encodePathSegment(slug)}`))
1048
1064
  );
1049
1065
  server.registerTool(
1050
1066
  "list_marketplace_updates",
@@ -1055,22 +1071,22 @@ function registerExtensionTools(server, client) {
1055
1071
  "install_marketplace_extension",
1056
1072
  {
1057
1073
  description: "Install a published marketplace extension onto the active site by slug.",
1058
- inputSchema: { slug: import_zod8.z.string().min(1) }
1074
+ inputSchema: { slug: idPathSegmentSchema }
1059
1075
  },
1060
- async ({ slug }) => run(() => client.post(`/marketplace/extensions/${slug}/install`, {}))
1076
+ async ({ slug }) => run(() => client.post(`/marketplace/extensions/${encodePathSegment(slug)}/install`, {}))
1061
1077
  );
1062
1078
  server.registerTool(
1063
1079
  "publish_extension",
1064
1080
  {
1065
1081
  description: "Publish an extension to the marketplace (signs + marks it published).",
1066
1082
  inputSchema: {
1067
- extensionId: import_zod8.z.string().min(1),
1068
- marketplaceSlug: import_zod8.z.string().min(1),
1069
- publisher: import_zod8.z.record(import_zod8.z.unknown()).optional(),
1070
- signature: import_zod8.z.string().optional(),
1071
- signatureAlg: import_zod8.z.string().optional(),
1072
- publisherKeyId: import_zod8.z.string().optional(),
1073
- bundleSha256: import_zod8.z.string().optional()
1083
+ extensionId: import_zod9.z.string().min(1),
1084
+ marketplaceSlug: import_zod9.z.string().min(1),
1085
+ publisher: import_zod9.z.record(import_zod9.z.unknown()).optional(),
1086
+ signature: import_zod9.z.string().optional(),
1087
+ signatureAlg: import_zod9.z.string().optional(),
1088
+ publisherKeyId: import_zod9.z.string().optional(),
1089
+ bundleSha256: import_zod9.z.string().optional()
1074
1090
  }
1075
1091
  },
1076
1092
  async (input) => run(() => client.post("/marketplace/publish", input))
@@ -1078,40 +1094,39 @@ function registerExtensionTools(server, client) {
1078
1094
  }
1079
1095
 
1080
1096
  // src/tools/fields.ts
1081
- var import_zod9 = require("zod");
1082
- var namePattern = /^[a-z][a-z0-9_]{0,62}$/;
1083
- var fieldInputSchema2 = import_zod9.z.object({
1084
- type: import_zod9.z.string().min(1).describe(
1097
+ var import_zod10 = require("zod");
1098
+ var fieldInputSchema2 = import_zod10.z.object({
1099
+ type: import_zod10.z.string().min(1).describe(
1085
1100
  "Storage type: string, text, integer, bigInteger, float, decimal, boolean, date, dateTime, time, json, uuid, csv, hash, alias"
1086
1101
  ),
1087
- interface: import_zod9.z.string().min(1).describe(
1102
+ interface: import_zod10.z.string().min(1).describe(
1088
1103
  "UI widget: input, textarea, select, toggle, datetime, file, image, repeater, relation-m2o, relation-o2m, relation-m2m, code, markdown, wysiwyg, \u2026"
1089
1104
  ),
1090
- display: import_zod9.z.string().optional(),
1091
- label: import_zod9.z.string().optional(),
1092
- note: import_zod9.z.string().optional(),
1093
- defaultValue: import_zod9.z.unknown().optional(),
1094
- nullable: import_zod9.z.boolean().optional().default(true),
1095
- unique: import_zod9.z.boolean().optional().default(false),
1096
- indexed: import_zod9.z.boolean().optional().default(false),
1097
- searchable: import_zod9.z.boolean().optional().default(false),
1098
- length: import_zod9.z.number().int().positive().optional(),
1099
- precision: import_zod9.z.number().int().positive().optional(),
1100
- scale: import_zod9.z.number().int().min(0).optional(),
1101
- special: import_zod9.z.array(import_zod9.z.string()).optional(),
1102
- options: import_zod9.z.record(import_zod9.z.unknown()).optional(),
1103
- displayOptions: import_zod9.z.record(import_zod9.z.unknown()).optional(),
1104
- conditions: import_zod9.z.array(import_zod9.z.unknown()).optional(),
1105
- required: import_zod9.z.boolean().optional().default(false),
1106
- readonly: import_zod9.z.boolean().optional().default(false),
1107
- hidden: import_zod9.z.boolean().optional().default(false),
1108
- encrypted: import_zod9.z.boolean().optional().default(false),
1109
- versioned: import_zod9.z.boolean().optional().default(false),
1110
- width: import_zod9.z.enum(["half", "full", "fill"]).optional().default("full"),
1111
- group: import_zod9.z.string().optional(),
1112
- sortOrder: import_zod9.z.number().int().optional(),
1113
- renameFrom: import_zod9.z.string().regex(namePattern).optional().describe("Previous field name if this is a rename operation"),
1114
- confirmRiskyChange: import_zod9.z.boolean().optional().describe("Set true to confirm type-change or destructive migration")
1105
+ display: import_zod10.z.string().optional(),
1106
+ label: import_zod10.z.string().optional(),
1107
+ note: import_zod10.z.string().optional(),
1108
+ defaultValue: import_zod10.z.unknown().optional(),
1109
+ nullable: import_zod10.z.boolean().optional().default(true),
1110
+ unique: import_zod10.z.boolean().optional().default(false),
1111
+ indexed: import_zod10.z.boolean().optional().default(false),
1112
+ searchable: import_zod10.z.boolean().optional().default(false),
1113
+ length: import_zod10.z.number().int().positive().optional(),
1114
+ precision: import_zod10.z.number().int().positive().optional(),
1115
+ scale: import_zod10.z.number().int().min(0).optional(),
1116
+ special: import_zod10.z.array(import_zod10.z.string()).optional(),
1117
+ options: import_zod10.z.record(import_zod10.z.unknown()).optional(),
1118
+ displayOptions: import_zod10.z.record(import_zod10.z.unknown()).optional(),
1119
+ conditions: import_zod10.z.array(import_zod10.z.unknown()).optional(),
1120
+ required: import_zod10.z.boolean().optional().default(false),
1121
+ readonly: import_zod10.z.boolean().optional().default(false),
1122
+ hidden: import_zod10.z.boolean().optional().default(false),
1123
+ encrypted: import_zod10.z.boolean().optional().default(false),
1124
+ versioned: import_zod10.z.boolean().optional().default(false),
1125
+ width: import_zod10.z.enum(["half", "full", "fill"]).optional().default("full"),
1126
+ group: import_zod10.z.string().optional(),
1127
+ sortOrder: import_zod10.z.number().int().optional(),
1128
+ renameFrom: fieldNameSchema.optional().describe("Previous field name if this is a rename operation"),
1129
+ confirmRiskyChange: import_zod10.z.boolean().optional().describe("Set true to confirm type-change or destructive migration")
1115
1130
  });
1116
1131
  function formatError3(err) {
1117
1132
  if (err instanceof LumiBaseApiError) {
@@ -1125,12 +1140,12 @@ function registerFieldTools(server, client) {
1125
1140
  {
1126
1141
  description: "List all fields in a collection, including system fields.",
1127
1142
  inputSchema: {
1128
- collection: import_zod9.z.string().min(1)
1143
+ collection: collectionNameSchema
1129
1144
  }
1130
1145
  },
1131
1146
  async ({ collection }) => {
1132
1147
  try {
1133
- const data = await client.get(`/collections/${collection}/fields`);
1148
+ const data = await client.get(`/collections/${encodePathSegment(collection)}/fields`);
1134
1149
  return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
1135
1150
  } catch (err) {
1136
1151
  return { content: [{ type: "text", text: `Error: ${formatError3(err)}` }], isError: true };
@@ -1142,15 +1157,15 @@ function registerFieldTools(server, client) {
1142
1157
  {
1143
1158
  description: 'Create or update a field in a collection. field_name must be lowercase snake_case (e.g. "published_at"). Common types: string (varchar), text (longtext), integer, boolean, dateTime, json, uuid. Common interfaces: input, textarea, datetime, toggle, select, file, markdown.',
1144
1159
  inputSchema: {
1145
- collection: import_zod9.z.string().min(1),
1146
- field_name: import_zod9.z.string().regex(namePattern, "Must be lowercase snake_case, start with a letter").describe("Machine name of the field"),
1160
+ collection: collectionNameSchema,
1161
+ field_name: fieldNameSchema.describe("Machine name of the field"),
1147
1162
  ...fieldInputSchema2.shape
1148
1163
  }
1149
1164
  },
1150
1165
  async ({ collection, field_name, ...fieldInput }) => {
1151
1166
  try {
1152
1167
  const data = await client.put(
1153
- `/collections/${collection}/fields/${field_name}`,
1168
+ `/collections/${encodePathSegment(collection)}/fields/${encodePathSegment(field_name)}`,
1154
1169
  fieldInput
1155
1170
  );
1156
1171
  return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
@@ -1164,16 +1179,18 @@ function registerFieldTools(server, client) {
1164
1179
  {
1165
1180
  description: "Delete a field from a collection. Data stored in this field will be lost. Pass confirm=true to confirm the destructive operation.",
1166
1181
  inputSchema: {
1167
- collection: import_zod9.z.string().min(1),
1168
- field_name: import_zod9.z.string().min(1),
1169
- confirm: import_zod9.z.literal(true).describe("Must be true to confirm destructive operation"),
1170
- force: import_zod9.z.boolean().optional().describe("Force deletion even if risky (foreign keys, etc.)")
1182
+ collection: collectionNameSchema,
1183
+ field_name: fieldNameSchema,
1184
+ confirm: import_zod10.z.literal(true).describe("Must be true to confirm destructive operation"),
1185
+ force: import_zod10.z.boolean().optional().describe("Force deletion even if risky (foreign keys, etc.)")
1171
1186
  }
1172
1187
  },
1173
1188
  async ({ collection, field_name, force }) => {
1174
1189
  try {
1175
1190
  const qs = force ? "?force=true" : "";
1176
- await client.delete(`/collections/${collection}/fields/${field_name}${qs}`);
1191
+ await client.delete(
1192
+ `/collections/${encodePathSegment(collection)}/fields/${encodePathSegment(field_name)}${qs}`
1193
+ );
1177
1194
  return {
1178
1195
  content: [{ type: "text", text: `Field "${field_name}" deleted from "${collection}".` }]
1179
1196
  };
@@ -1185,7 +1202,7 @@ function registerFieldTools(server, client) {
1185
1202
  }
1186
1203
 
1187
1204
  // src/tools/items.ts
1188
- var import_zod10 = require("zod");
1205
+ var import_zod11 = require("zod");
1189
1206
  function formatError4(err) {
1190
1207
  if (err instanceof LumiBaseApiError) {
1191
1208
  return err.errors.map((e) => `[${e.code}] ${e.message}`).join("; ");
@@ -1206,19 +1223,19 @@ function registerItemTools(server, client) {
1206
1223
  {
1207
1224
  description: "List items from a collection with optional filtering, sorting, and pagination.",
1208
1225
  inputSchema: {
1209
- collection: import_zod10.z.string().min(1),
1210
- limit: import_zod10.z.number().int().min(1).max(200).optional().default(25),
1211
- offset: import_zod10.z.number().int().min(0).optional().default(0),
1212
- status: import_zod10.z.enum(["draft", "published", "archived"]).optional(),
1213
- sort: import_zod10.z.string().optional().describe('Comma-separated field names; prefix with - for descending (e.g. "-created_at")'),
1214
- fields: import_zod10.z.string().optional().describe('Comma-separated field names to return (e.g. "id,title,status")'),
1215
- search: import_zod10.z.string().optional().describe("Full-text search across searchable fields")
1226
+ collection: collectionNameSchema,
1227
+ limit: import_zod11.z.number().int().min(1).max(200).optional().default(25),
1228
+ offset: import_zod11.z.number().int().min(0).optional().default(0),
1229
+ status: import_zod11.z.enum(["draft", "published", "archived"]).optional(),
1230
+ sort: import_zod11.z.string().optional().describe('Comma-separated field names; prefix with - for descending (e.g. "-created_at")'),
1231
+ fields: import_zod11.z.string().optional().describe('Comma-separated field names to return (e.g. "id,title,status")'),
1232
+ search: import_zod11.z.string().optional().describe("Full-text search across searchable fields")
1216
1233
  }
1217
1234
  },
1218
1235
  async ({ collection, ...params }) => {
1219
1236
  try {
1220
1237
  const qs = buildQs2(params);
1221
- const data = await client.get(`/items/${collection}${qs}`);
1238
+ const data = await client.get(`/items/${encodePathSegment(collection)}${qs}`);
1222
1239
  return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
1223
1240
  } catch (err) {
1224
1241
  return { content: [{ type: "text", text: `Error: ${formatError4(err)}` }], isError: true };
@@ -1230,15 +1247,17 @@ function registerItemTools(server, client) {
1230
1247
  {
1231
1248
  description: "Get a single item by ID from a collection.",
1232
1249
  inputSchema: {
1233
- collection: import_zod10.z.string().min(1),
1234
- id: import_zod10.z.string().min(1),
1235
- fields: import_zod10.z.string().optional().describe("Comma-separated field names to return")
1250
+ collection: collectionNameSchema,
1251
+ id: idPathSegmentSchema,
1252
+ fields: import_zod11.z.string().optional().describe("Comma-separated field names to return")
1236
1253
  }
1237
1254
  },
1238
1255
  async ({ collection, id, fields }) => {
1239
1256
  try {
1240
1257
  const qs = buildQs2({ fields });
1241
- const data = await client.get(`/items/${collection}/${id}${qs}`);
1258
+ const data = await client.get(
1259
+ `/items/${encodePathSegment(collection)}/${encodePathSegment(id)}${qs}`
1260
+ );
1242
1261
  return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
1243
1262
  } catch (err) {
1244
1263
  return { content: [{ type: "text", text: `Error: ${formatError4(err)}` }], isError: true };
@@ -1250,14 +1269,14 @@ function registerItemTools(server, client) {
1250
1269
  {
1251
1270
  description: "Create a new item in a collection.",
1252
1271
  inputSchema: {
1253
- collection: import_zod10.z.string().min(1),
1254
- data: import_zod10.z.record(import_zod10.z.unknown()).describe("Field values for the new item"),
1255
- status: import_zod10.z.enum(["draft", "published"]).optional().default("draft")
1272
+ collection: collectionNameSchema,
1273
+ data: import_zod11.z.record(import_zod11.z.unknown()).describe("Field values for the new item"),
1274
+ status: import_zod11.z.enum(["draft", "published"]).optional().default("draft")
1256
1275
  }
1257
1276
  },
1258
1277
  async ({ collection, data: itemData, status }) => {
1259
1278
  try {
1260
- const data = await client.post(`/items/${collection}`, {
1279
+ const data = await client.post(`/items/${encodePathSegment(collection)}`, {
1261
1280
  ...itemData,
1262
1281
  status
1263
1282
  });
@@ -1272,14 +1291,17 @@ function registerItemTools(server, client) {
1272
1291
  {
1273
1292
  description: "Partially update an item (PATCH \u2014 only provided fields are changed).",
1274
1293
  inputSchema: {
1275
- collection: import_zod10.z.string().min(1),
1276
- id: import_zod10.z.string().min(1),
1277
- data: import_zod10.z.record(import_zod10.z.unknown()).describe("Fields to update")
1294
+ collection: collectionNameSchema,
1295
+ id: idPathSegmentSchema,
1296
+ data: import_zod11.z.record(import_zod11.z.unknown()).describe("Fields to update")
1278
1297
  }
1279
1298
  },
1280
1299
  async ({ collection, id, data: itemData }) => {
1281
1300
  try {
1282
- const data = await client.patch(`/items/${collection}/${id}`, itemData);
1301
+ const data = await client.patch(
1302
+ `/items/${encodePathSegment(collection)}/${encodePathSegment(id)}`,
1303
+ itemData
1304
+ );
1283
1305
  return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
1284
1306
  } catch (err) {
1285
1307
  return { content: [{ type: "text", text: `Error: ${formatError4(err)}` }], isError: true };
@@ -1291,14 +1313,14 @@ function registerItemTools(server, client) {
1291
1313
  {
1292
1314
  description: "Soft-delete an item (sets deleted_at, recoverable). Pass confirm=true.",
1293
1315
  inputSchema: {
1294
- collection: import_zod10.z.string().min(1),
1295
- id: import_zod10.z.string().min(1),
1296
- confirm: import_zod10.z.literal(true).describe("Must be true to confirm deletion")
1316
+ collection: collectionNameSchema,
1317
+ id: idPathSegmentSchema,
1318
+ confirm: import_zod11.z.literal(true).describe("Must be true to confirm deletion")
1297
1319
  }
1298
1320
  },
1299
1321
  async ({ collection, id }) => {
1300
1322
  try {
1301
- await client.delete(`/items/${collection}/${id}`);
1323
+ await client.delete(`/items/${encodePathSegment(collection)}/${encodePathSegment(id)}`);
1302
1324
  return { content: [{ type: "text", text: `Item "${id}" deleted from "${collection}".` }] };
1303
1325
  } catch (err) {
1304
1326
  return { content: [{ type: "text", text: `Error: ${formatError4(err)}` }], isError: true };
@@ -1308,15 +1330,15 @@ function registerItemTools(server, client) {
1308
1330
  }
1309
1331
 
1310
1332
  // src/tools/ops.ts
1311
- var import_zod11 = require("zod");
1333
+ var import_zod12 = require("zod");
1312
1334
  function registerOpsTools(server, client) {
1313
1335
  server.registerTool(
1314
1336
  "list_activity",
1315
1337
  {
1316
1338
  description: "List the site activity / audit trail (most recent first).",
1317
1339
  inputSchema: {
1318
- limit: import_zod11.z.number().int().min(1).max(500).optional(),
1319
- offset: import_zod11.z.number().int().min(0).optional()
1340
+ limit: import_zod12.z.number().int().min(1).max(500).optional(),
1341
+ offset: import_zod12.z.number().int().min(0).optional()
1320
1342
  }
1321
1343
  },
1322
1344
  async (args) => run(
@@ -1338,7 +1360,7 @@ function registerOpsTools(server, client) {
1338
1360
  }
1339
1361
 
1340
1362
  // src/tools/permissions.ts
1341
- var import_zod12 = require("zod");
1363
+ var import_zod13 = require("zod");
1342
1364
  function registerPermissionTools(server, client) {
1343
1365
  server.registerTool(
1344
1366
  "get_my_permissions",
@@ -1353,9 +1375,9 @@ function registerPermissionTools(server, client) {
1353
1375
  {
1354
1376
  description: "Evaluate whether the current principal may perform an action on a collection (optionally against a specific item), returning { allowed, reason, fields }.",
1355
1377
  inputSchema: {
1356
- collection: import_zod12.z.string().min(1),
1357
- action: import_zod12.z.enum(["create", "read", "update", "delete", "share"]),
1358
- item: import_zod12.z.record(import_zod12.z.unknown()).optional().describe("Item payload to evaluate row-level rules against.")
1378
+ collection: import_zod13.z.string().min(1),
1379
+ action: import_zod13.z.enum(["create", "read", "update", "delete", "share"]),
1380
+ item: import_zod13.z.record(import_zod13.z.unknown()).optional().describe("Item payload to evaluate row-level rules against.")
1359
1381
  }
1360
1382
  },
1361
1383
  async (input) => run(() => client.post("/permissions/check", input))
@@ -1363,21 +1385,21 @@ function registerPermissionTools(server, client) {
1363
1385
  }
1364
1386
 
1365
1387
  // src/tools/relations.ts
1366
- var import_zod13 = require("zod");
1388
+ var import_zod14 = require("zod");
1367
1389
  var relationInputSchema = {
1368
- manyCollection: import_zod13.z.string().min(1).describe('Collection that holds the foreign key (the "many" side).'),
1369
- manyField: import_zod13.z.string().min(1).describe("Field on manyCollection that stores the relation."),
1370
- oneCollection: import_zod13.z.string().min(1).describe('Related collection (the "one" side).'),
1371
- oneField: import_zod13.z.string().nullable().optional(),
1372
- junctionCollection: import_zod13.z.string().nullable().optional().describe("Junction table for m2m relations."),
1373
- type: import_zod13.z.enum(["m2o", "o2m", "m2m", "m2a"]).optional(),
1374
- aliasField: import_zod13.z.string().nullable().optional(),
1375
- relatedDisplayTemplate: import_zod13.z.string().nullable().optional(),
1376
- junctionManyField: import_zod13.z.string().nullable().optional(),
1377
- junctionOneField: import_zod13.z.string().nullable().optional(),
1378
- sortField: import_zod13.z.string().nullable().optional(),
1379
- onDelete: import_zod13.z.enum(["restrict", "cascade", "set null", "no action"]).optional(),
1380
- meta: import_zod13.z.record(import_zod13.z.unknown()).optional()
1390
+ manyCollection: import_zod14.z.string().min(1).describe('Collection that holds the foreign key (the "many" side).'),
1391
+ manyField: import_zod14.z.string().min(1).describe("Field on manyCollection that stores the relation."),
1392
+ oneCollection: import_zod14.z.string().min(1).describe('Related collection (the "one" side).'),
1393
+ oneField: import_zod14.z.string().nullable().optional(),
1394
+ junctionCollection: import_zod14.z.string().nullable().optional().describe("Junction table for m2m relations."),
1395
+ type: import_zod14.z.enum(["m2o", "o2m", "m2m", "m2a"]).optional(),
1396
+ aliasField: import_zod14.z.string().nullable().optional(),
1397
+ relatedDisplayTemplate: import_zod14.z.string().nullable().optional(),
1398
+ junctionManyField: import_zod14.z.string().nullable().optional(),
1399
+ junctionOneField: import_zod14.z.string().nullable().optional(),
1400
+ sortField: import_zod14.z.string().nullable().optional(),
1401
+ onDelete: import_zod14.z.enum(["restrict", "cascade", "set null", "no action"]).optional(),
1402
+ meta: import_zod14.z.record(import_zod14.z.unknown()).optional()
1381
1403
  };
1382
1404
  function registerRelationTools(server, client) {
1383
1405
  server.registerTool(
@@ -1398,31 +1420,31 @@ function registerRelationTools(server, client) {
1398
1420
  {
1399
1421
  description: "Delete a relation by id. DESTRUCTIVE \u2014 warn the user first and pass confirm=true.",
1400
1422
  inputSchema: {
1401
- id: import_zod13.z.string().min(1),
1402
- confirm: import_zod13.z.literal(true).describe(confirmDescription)
1423
+ id: idPathSegmentSchema,
1424
+ confirm: import_zod14.z.literal(true).describe(confirmDescription)
1403
1425
  }
1404
1426
  },
1405
1427
  async ({ id }) => run(async () => {
1406
- await client.delete(`/relations/${id}`);
1428
+ await client.delete(`/relations/${encodePathSegment(id)}`);
1407
1429
  return okText(`Relation "${id}" deleted.`);
1408
1430
  })
1409
1431
  );
1410
1432
  }
1411
1433
 
1412
1434
  // src/tools/search-media.ts
1413
- var import_zod14 = require("zod");
1435
+ var import_zod15 = require("zod");
1414
1436
  function registerSearchMediaTools(server, client) {
1415
1437
  server.registerTool(
1416
1438
  "search",
1417
1439
  {
1418
1440
  description: "Full-text search within a collection. Returns ranked hits from the search backend. The `collection` parameter is required.",
1419
1441
  inputSchema: {
1420
- q: import_zod14.z.string().min(1).describe("Query string."),
1421
- collection: import_zod14.z.string().min(1).describe("Collection to search."),
1422
- filter: import_zod14.z.string().optional().describe("Backend filter expression."),
1423
- sort: import_zod14.z.string().optional().describe("Comma-separated sort fields."),
1424
- limit: import_zod14.z.number().int().min(1).max(200).optional(),
1425
- offset: import_zod14.z.number().int().min(0).optional()
1442
+ q: import_zod15.z.string().min(1).describe("Query string."),
1443
+ collection: import_zod15.z.string().min(1).describe("Collection to search."),
1444
+ filter: import_zod15.z.string().optional().describe("Backend filter expression."),
1445
+ sort: import_zod15.z.string().optional().describe("Comma-separated sort fields."),
1446
+ limit: import_zod15.z.number().int().min(1).max(200).optional(),
1447
+ offset: import_zod15.z.number().int().min(0).optional()
1426
1448
  }
1427
1449
  },
1428
1450
  async (args) => run(
@@ -1435,7 +1457,7 @@ function registerSearchMediaTools(server, client) {
1435
1457
  "list_media",
1436
1458
  {
1437
1459
  description: "List media asset keys, optionally filtered by key prefix.",
1438
- inputSchema: { prefix: import_zod14.z.string().optional() }
1460
+ inputSchema: { prefix: import_zod15.z.string().optional() }
1439
1461
  },
1440
1462
  async ({ prefix }) => run(() => client.get(`/media${prefix ? `?prefix=${encodeURIComponent(prefix)}` : ""}`))
1441
1463
  );
@@ -1444,27 +1466,27 @@ function registerSearchMediaTools(server, client) {
1444
1466
  {
1445
1467
  description: "Delete a media asset by key. DESTRUCTIVE \u2014 warn the user first and pass confirm=true.",
1446
1468
  inputSchema: {
1447
- key: import_zod14.z.string().min(1).describe("Full storage key of the asset."),
1448
- confirm: import_zod14.z.literal(true).describe(confirmDescription)
1469
+ key: mediaKeySchema.describe("Full storage key of the asset."),
1470
+ confirm: import_zod15.z.literal(true).describe(confirmDescription)
1449
1471
  }
1450
1472
  },
1451
1473
  async ({ key }) => run(async () => {
1452
- await client.delete(`/media/${key}`);
1474
+ await client.delete(`/media/${encodeMediaKey(key)}`);
1453
1475
  return okText(`Media asset "${key}" deleted.`);
1454
1476
  })
1455
1477
  );
1456
1478
  }
1457
1479
 
1458
1480
  // src/tools/translation-memory.ts
1459
- var import_zod15 = require("zod");
1481
+ var import_zod16 = require("zod");
1460
1482
  function registerTranslationMemoryTools(server, client) {
1461
1483
  server.registerTool(
1462
1484
  "list_tm",
1463
1485
  {
1464
1486
  description: "List translation-memory entries, optionally filtered by source/target language.",
1465
1487
  inputSchema: {
1466
- source: import_zod15.z.string().optional().describe("Source language code."),
1467
- target: import_zod15.z.string().optional().describe("Target language code.")
1488
+ source: import_zod16.z.string().optional().describe("Source language code."),
1489
+ target: import_zod16.z.string().optional().describe("Target language code.")
1468
1490
  }
1469
1491
  },
1470
1492
  async (args) => run(
@@ -1476,14 +1498,14 @@ function registerTranslationMemoryTools(server, client) {
1476
1498
  {
1477
1499
  description: "Add or update a translation-memory entry.",
1478
1500
  inputSchema: {
1479
- sourceLang: import_zod15.z.string().min(2),
1480
- targetLang: import_zod15.z.string().min(2),
1481
- sourceText: import_zod15.z.string().min(1),
1482
- targetText: import_zod15.z.string().min(1),
1483
- context: import_zod15.z.string().optional(),
1484
- quality: import_zod15.z.number().min(0).max(100).optional(),
1485
- source: import_zod15.z.enum(["human", "mt", "imported"]).optional(),
1486
- provider: import_zod15.z.string().optional()
1501
+ sourceLang: import_zod16.z.string().min(2),
1502
+ targetLang: import_zod16.z.string().min(2),
1503
+ sourceText: import_zod16.z.string().min(1),
1504
+ targetText: import_zod16.z.string().min(1),
1505
+ context: import_zod16.z.string().optional(),
1506
+ quality: import_zod16.z.number().min(0).max(100).optional(),
1507
+ source: import_zod16.z.enum(["human", "mt", "imported"]).optional(),
1508
+ provider: import_zod16.z.string().optional()
1487
1509
  }
1488
1510
  },
1489
1511
  async (input) => run(() => client.post("/tm", input))
@@ -1493,10 +1515,10 @@ function registerTranslationMemoryTools(server, client) {
1493
1515
  {
1494
1516
  description: "Fuzzy-match a query string against translation memory for a language pair.",
1495
1517
  inputSchema: {
1496
- query: import_zod15.z.string().min(1),
1497
- sourceLang: import_zod15.z.string().min(2),
1498
- targetLang: import_zod15.z.string().min(2),
1499
- threshold: import_zod15.z.number().min(0).max(100).optional().describe("Minimum match score (default 75).")
1518
+ query: import_zod16.z.string().min(1),
1519
+ sourceLang: import_zod16.z.string().min(2),
1520
+ targetLang: import_zod16.z.string().min(2),
1521
+ threshold: import_zod16.z.number().min(0).max(100).optional().describe("Minimum match score (default 75).")
1500
1522
  }
1501
1523
  },
1502
1524
  async (input) => run(() => client.post("/tm/lookup", input))
@@ -1506,10 +1528,10 @@ function registerTranslationMemoryTools(server, client) {
1506
1528
  {
1507
1529
  description: "Run the full translation pipeline (TM + glossary + MT provider) for a text.",
1508
1530
  inputSchema: {
1509
- text: import_zod15.z.string().min(1),
1510
- from: import_zod15.z.string().min(2),
1511
- to: import_zod15.z.string().min(2),
1512
- provider: import_zod15.z.string().optional()
1531
+ text: import_zod16.z.string().min(1),
1532
+ from: import_zod16.z.string().min(2),
1533
+ to: import_zod16.z.string().min(2),
1534
+ provider: import_zod16.z.string().optional()
1513
1535
  }
1514
1536
  },
1515
1537
  async (input) => run(() => client.post("/tm/translate", input))
@@ -1517,7 +1539,7 @@ function registerTranslationMemoryTools(server, client) {
1517
1539
  }
1518
1540
 
1519
1541
  // src/tools/users-teams.ts
1520
- var import_zod16 = require("zod");
1542
+ var import_zod17 = require("zod");
1521
1543
  function registerUsersTeamsTools(server, client) {
1522
1544
  server.registerTool(
1523
1545
  "list_users",
@@ -1526,16 +1548,16 @@ function registerUsersTeamsTools(server, client) {
1526
1548
  );
1527
1549
  server.registerTool(
1528
1550
  "get_user",
1529
- { description: "Get a single user in the active site by id.", inputSchema: { id: import_zod16.z.string().min(1) } },
1530
- async ({ id }) => run(() => client.get(`/users/${id}`))
1551
+ { description: "Get a single user in the active site by id.", inputSchema: { id: idPathSegmentSchema } },
1552
+ async ({ id }) => run(() => client.get(`/users/${encodePathSegment(id)}`))
1531
1553
  );
1532
1554
  server.registerTool(
1533
1555
  "invite_user",
1534
1556
  {
1535
1557
  description: "Invite a user to the site by email, optionally assigning a role. Sends an invite email.",
1536
1558
  inputSchema: {
1537
- email: import_zod16.z.string().email(),
1538
- roleId: import_zod16.z.string().optional()
1559
+ email: import_zod17.z.string().email(),
1560
+ roleId: import_zod17.z.string().optional()
1539
1561
  }
1540
1562
  },
1541
1563
  async (input) => run(() => client.post("/users/invite", input))
@@ -1545,21 +1567,21 @@ function registerUsersTeamsTools(server, client) {
1545
1567
  {
1546
1568
  description: "Update a user's site membership (role and/or status).",
1547
1569
  inputSchema: {
1548
- id: import_zod16.z.string().min(1),
1549
- roleId: import_zod16.z.string().nullable().optional(),
1550
- status: import_zod16.z.string().optional().describe("e.g. active, suspended.")
1570
+ id: idPathSegmentSchema,
1571
+ roleId: import_zod17.z.string().nullable().optional(),
1572
+ status: import_zod17.z.string().optional().describe("e.g. active, suspended.")
1551
1573
  }
1552
1574
  },
1553
- async ({ id, ...patch }) => run(() => client.patch(`/users/${id}`, patch))
1575
+ async ({ id, ...patch }) => run(() => client.patch(`/users/${encodePathSegment(id)}`, patch))
1554
1576
  );
1555
1577
  server.registerTool(
1556
1578
  "remove_user",
1557
1579
  {
1558
1580
  description: "Remove a user from the site. DESTRUCTIVE \u2014 pass confirm=true.",
1559
- inputSchema: { id: import_zod16.z.string().min(1), confirm: import_zod16.z.literal(true).describe(confirmDescription) }
1581
+ inputSchema: { id: idPathSegmentSchema, confirm: import_zod17.z.literal(true).describe(confirmDescription) }
1560
1582
  },
1561
1583
  async ({ id }) => run(async () => {
1562
- await client.delete(`/users/${id}`);
1584
+ await client.delete(`/users/${encodePathSegment(id)}`);
1563
1585
  return okText(`User "${id}" removed from the site.`);
1564
1586
  })
1565
1587
  );
@@ -1570,14 +1592,14 @@ function registerUsersTeamsTools(server, client) {
1570
1592
  );
1571
1593
  server.registerTool(
1572
1594
  "get_team",
1573
- { description: "Get a single team by id.", inputSchema: { id: import_zod16.z.string().min(1) } },
1574
- async ({ id }) => run(() => client.get(`/teams/${id}`))
1595
+ { description: "Get a single team by id.", inputSchema: { id: idPathSegmentSchema } },
1596
+ async ({ id }) => run(() => client.get(`/teams/${encodePathSegment(id)}`))
1575
1597
  );
1576
1598
  server.registerTool(
1577
1599
  "create_team",
1578
1600
  {
1579
1601
  description: "Create a team.",
1580
- inputSchema: { name: import_zod16.z.string().min(1).max(128), description: import_zod16.z.string().nullable().optional() }
1602
+ inputSchema: { name: import_zod17.z.string().min(1).max(128), description: import_zod17.z.string().nullable().optional() }
1581
1603
  },
1582
1604
  async (input) => run(() => client.post("/teams", input))
1583
1605
  );
@@ -1586,64 +1608,64 @@ function registerUsersTeamsTools(server, client) {
1586
1608
  {
1587
1609
  description: "Update a team (partial PATCH).",
1588
1610
  inputSchema: {
1589
- id: import_zod16.z.string().min(1),
1590
- name: import_zod16.z.string().min(1).max(128).optional(),
1591
- description: import_zod16.z.string().nullable().optional()
1611
+ id: idPathSegmentSchema,
1612
+ name: import_zod17.z.string().min(1).max(128).optional(),
1613
+ description: import_zod17.z.string().nullable().optional()
1592
1614
  }
1593
1615
  },
1594
- async ({ id, ...patch }) => run(() => client.patch(`/teams/${id}`, patch))
1616
+ async ({ id, ...patch }) => run(() => client.patch(`/teams/${encodePathSegment(id)}`, patch))
1595
1617
  );
1596
1618
  server.registerTool(
1597
1619
  "delete_team",
1598
1620
  {
1599
1621
  description: "Delete a team. DESTRUCTIVE \u2014 pass confirm=true.",
1600
- inputSchema: { id: import_zod16.z.string().min(1), confirm: import_zod16.z.literal(true).describe(confirmDescription) }
1622
+ inputSchema: { id: idPathSegmentSchema, confirm: import_zod17.z.literal(true).describe(confirmDescription) }
1601
1623
  },
1602
1624
  async ({ id }) => run(async () => {
1603
- await client.delete(`/teams/${id}`);
1625
+ await client.delete(`/teams/${encodePathSegment(id)}`);
1604
1626
  return okText(`Team "${id}" deleted.`);
1605
1627
  })
1606
1628
  );
1607
1629
  server.registerTool(
1608
1630
  "list_team_members",
1609
- { description: "List members of a team.", inputSchema: { id: import_zod16.z.string().min(1).describe("Team id.") } },
1610
- async ({ id }) => run(() => client.get(`/teams/${id}/members`))
1631
+ { description: "List members of a team.", inputSchema: { id: idPathSegmentSchema.describe("Team id.") } },
1632
+ async ({ id }) => run(() => client.get(`/teams/${encodePathSegment(id)}/members`))
1611
1633
  );
1612
1634
  server.registerTool(
1613
1635
  "add_team_member",
1614
1636
  {
1615
1637
  description: "Add a user to a team.",
1616
- inputSchema: { id: import_zod16.z.string().min(1).describe("Team id."), userId: import_zod16.z.string().min(1) }
1638
+ inputSchema: { id: idPathSegmentSchema.describe("Team id."), userId: idPathSegmentSchema }
1617
1639
  },
1618
- async ({ id, userId }) => run(() => client.post(`/teams/${id}/members`, { userId }))
1640
+ async ({ id, userId }) => run(() => client.post(`/teams/${encodePathSegment(id)}/members`, { userId }))
1619
1641
  );
1620
1642
  server.registerTool(
1621
1643
  "remove_team_member",
1622
1644
  {
1623
1645
  description: "Remove a user from a team. DESTRUCTIVE \u2014 pass confirm=true.",
1624
1646
  inputSchema: {
1625
- id: import_zod16.z.string().min(1).describe("Team id."),
1626
- userId: import_zod16.z.string().min(1),
1627
- confirm: import_zod16.z.literal(true).describe(confirmDescription)
1647
+ id: idPathSegmentSchema.describe("Team id."),
1648
+ userId: idPathSegmentSchema,
1649
+ confirm: import_zod17.z.literal(true).describe(confirmDescription)
1628
1650
  }
1629
1651
  },
1630
1652
  async ({ id, userId }) => run(async () => {
1631
- await client.delete(`/teams/${id}/members/${userId}`);
1653
+ await client.delete(`/teams/${encodePathSegment(id)}/members/${encodePathSegment(userId)}`);
1632
1654
  return okText(`User "${userId}" removed from team "${id}".`);
1633
1655
  })
1634
1656
  );
1635
1657
  }
1636
1658
 
1637
1659
  // src/tools/webhooks.ts
1638
- var import_zod17 = require("zod");
1639
- var webhookSchema = import_zod17.z.object({
1640
- name: import_zod17.z.string().min(1).max(255),
1641
- url: import_zod17.z.string().url(),
1642
- actions: import_zod17.z.array(import_zod17.z.string()).optional().describe("Item events that trigger the webhook (e.g. create, update, delete)."),
1643
- collections: import_zod17.z.array(import_zod17.z.string()).optional().describe("Collections to filter on (empty = all)."),
1644
- headers: import_zod17.z.record(import_zod17.z.string()).optional(),
1645
- status: import_zod17.z.enum(["active", "inactive"]).optional(),
1646
- secret: import_zod17.z.string().nullable().optional()
1660
+ var import_zod18 = require("zod");
1661
+ var webhookSchema = import_zod18.z.object({
1662
+ name: import_zod18.z.string().min(1).max(255),
1663
+ url: import_zod18.z.string().url(),
1664
+ actions: import_zod18.z.array(import_zod18.z.string()).optional().describe("Item events that trigger the webhook (e.g. create, update, delete)."),
1665
+ collections: import_zod18.z.array(import_zod18.z.string()).optional().describe("Collections to filter on (empty = all)."),
1666
+ headers: import_zod18.z.record(import_zod18.z.string()).optional(),
1667
+ status: import_zod18.z.enum(["active", "inactive"]).optional(),
1668
+ secret: import_zod18.z.string().nullable().optional()
1647
1669
  });
1648
1670
  function registerWebhookTools(server, client) {
1649
1671
  registerCrud(server, client, {