@contentful/mcp-tools 0.4.5 → 0.8.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.d.ts +139 -16
  2. package/dist/index.js +1222 -529
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -81,6 +81,13 @@ function createClientConfig(config) {
81
81
  };
82
82
  return clientConfig;
83
83
  }
84
+ function assertEnvironmentNotProtected(environmentId, protectedEnvironments) {
85
+ if (protectedEnvironments && protectedEnvironments.includes(environmentId)) {
86
+ throw new Error(
87
+ `Environment '${environmentId}' is protected. Write and delete operations are not allowed.`
88
+ );
89
+ }
90
+ }
84
91
 
85
92
  // src/utils/ai-actions.ts
86
93
  import { z as z2 } from "zod";
@@ -171,13 +178,18 @@ var CreateAiActionToolParams = BaseToolSchema.extend({
171
178
  });
172
179
  function createAiActionTool(config) {
173
180
  async function tool2(args) {
181
+ const resolvedEnvironmentId = args.environmentId || "master";
182
+ assertEnvironmentNotProtected(
183
+ resolvedEnvironmentId,
184
+ config.protectedEnvironments
185
+ );
174
186
  const params = {
175
187
  spaceId: args.spaceId,
176
- environmentId: args.environmentId || "master"
188
+ environmentId: resolvedEnvironmentId
177
189
  };
178
190
  const contentfulClient = createToolClient(config, {
179
191
  ...args,
180
- environmentId: args.environmentId || "master"
192
+ environmentId: resolvedEnvironmentId
181
193
  });
182
194
  const aiAction = await contentfulClient.aiAction.create(params, {
183
195
  name: args.name,
@@ -186,7 +198,9 @@ function createAiActionTool(config) {
186
198
  configuration: args.configuration,
187
199
  testCases: args.testCases
188
200
  });
189
- return createSuccessResponse("AI action created successfully", { aiAction });
201
+ return createSuccessResponse("AI action created successfully", {
202
+ aiAction
203
+ });
190
204
  }
191
205
  return withErrorHandling(tool2, "Error creating AI action");
192
206
  }
@@ -305,11 +319,49 @@ function getAiActionInvocationTool(config) {
305
319
 
306
320
  // src/tools/ai-actions/deleteAiAction.ts
307
321
  import { z as z7 } from "zod";
322
+
323
+ // src/utils/confirmation.ts
324
+ import { createHash } from "crypto";
325
+ var CONFIRMATION_MESSAGE_PREFIX = "Confirmation required to delete";
326
+ function buildConfirmToken(resource, id, version) {
327
+ const payload = `${resource}:${id}:${version ?? ""}`;
328
+ return createHash("sha256").update(payload).digest("hex").slice(0, 16);
329
+ }
330
+ var RESOURCE_DISPLAY_NAME = {
331
+ entry: "entry",
332
+ environment: "environment",
333
+ contentType: "content type",
334
+ asset: "asset",
335
+ aiAction: "AI action",
336
+ locale: "locale",
337
+ concept: "concept",
338
+ conceptScheme: "concept scheme"
339
+ };
340
+ function buildConfirmationPreview(resource, id, details, confirmToken) {
341
+ const displayName = RESOURCE_DISPLAY_NAME[resource];
342
+ return {
343
+ preview: details,
344
+ confirmToken,
345
+ instructions: `This will permanently delete ${displayName} "${id}". This action cannot be undone. To proceed, call this tool again with confirm: true and confirmToken: "${confirmToken}".`
346
+ };
347
+ }
348
+
349
+ // src/tools/ai-actions/deleteAiAction.ts
308
350
  var DeleteAiActionToolParams = BaseToolSchema.extend({
309
- aiActionId: z7.string().describe("The ID of the AI action to delete")
351
+ aiActionId: z7.string().describe("The ID of the AI action to delete"),
352
+ confirm: z7.boolean().optional().describe(
353
+ "Set to true on the second call to actually perform the deletion. Required together with confirmToken."
354
+ ),
355
+ confirmToken: z7.string().optional().describe(
356
+ "Token returned by the preview call; must be supplied with confirm: true."
357
+ )
310
358
  });
311
359
  function deleteAiActionTool(config) {
312
360
  async function tool2(args) {
361
+ assertEnvironmentNotProtected(
362
+ args.environmentId,
363
+ config.protectedEnvironments
364
+ );
313
365
  const params = {
314
366
  spaceId: args.spaceId,
315
367
  environmentId: args.environmentId,
@@ -317,8 +369,26 @@ function deleteAiActionTool(config) {
317
369
  };
318
370
  const contentfulClient = createToolClient(config, args);
319
371
  const aiAction = await contentfulClient.aiAction.get(params);
372
+ const expectedToken = buildConfirmToken(
373
+ "aiAction",
374
+ args.aiActionId,
375
+ aiAction.sys.version
376
+ );
377
+ if (args.confirm !== true || args.confirmToken !== expectedToken) {
378
+ return createSuccessResponse(
379
+ `${CONFIRMATION_MESSAGE_PREFIX} AI action`,
380
+ buildConfirmationPreview(
381
+ "aiAction",
382
+ args.aiActionId,
383
+ { aiAction },
384
+ expectedToken
385
+ )
386
+ );
387
+ }
320
388
  await contentfulClient.aiAction.delete(params);
321
- return createSuccessResponse("AI action deleted successfully", { aiAction });
389
+ return createSuccessResponse("AI action deleted successfully", {
390
+ aiAction
391
+ });
322
392
  }
323
393
  return withErrorHandling(tool2, "Error deleting AI action");
324
394
  }
@@ -452,6 +522,10 @@ var PublishAiActionToolParams = BaseToolSchema.extend({
452
522
  });
453
523
  function publishAiActionTool(config) {
454
524
  async function tool2(args) {
525
+ assertEnvironmentNotProtected(
526
+ args.environmentId,
527
+ config.protectedEnvironments
528
+ );
455
529
  const params = {
456
530
  spaceId: args.spaceId,
457
531
  environmentId: args.environmentId,
@@ -488,6 +562,10 @@ var UnpublishAiActionToolParams = BaseToolSchema.extend({
488
562
  });
489
563
  function unpublishAiActionTool(config) {
490
564
  async function tool2(args) {
565
+ assertEnvironmentNotProtected(
566
+ args.environmentId,
567
+ config.protectedEnvironments
568
+ );
491
569
  const params = {
492
570
  spaceId: args.spaceId,
493
571
  environmentId: args.environmentId,
@@ -534,6 +612,10 @@ var UpdateAiActionToolParams = BaseToolSchema.extend({
534
612
  });
535
613
  function updateAiActionTool(config) {
536
614
  async function tool2(args) {
615
+ assertEnvironmentNotProtected(
616
+ args.environmentId,
617
+ config.protectedEnvironments
618
+ );
537
619
  const params = {
538
620
  spaceId: args.spaceId,
539
621
  environmentId: args.environmentId,
@@ -605,13 +687,12 @@ function createAiActionTools(config) {
605
687
  },
606
688
  deleteAiAction: {
607
689
  title: "delete_ai_action",
608
- description: "Delete a specific AI action from your Contentful space",
690
+ description: "Delete a specific AI action from your Contentful space. This is a two-phase operation: the first call (without confirm/confirmToken) returns a preview of the AI action and a confirmToken. To complete the deletion, call this tool again with the same aiActionId, confirm: true, and the confirmToken from the preview response.",
609
691
  inputParams: DeleteAiActionToolParams.shape,
610
692
  annotations: {
611
693
  readOnlyHint: false,
612
694
  destructiveHint: true,
613
- idempotentHint: true,
614
- // Deleting same item multiple times has same effect
695
+ idempotentHint: false,
615
696
  openWorldHint: false
616
697
  },
617
698
  tool: deleteAiAction
@@ -765,6 +846,10 @@ var UploadAssetToolParams = BaseToolSchema.extend({
765
846
  });
766
847
  function uploadAssetTool(config) {
767
848
  async function tool2(args) {
849
+ assertEnvironmentNotProtected(
850
+ args.environmentId,
851
+ config.protectedEnvironments
852
+ );
768
853
  const params = {
769
854
  spaceId: args.spaceId,
770
855
  environmentId: args.environmentId
@@ -918,6 +1003,10 @@ var UpdateAssetToolParams = BaseToolSchema.extend({
918
1003
  });
919
1004
  function updateAssetTool(config) {
920
1005
  async function tool2(args) {
1006
+ assertEnvironmentNotProtected(
1007
+ args.environmentId,
1008
+ config.protectedEnvironments
1009
+ );
921
1010
  const params = {
922
1011
  spaceId: args.spaceId,
923
1012
  environmentId: args.environmentId,
@@ -941,7 +1030,9 @@ function updateAssetTool(config) {
941
1030
  concepts: allConcepts
942
1031
  }
943
1032
  });
944
- return createSuccessResponse("Asset updated successfully", { updatedAsset });
1033
+ return createSuccessResponse("Asset updated successfully", {
1034
+ updatedAsset
1035
+ });
945
1036
  }
946
1037
  return withErrorHandling(tool2, "Error updating asset");
947
1038
  }
@@ -949,10 +1040,20 @@ function updateAssetTool(config) {
949
1040
  // src/tools/assets/deleteAsset.ts
950
1041
  import { z as z18 } from "zod";
951
1042
  var DeleteAssetToolParams = BaseToolSchema.extend({
952
- assetId: z18.string().describe("The ID of the asset to delete")
1043
+ assetId: z18.string().describe("The ID of the asset to delete"),
1044
+ confirm: z18.boolean().optional().describe(
1045
+ "Set to true on the second call to actually perform the deletion. Required together with confirmToken."
1046
+ ),
1047
+ confirmToken: z18.string().optional().describe(
1048
+ "Token returned by the preview call; must be supplied with confirm: true."
1049
+ )
953
1050
  });
954
1051
  function deleteAssetTool(config) {
955
1052
  async function tool2(args) {
1053
+ assertEnvironmentNotProtected(
1054
+ args.environmentId,
1055
+ config.protectedEnvironments
1056
+ );
956
1057
  const params = {
957
1058
  spaceId: args.spaceId,
958
1059
  environmentId: args.environmentId,
@@ -960,6 +1061,22 @@ function deleteAssetTool(config) {
960
1061
  };
961
1062
  const contentfulClient = createToolClient(config, args);
962
1063
  const asset = await contentfulClient.asset.get(params);
1064
+ const expectedToken = buildConfirmToken(
1065
+ "asset",
1066
+ args.assetId,
1067
+ asset.sys.version
1068
+ );
1069
+ if (args.confirm !== true || args.confirmToken !== expectedToken) {
1070
+ return createSuccessResponse(
1071
+ `${CONFIRMATION_MESSAGE_PREFIX} asset`,
1072
+ buildConfirmationPreview(
1073
+ "asset",
1074
+ args.assetId,
1075
+ { asset },
1076
+ expectedToken
1077
+ )
1078
+ );
1079
+ }
963
1080
  await contentfulClient.asset.delete(params);
964
1081
  return createSuccessResponse("Asset deleted successfully", { asset });
965
1082
  }
@@ -1063,20 +1180,74 @@ function createEntitiesCollection(entities) {
1063
1180
  };
1064
1181
  }
1065
1182
 
1183
+ // src/utils/bulkLimits.ts
1184
+ var DEFAULT_MAX_BULK_SIZE = 10;
1185
+ function resolveMaxBulkSize(configured) {
1186
+ if (configured === void 0 || !Number.isInteger(configured) || configured <= 0) {
1187
+ return DEFAULT_MAX_BULK_SIZE;
1188
+ }
1189
+ return configured;
1190
+ }
1191
+ function assertBulkSizeAllowed(count, configured) {
1192
+ const limit = resolveMaxBulkSize(configured);
1193
+ if (count > limit) {
1194
+ throw new Error(
1195
+ `Bulk operation rejected: ${count} IDs exceeds MAX_BULK_SIZE of ${limit}. Reduce batch size or increase the limit.`
1196
+ );
1197
+ }
1198
+ }
1199
+ var PLURAL_BY_ENTITY = {
1200
+ entry: "entries",
1201
+ asset: "assets"
1202
+ };
1203
+ function buildDryRunPreview(input) {
1204
+ const { operation, entityType, ids, spaceId, environmentId } = input;
1205
+ const noun = ids.length === 1 ? entityType : PLURAL_BY_ENTITY[entityType];
1206
+ return {
1207
+ dryRun: true,
1208
+ operation,
1209
+ entityType,
1210
+ count: ids.length,
1211
+ ids,
1212
+ target: { spaceId, environmentId },
1213
+ message: `Dry run: would ${operation} ${ids.length} ${noun} in ${spaceId}/${environmentId}. No changes were made. Re-run without dryRun to execute.`
1214
+ };
1215
+ }
1216
+
1066
1217
  // src/tools/assets/publishAsset.ts
1067
1218
  var PublishAssetToolParams = BaseToolSchema.extend({
1068
1219
  assetId: z19.union([z19.string(), z19.array(z19.string()).max(100)]).describe(
1069
- "The ID of the asset to publish (string) or an array of asset IDs (up to 100 assets)"
1220
+ "A single asset ID (string) or an array of asset IDs to publish (up to MAX_BULK_SIZE per call; default 10, max 100 \u2014 configurable via MAX_BULK_SIZE env var)."
1221
+ ),
1222
+ dryRun: z19.boolean().optional().describe(
1223
+ "When true, returns a preview of the operation without executing it. Still subject to MAX_BULK_SIZE \u2014 use this to confirm intent for within-limit calls."
1070
1224
  )
1071
1225
  });
1072
1226
  function publishAssetTool(config) {
1073
1227
  async function tool2(args) {
1228
+ assertEnvironmentNotProtected(
1229
+ args.environmentId,
1230
+ config.protectedEnvironments
1231
+ );
1232
+ const assetIds = Array.isArray(args.assetId) ? args.assetId : [args.assetId];
1233
+ assertBulkSizeAllowed(assetIds.length, config.maxBulkSize);
1234
+ if (args.dryRun) {
1235
+ return createSuccessResponse(
1236
+ "Dry run: no changes were made",
1237
+ buildDryRunPreview({
1238
+ operation: "publish",
1239
+ entityType: "asset",
1240
+ ids: assetIds,
1241
+ spaceId: args.spaceId,
1242
+ environmentId: args.environmentId
1243
+ })
1244
+ );
1245
+ }
1074
1246
  const baseParams = {
1075
1247
  spaceId: args.spaceId,
1076
1248
  environmentId: args.environmentId
1077
1249
  };
1078
1250
  const contentfulClient = createToolClient(config, args);
1079
- const assetIds = Array.isArray(args.assetId) ? args.assetId : [args.assetId];
1080
1251
  if (assetIds.length === 1) {
1081
1252
  try {
1082
1253
  const assetId = assetIds[0];
@@ -1126,17 +1297,37 @@ function publishAssetTool(config) {
1126
1297
  import { z as z20 } from "zod";
1127
1298
  var UnpublishAssetToolParams = BaseToolSchema.extend({
1128
1299
  assetId: z20.union([z20.string(), z20.array(z20.string()).max(100)]).describe(
1129
- "The ID of the asset to unpublish (string) or an array of asset IDs (up to 100 assets)"
1300
+ "A single asset ID (string) or an array of asset IDs to unpublish (up to MAX_BULK_SIZE per call; default 10, max 100 \u2014 configurable via MAX_BULK_SIZE env var)."
1301
+ ),
1302
+ dryRun: z20.boolean().optional().describe(
1303
+ "When true, returns a preview of the operation without executing it. Still subject to MAX_BULK_SIZE \u2014 use this to confirm intent for within-limit calls."
1130
1304
  )
1131
1305
  });
1132
1306
  function unpublishAssetTool(config) {
1133
1307
  async function tool2(args) {
1308
+ assertEnvironmentNotProtected(
1309
+ args.environmentId,
1310
+ config.protectedEnvironments
1311
+ );
1312
+ const assetIds = Array.isArray(args.assetId) ? args.assetId : [args.assetId];
1313
+ assertBulkSizeAllowed(assetIds.length, config.maxBulkSize);
1314
+ if (args.dryRun) {
1315
+ return createSuccessResponse(
1316
+ "Dry run: no changes were made",
1317
+ buildDryRunPreview({
1318
+ operation: "unpublish",
1319
+ entityType: "asset",
1320
+ ids: assetIds,
1321
+ spaceId: args.spaceId,
1322
+ environmentId: args.environmentId
1323
+ })
1324
+ );
1325
+ }
1134
1326
  const baseParams = {
1135
1327
  spaceId: args.spaceId,
1136
1328
  environmentId: args.environmentId
1137
1329
  };
1138
1330
  const contentfulClient = createToolClient(config, args);
1139
- const assetIds = Array.isArray(args.assetId) ? args.assetId : [args.assetId];
1140
1331
  if (assetIds.length === 1) {
1141
1332
  try {
1142
1333
  const assetId = assetIds[0];
@@ -1186,17 +1377,37 @@ function unpublishAssetTool(config) {
1186
1377
  import { z as z21 } from "zod";
1187
1378
  var ArchiveAssetToolParams = BaseToolSchema.extend({
1188
1379
  assetId: z21.union([z21.string(), z21.array(z21.string()).max(100)]).describe(
1189
- "The ID of the asset to archive (string) or an array of asset IDs (up to 100 assets)"
1380
+ "A single asset ID (string) or an array of asset IDs to archive (up to MAX_BULK_SIZE per call; default 10, max 100 \u2014 configurable via MAX_BULK_SIZE env var)."
1381
+ ),
1382
+ dryRun: z21.boolean().optional().describe(
1383
+ "When true, returns a preview of the operation without executing it. Still subject to MAX_BULK_SIZE \u2014 use this to confirm intent for within-limit calls."
1190
1384
  )
1191
1385
  });
1192
1386
  function archiveAssetTool(config) {
1193
1387
  async function tool2(args) {
1388
+ assertEnvironmentNotProtected(
1389
+ args.environmentId,
1390
+ config.protectedEnvironments
1391
+ );
1392
+ const assetIds = Array.isArray(args.assetId) ? args.assetId : [args.assetId];
1393
+ assertBulkSizeAllowed(assetIds.length, config.maxBulkSize);
1394
+ if (args.dryRun) {
1395
+ return createSuccessResponse(
1396
+ "Dry run: no changes were made",
1397
+ buildDryRunPreview({
1398
+ operation: "archive",
1399
+ entityType: "asset",
1400
+ ids: assetIds,
1401
+ spaceId: args.spaceId,
1402
+ environmentId: args.environmentId
1403
+ })
1404
+ );
1405
+ }
1194
1406
  const baseParams = {
1195
1407
  spaceId: args.spaceId,
1196
1408
  environmentId: args.environmentId
1197
1409
  };
1198
1410
  const contentfulClient = createToolClient(config, args);
1199
- const assetIds = Array.isArray(args.assetId) ? args.assetId : [args.assetId];
1200
1411
  const successfullyArchived = [];
1201
1412
  for (const assetId of assetIds) {
1202
1413
  try {
@@ -1232,17 +1443,37 @@ function archiveAssetTool(config) {
1232
1443
  import { z as z22 } from "zod";
1233
1444
  var UnarchiveAssetToolParams = BaseToolSchema.extend({
1234
1445
  assetId: z22.union([z22.string(), z22.array(z22.string()).max(100)]).describe(
1235
- "The ID of the asset to unarchive (string) or an array of asset IDs (up to 100 assets)"
1446
+ "A single asset ID (string) or an array of asset IDs to unarchive (up to MAX_BULK_SIZE per call; default 10, max 100 \u2014 configurable via MAX_BULK_SIZE env var)."
1447
+ ),
1448
+ dryRun: z22.boolean().optional().describe(
1449
+ "When true, returns a preview of the operation without executing it. Still subject to MAX_BULK_SIZE \u2014 use this to confirm intent for within-limit calls."
1236
1450
  )
1237
1451
  });
1238
1452
  function unarchiveAssetTool(config) {
1239
1453
  async function tool2(args) {
1454
+ assertEnvironmentNotProtected(
1455
+ args.environmentId,
1456
+ config.protectedEnvironments
1457
+ );
1458
+ const assetIds = Array.isArray(args.assetId) ? args.assetId : [args.assetId];
1459
+ assertBulkSizeAllowed(assetIds.length, config.maxBulkSize);
1460
+ if (args.dryRun) {
1461
+ return createSuccessResponse(
1462
+ "Dry run: no changes were made",
1463
+ buildDryRunPreview({
1464
+ operation: "unarchive",
1465
+ entityType: "asset",
1466
+ ids: assetIds,
1467
+ spaceId: args.spaceId,
1468
+ environmentId: args.environmentId
1469
+ })
1470
+ );
1471
+ }
1240
1472
  const baseParams = {
1241
1473
  spaceId: args.spaceId,
1242
1474
  environmentId: args.environmentId
1243
1475
  };
1244
1476
  const contentfulClient = createToolClient(config, args);
1245
- const assetIds = Array.isArray(args.assetId) ? args.assetId : [args.assetId];
1246
1477
  const successfullyUnarchived = [];
1247
1478
  for (const assetId of assetIds) {
1248
1479
  try {
@@ -1332,12 +1563,12 @@ function createAssetTools(config) {
1332
1563
  },
1333
1564
  deleteAsset: {
1334
1565
  title: "delete_asset",
1335
- description: "Delete an asset",
1566
+ description: "Delete an asset from your Contentful space. This is a two-phase operation: the first call (without confirm/confirmToken) returns a preview of the asset and a confirmToken. To complete the deletion, call this tool again with the same assetId, confirm: true, and the confirmToken from the preview response.",
1336
1567
  inputParams: DeleteAssetToolParams.shape,
1337
1568
  annotations: {
1338
1569
  readOnlyHint: false,
1339
1570
  destructiveHint: true,
1340
- idempotentHint: true,
1571
+ idempotentHint: false,
1341
1572
  openWorldHint: false
1342
1573
  },
1343
1574
  tool: deleteAsset
@@ -1577,6 +1808,10 @@ var CreateContentTypeToolParams = BaseToolSchema.extend({
1577
1808
  });
1578
1809
  function createContentTypeTool(config) {
1579
1810
  async function tool2(args) {
1811
+ assertEnvironmentNotProtected(
1812
+ args.environmentId,
1813
+ config.protectedEnvironments
1814
+ );
1580
1815
  const params = {
1581
1816
  spaceId: args.spaceId,
1582
1817
  environmentId: args.environmentId
@@ -1614,6 +1849,10 @@ var UpdateContentTypeToolParams = BaseToolSchema.extend({
1614
1849
  });
1615
1850
  function updateContentTypeTool(config) {
1616
1851
  async function tool2(args) {
1852
+ assertEnvironmentNotProtected(
1853
+ args.environmentId,
1854
+ config.protectedEnvironments
1855
+ );
1617
1856
  const params = {
1618
1857
  spaceId: args.spaceId,
1619
1858
  environmentId: args.environmentId,
@@ -1664,16 +1903,43 @@ function updateContentTypeTool(config) {
1664
1903
  // src/tools/content-types/deleteContentType.ts
1665
1904
  import { z as z29 } from "zod";
1666
1905
  var DeleteContentTypeToolParams = BaseToolSchema.extend({
1667
- contentTypeId: z29.string().describe("The ID of the content type to delete")
1906
+ contentTypeId: z29.string().describe("The ID of the content type to delete"),
1907
+ confirm: z29.boolean().optional().describe(
1908
+ "Set to true on the second call to actually perform the deletion. Required together with confirmToken."
1909
+ ),
1910
+ confirmToken: z29.string().optional().describe(
1911
+ "Token returned by the preview call; must be supplied with confirm: true."
1912
+ )
1668
1913
  });
1669
1914
  function deleteContentTypeTool(config) {
1670
1915
  async function tool2(args) {
1916
+ assertEnvironmentNotProtected(
1917
+ args.environmentId,
1918
+ config.protectedEnvironments
1919
+ );
1671
1920
  const params = {
1672
1921
  spaceId: args.spaceId,
1673
1922
  environmentId: args.environmentId,
1674
1923
  contentTypeId: args.contentTypeId
1675
1924
  };
1676
1925
  const contentfulClient = createToolClient(config, args);
1926
+ const contentType = await contentfulClient.contentType.get(params);
1927
+ const expectedToken = buildConfirmToken(
1928
+ "contentType",
1929
+ args.contentTypeId,
1930
+ contentType.sys.version
1931
+ );
1932
+ if (args.confirm !== true || args.confirmToken !== expectedToken) {
1933
+ return createSuccessResponse(
1934
+ `${CONFIRMATION_MESSAGE_PREFIX} content type`,
1935
+ buildConfirmationPreview(
1936
+ "contentType",
1937
+ args.contentTypeId,
1938
+ { contentType },
1939
+ expectedToken
1940
+ )
1941
+ );
1942
+ }
1677
1943
  await contentfulClient.contentType.delete(params);
1678
1944
  return createSuccessResponse("Content type deleted successfully", {
1679
1945
  contentTypeId: args.contentTypeId
@@ -1689,6 +1955,10 @@ var PublishContentTypeToolParams = BaseToolSchema.extend({
1689
1955
  });
1690
1956
  function publishContentTypeTool(config) {
1691
1957
  async function tool2(args) {
1958
+ assertEnvironmentNotProtected(
1959
+ args.environmentId,
1960
+ config.protectedEnvironments
1961
+ );
1692
1962
  const params = {
1693
1963
  spaceId: args.spaceId,
1694
1964
  environmentId: args.environmentId,
@@ -1714,6 +1984,10 @@ var UnpublishContentTypeToolParams = BaseToolSchema.extend({
1714
1984
  });
1715
1985
  function unpublishContentTypeTool(config) {
1716
1986
  async function tool2(args) {
1987
+ assertEnvironmentNotProtected(
1988
+ args.environmentId,
1989
+ config.protectedEnvironments
1990
+ );
1717
1991
  const params = {
1718
1992
  spaceId: args.spaceId,
1719
1993
  environmentId: args.environmentId,
@@ -1728,6 +2002,146 @@ function unpublishContentTypeTool(config) {
1728
2002
  return withErrorHandling(tool2, "Error unpublishing content type");
1729
2003
  }
1730
2004
 
2005
+ // src/tools/content-types/omitContentTypeField.ts
2006
+ import { z as z32 } from "zod";
2007
+ var OmitContentTypeFieldToolParams = BaseToolSchema.extend({
2008
+ contentTypeId: z32.string().describe("The ID of the content type containing the field"),
2009
+ fieldId: z32.string().describe("The ID of the field to omit"),
2010
+ omitted: z32.boolean().default(true).describe(
2011
+ "Whether the field should be omitted. Defaults to true. Set to false to un-omit a field."
2012
+ )
2013
+ });
2014
+ function omitContentTypeFieldTool(config) {
2015
+ async function tool2(args) {
2016
+ const params = {
2017
+ spaceId: args.spaceId,
2018
+ environmentId: args.environmentId,
2019
+ contentTypeId: args.contentTypeId
2020
+ };
2021
+ const contentfulClient = createToolClient(config, args);
2022
+ const currentContentType = await contentfulClient.contentType.get(params);
2023
+ const field = currentContentType.fields.find((f) => f.id === args.fieldId);
2024
+ if (!field) {
2025
+ throw new Error(
2026
+ `Field "${args.fieldId}" not found on content type "${args.contentTypeId}"`
2027
+ );
2028
+ }
2029
+ const updatedFields = currentContentType.fields.map(
2030
+ (f) => f.id === args.fieldId ? { ...f, omitted: args.omitted } : f
2031
+ );
2032
+ const updatedContentType = await contentfulClient.contentType.update(
2033
+ params,
2034
+ { ...currentContentType, fields: updatedFields }
2035
+ );
2036
+ return createSuccessResponse(
2037
+ `Field "${args.fieldId}" updated (omitted=${args.omitted}) on content type "${args.contentTypeId}". Publish the content type for the change to take effect.`,
2038
+ { contentType: updatedContentType }
2039
+ );
2040
+ }
2041
+ return withErrorHandling(tool2, "Error omitting field");
2042
+ }
2043
+
2044
+ // src/tools/content-types/deleteContentTypeField.ts
2045
+ import { z as z33 } from "zod";
2046
+ var DeleteContentTypeFieldToolParams = BaseToolSchema.extend({
2047
+ contentTypeId: z33.string().describe("The ID of the content type containing the field"),
2048
+ fieldId: z33.string().describe("The ID of the field to delete")
2049
+ });
2050
+ function deleteContentTypeFieldTool(config) {
2051
+ async function tool2(args) {
2052
+ const params = {
2053
+ spaceId: args.spaceId,
2054
+ environmentId: args.environmentId,
2055
+ contentTypeId: args.contentTypeId
2056
+ };
2057
+ const contentfulClient = createToolClient(config, args);
2058
+ const currentContentType = await contentfulClient.contentType.get(params);
2059
+ const field = currentContentType.fields.find((f) => f.id === args.fieldId);
2060
+ if (!field) {
2061
+ throw new Error(
2062
+ `Field "${args.fieldId}" not found on content type "${args.contentTypeId}"`
2063
+ );
2064
+ }
2065
+ if (field.required) {
2066
+ throw new Error(
2067
+ `Field "${args.fieldId}" is required. Set required=false via update_content_type and publish before deleting.`
2068
+ );
2069
+ }
2070
+ if (!field.omitted) {
2071
+ throw new Error(
2072
+ `Field "${args.fieldId}" must be omitted and the content type published before it can be deleted. Use omit_content_type_field, then publish_content_type, then retry.`
2073
+ );
2074
+ }
2075
+ const updatedFields = currentContentType.fields.map(
2076
+ (f) => f.id === args.fieldId ? { ...f, deleted: true } : f
2077
+ );
2078
+ const updatedContentType = await contentfulClient.contentType.update(
2079
+ params,
2080
+ { ...currentContentType, fields: updatedFields }
2081
+ );
2082
+ return createSuccessResponse(
2083
+ `Field "${args.fieldId}" marked deleted on content type "${args.contentTypeId}". Publish the content type for the deletion to take effect.`,
2084
+ { contentType: updatedContentType }
2085
+ );
2086
+ }
2087
+ return withErrorHandling(tool2, "Error deleting field");
2088
+ }
2089
+
2090
+ // src/tools/content-types/disableContentTypeField.ts
2091
+ import { z as z34 } from "zod";
2092
+ var DisableContentTypeFieldToolParams = BaseToolSchema.extend({
2093
+ contentTypeId: z34.string().describe("The ID of the content type containing the field"),
2094
+ fieldId: z34.string().describe("The ID of the field to update"),
2095
+ disabled: z34.boolean().optional().describe(
2096
+ "Set to true to disable the field in the editor UI (editors cannot edit it), false to re-enable. Takes effect once the content type is published."
2097
+ ),
2098
+ omitted: z34.boolean().optional().describe(
2099
+ "Set to true to omit the field from API responses, false to include it again. Takes effect once the content type is published. Prefer omit_content_type_field when only changing the omitted flag."
2100
+ )
2101
+ });
2102
+ function disableContentTypeFieldTool(config) {
2103
+ async function tool2(args) {
2104
+ if (args.disabled === void 0 && args.omitted === void 0) {
2105
+ throw new Error(
2106
+ 'At least one of "disabled" or "omitted" must be provided'
2107
+ );
2108
+ }
2109
+ const params = {
2110
+ spaceId: args.spaceId,
2111
+ environmentId: args.environmentId,
2112
+ contentTypeId: args.contentTypeId
2113
+ };
2114
+ const contentfulClient = createToolClient(config, args);
2115
+ const currentContentType = await contentfulClient.contentType.get(params);
2116
+ const field = currentContentType.fields.find((f) => f.id === args.fieldId);
2117
+ if (!field) {
2118
+ throw new Error(
2119
+ `Field "${args.fieldId}" not found on content type "${args.contentTypeId}"`
2120
+ );
2121
+ }
2122
+ const updatedFields = currentContentType.fields.map((f) => {
2123
+ if (f.id !== args.fieldId) return f;
2124
+ return {
2125
+ ...f,
2126
+ ...args.disabled !== void 0 && { disabled: args.disabled },
2127
+ ...args.omitted !== void 0 && { omitted: args.omitted }
2128
+ };
2129
+ });
2130
+ const updatedContentType = await contentfulClient.contentType.update(
2131
+ params,
2132
+ { ...currentContentType, fields: updatedFields }
2133
+ );
2134
+ const changes = [];
2135
+ if (args.disabled !== void 0) changes.push(`disabled=${args.disabled}`);
2136
+ if (args.omitted !== void 0) changes.push(`omitted=${args.omitted}`);
2137
+ return createSuccessResponse(
2138
+ `Field "${args.fieldId}" updated (${changes.join(", ")}) on content type "${args.contentTypeId}". Publish the content type for the change to take effect.`,
2139
+ { contentType: updatedContentType }
2140
+ );
2141
+ }
2142
+ return withErrorHandling(tool2, "Error updating field");
2143
+ }
2144
+
1731
2145
  // src/tools/content-types/register.ts
1732
2146
  function createContentTypeTools(config) {
1733
2147
  const getContentType = getContentTypeTool(config);
@@ -1737,6 +2151,9 @@ function createContentTypeTools(config) {
1737
2151
  const deleteContentType = deleteContentTypeTool(config);
1738
2152
  const publishContentType = publishContentTypeTool(config);
1739
2153
  const unpublishContentType = unpublishContentTypeTool(config);
2154
+ const omitContentTypeField = omitContentTypeFieldTool(config);
2155
+ const deleteContentTypeField = deleteContentTypeFieldTool(config);
2156
+ const disableContentTypeField = disableContentTypeFieldTool(config);
1740
2157
  return {
1741
2158
  getContentType: {
1742
2159
  title: "get_content_type",
@@ -1784,12 +2201,12 @@ function createContentTypeTools(config) {
1784
2201
  },
1785
2202
  deleteContentType: {
1786
2203
  title: "delete_content_type",
1787
- description: "Delete a content type",
2204
+ description: "Delete a content type from your Contentful space. This is a two-phase operation: the first call (without confirm/confirmToken) returns a preview of the content type and a confirmToken. To complete the deletion, call this tool again with the same contentTypeId, confirm: true, and the confirmToken from the preview response.",
1788
2205
  inputParams: DeleteContentTypeToolParams.shape,
1789
2206
  annotations: {
1790
2207
  readOnlyHint: false,
1791
2208
  destructiveHint: true,
1792
- idempotentHint: true,
2209
+ idempotentHint: false,
1793
2210
  openWorldHint: false
1794
2211
  },
1795
2212
  tool: deleteContentType
@@ -1817,12 +2234,48 @@ function createContentTypeTools(config) {
1817
2234
  openWorldHint: false
1818
2235
  },
1819
2236
  tool: unpublishContentType
2237
+ },
2238
+ omitContentTypeField: {
2239
+ title: "omit_content_type_field",
2240
+ description: "Mark a single field as omitted (or un-omitted) on a content type. Updates the content type draft only \u2014 call publish_content_type afterwards for the change to take effect. Reversible via the same tool with omitted=false. This is a prerequisite for delete_content_type_field: the field must be omitted in the published version before it can be deleted.",
2241
+ inputParams: OmitContentTypeFieldToolParams.shape,
2242
+ annotations: {
2243
+ readOnlyHint: false,
2244
+ destructiveHint: false,
2245
+ idempotentHint: false,
2246
+ openWorldHint: false
2247
+ },
2248
+ tool: omitContentTypeField
2249
+ },
2250
+ deleteContentTypeField: {
2251
+ title: "delete_content_type_field",
2252
+ description: "Permanently mark a single field as deleted on a content type. Destructive and irreversible once published. Updates the content type draft only \u2014 call publish_content_type afterwards for the deletion to take effect. The field must not be required AND must already be omitted in the published version of the content type. Run omit_content_type_field, then publish_content_type, before calling this. Use disable_content_type_field to temporarily hide a field instead.",
2253
+ inputParams: DeleteContentTypeFieldToolParams.shape,
2254
+ annotations: {
2255
+ readOnlyHint: false,
2256
+ destructiveHint: true,
2257
+ idempotentHint: false,
2258
+ openWorldHint: false
2259
+ },
2260
+ tool: deleteContentTypeField
2261
+ },
2262
+ disableContentTypeField: {
2263
+ title: "disable_content_type_field",
2264
+ description: "Toggle the disabled and/or omitted flags on a single field. Setting disabled=true hides the field from the editor UI; setting omitted=true removes it from API responses. Both flags are reversible. Updates the content type draft only \u2014 call publish_content_type afterwards for the change to take effect. Use omit_content_type_field when only changing the omitted flag.",
2265
+ inputParams: DisableContentTypeFieldToolParams.shape,
2266
+ annotations: {
2267
+ readOnlyHint: false,
2268
+ destructiveHint: false,
2269
+ idempotentHint: false,
2270
+ openWorldHint: false
2271
+ },
2272
+ tool: disableContentTypeField
1820
2273
  }
1821
2274
  };
1822
2275
  }
1823
2276
 
1824
2277
  // src/tools/context/getInitialContextTool.ts
1825
- import { z as z32 } from "zod";
2278
+ import { z as z35 } from "zod";
1826
2279
  import { outdent } from "outdent";
1827
2280
 
1828
2281
  // src/tools/context/store.ts
@@ -1959,7 +2412,7 @@ Before running a tool:
1959
2412
  You have access to powerful tools that can help you work with Contentful effectively. Always start with get_initial_context, check the schema when needed, clarify resources when multiple exist, and take action to complete user requests fully.`;
1960
2413
 
1961
2414
  // src/tools/context/getInitialContextTool.ts
1962
- var GetInitialContextToolParams = z32.object({});
2415
+ var GetInitialContextToolParams = z35.object({});
1963
2416
  function getInitialContextTool(config) {
1964
2417
  async function tool2(_params) {
1965
2418
  const configInfo = `Current Contentful Configuration:
@@ -2046,9 +2499,9 @@ function listEditorInterfacesTool(config) {
2046
2499
  }
2047
2500
 
2048
2501
  // src/tools/editor-interfaces/getEditorInterface.ts
2049
- import { z as z33 } from "zod";
2502
+ import { z as z36 } from "zod";
2050
2503
  var GetEditorInterfaceToolParams = BaseToolSchema.extend({
2051
- contentTypeId: z33.string().describe(
2504
+ contentTypeId: z36.string().describe(
2052
2505
  "The ID of the content type to retrieve the editor interface for"
2053
2506
  )
2054
2507
  });
@@ -2069,45 +2522,49 @@ function getEditorInterfaceTool(config) {
2069
2522
  }
2070
2523
 
2071
2524
  // src/tools/editor-interfaces/updateEditorInterface.ts
2072
- import { z as z34 } from "zod";
2073
- var ControlSchema = z34.object({
2074
- fieldId: z34.string().describe("The field ID this control applies to"),
2075
- widgetId: z34.string().describe("The widget ID to use for this field"),
2076
- widgetNamespace: z34.enum(["builtin", "extension", "app", "editor-builtin"]).optional().describe(
2525
+ import { z as z37 } from "zod";
2526
+ var ControlSchema = z37.object({
2527
+ fieldId: z37.string().describe("The field ID this control applies to"),
2528
+ widgetId: z37.string().describe("The widget ID to use for this field"),
2529
+ widgetNamespace: z37.enum(["builtin", "extension", "app", "editor-builtin"]).optional().describe(
2077
2530
  "The namespace of the widget (builtin, extension, app, or editor-builtin)"
2078
2531
  ),
2079
- settings: z34.record(z34.any()).optional().describe("Settings object for the widget")
2532
+ settings: z37.record(z37.any()).optional().describe("Settings object for the widget")
2080
2533
  });
2081
- var SidebarItemSchema = z34.object({
2082
- widgetId: z34.string().describe("The widget ID for the sidebar item"),
2083
- widgetNamespace: z34.enum(["sidebar-builtin", "extension", "app"]).describe("The namespace of the sidebar widget"),
2084
- settings: z34.record(z34.any()).optional().describe("Settings object for the sidebar widget"),
2085
- disabled: z34.boolean().optional().describe("Whether the sidebar item is disabled")
2534
+ var SidebarItemSchema = z37.object({
2535
+ widgetId: z37.string().describe("The widget ID for the sidebar item"),
2536
+ widgetNamespace: z37.enum(["sidebar-builtin", "extension", "app"]).describe("The namespace of the sidebar widget"),
2537
+ settings: z37.record(z37.any()).optional().describe("Settings object for the sidebar widget"),
2538
+ disabled: z37.boolean().optional().describe("Whether the sidebar item is disabled")
2086
2539
  });
2087
- var EditorLayoutItemSchema = z34.object({
2088
- fieldId: z34.string().describe("The field ID"),
2089
- settings: z34.record(z34.any()).optional().describe("Layout settings for the field")
2540
+ var EditorLayoutItemSchema = z37.object({
2541
+ fieldId: z37.string().describe("The field ID"),
2542
+ settings: z37.record(z37.any()).optional().describe("Layout settings for the field")
2090
2543
  });
2091
- var EditorLayoutSchema = z34.object({
2092
- items: z34.array(EditorLayoutItemSchema).optional().describe("Array of editor layout items")
2544
+ var EditorLayoutSchema = z37.object({
2545
+ items: z37.array(EditorLayoutItemSchema).optional().describe("Array of editor layout items")
2093
2546
  });
2094
- var GroupControlSchema = z34.object({
2095
- groupId: z34.string().describe("The group ID"),
2096
- widgetId: z34.string().describe("The widget ID for the group control"),
2097
- widgetNamespace: z34.enum(["builtin", "extension", "app"]).optional().describe("The namespace of the group control widget"),
2098
- settings: z34.record(z34.any()).optional().describe("Settings object for the group control")
2547
+ var GroupControlSchema = z37.object({
2548
+ groupId: z37.string().describe("The group ID"),
2549
+ widgetId: z37.string().describe("The widget ID for the group control"),
2550
+ widgetNamespace: z37.enum(["builtin", "extension", "app"]).optional().describe("The namespace of the group control widget"),
2551
+ settings: z37.record(z37.any()).optional().describe("Settings object for the group control")
2099
2552
  });
2100
2553
  var UpdateEditorInterfaceToolParams = BaseToolSchema.extend({
2101
- contentTypeId: z34.string().describe("The ID of the content type to update the editor interface for"),
2102
- controls: z34.array(ControlSchema).optional().describe(
2554
+ contentTypeId: z37.string().describe("The ID of the content type to update the editor interface for"),
2555
+ controls: z37.array(ControlSchema).optional().describe(
2103
2556
  "Array of control definitions for fields in the content type. Each control defines which widget to use for a field."
2104
2557
  ),
2105
- sidebar: z34.array(SidebarItemSchema).optional().describe("Array of sidebar widget configurations"),
2106
- editorLayout: z34.array(EditorLayoutSchema).optional().describe("Editor layout configuration for organizing fields"),
2107
- groupControls: z34.array(GroupControlSchema).optional().describe("Array of group control definitions for field groups")
2558
+ sidebar: z37.array(SidebarItemSchema).optional().describe("Array of sidebar widget configurations"),
2559
+ editorLayout: z37.array(EditorLayoutSchema).optional().describe("Editor layout configuration for organizing fields"),
2560
+ groupControls: z37.array(GroupControlSchema).optional().describe("Array of group control definitions for field groups")
2108
2561
  });
2109
2562
  function updateEditorInterfaceTool(config) {
2110
2563
  async function tool2(args) {
2564
+ assertEnvironmentNotProtected(
2565
+ args.environmentId,
2566
+ config.protectedEnvironments
2567
+ );
2111
2568
  const params = {
2112
2569
  spaceId: args.spaceId,
2113
2570
  environmentId: args.environmentId,
@@ -2183,7 +2640,7 @@ function createEditorInterfaceTools(config) {
2183
2640
  }
2184
2641
 
2185
2642
  // src/tools/entries/searchEntries.ts
2186
- import { z as z35 } from "zod";
2643
+ import { z as z38 } from "zod";
2187
2644
 
2188
2645
  // src/utils/limits.ts
2189
2646
  function searchLimit(userLimit) {
@@ -2206,38 +2663,38 @@ function normalizeArrayFilters(query) {
2206
2663
 
2207
2664
  // src/tools/entries/searchEntries.ts
2208
2665
  var SearchEntriesToolParams = BaseToolSchema.extend({
2209
- query: z35.object({
2666
+ query: z38.object({
2210
2667
  // Core parameters (maintain backward compatibility)
2211
- content_type: z35.string().optional().describe("Filter by content type"),
2212
- include: z35.number().optional().describe("Include this many levels of linked entries"),
2213
- select: z35.string().optional().describe("Comma-separated list of fields to return"),
2214
- links_to_entry: z35.string().optional().describe("Find entries that link to the specified entry ID"),
2215
- limit: z35.number().optional().describe(
2668
+ content_type: z38.string().optional().describe("Filter by content type"),
2669
+ include: z38.number().optional().describe("Include this many levels of linked entries"),
2670
+ select: z38.string().optional().describe("Comma-separated list of fields to return"),
2671
+ links_to_entry: z38.string().optional().describe("Find entries that link to the specified entry ID"),
2672
+ limit: z38.number().optional().describe(
2216
2673
  "Maximum number of entries to return (default: 10, max: 100)"
2217
2674
  ),
2218
- skip: z35.number().optional().describe("Skip this many entries for pagination"),
2219
- order: z35.string().optional().describe("Order entries by this field"),
2675
+ skip: z38.number().optional().describe("Skip this many entries for pagination"),
2676
+ order: z38.string().optional().describe("Order entries by this field"),
2220
2677
  // Full-text search
2221
- query: z35.string().optional().describe("Full-text search across all fields"),
2678
+ query: z38.string().optional().describe("Full-text search across all fields"),
2222
2679
  // Common field-based searches (examples - any field is supported via catchall)
2223
- "fields.title": z35.string().optional().describe("Search by title field"),
2224
- "fields.slug": z35.string().optional().describe("Search by slug field"),
2225
- "fields.internalName": z35.string().optional().describe("Search by internal name field"),
2226
- "fields.text": z35.string().optional().describe("Search by text field (useful for testimonials)"),
2227
- "fields.title[match]": z35.string().optional().describe("Pattern match on title field"),
2228
- "fields.slug[match]": z35.string().optional().describe("Pattern match on slug field"),
2229
- "fields.title[exists]": z35.boolean().optional().describe("Check if title field exists"),
2230
- "fields.slug[exists]": z35.boolean().optional().describe("Check if slug field exists"),
2680
+ "fields.title": z38.string().optional().describe("Search by title field"),
2681
+ "fields.slug": z38.string().optional().describe("Search by slug field"),
2682
+ "fields.internalName": z38.string().optional().describe("Search by internal name field"),
2683
+ "fields.text": z38.string().optional().describe("Search by text field (useful for testimonials)"),
2684
+ "fields.title[match]": z38.string().optional().describe("Pattern match on title field"),
2685
+ "fields.slug[match]": z38.string().optional().describe("Pattern match on slug field"),
2686
+ "fields.title[exists]": z38.boolean().optional().describe("Check if title field exists"),
2687
+ "fields.slug[exists]": z38.boolean().optional().describe("Check if slug field exists"),
2231
2688
  // System field searches
2232
- "sys.id[in]": z35.array(z35.string()).optional().describe("Search by multiple entry IDs"),
2233
- "sys.contentType.sys.id": z35.string().optional().describe("Filter by content type ID"),
2234
- "sys.createdAt[gte]": z35.string().optional().describe("Created after date (ISO format)"),
2235
- "sys.createdAt[lte]": z35.string().optional().describe("Created before date (ISO format)"),
2236
- "sys.updatedAt[gte]": z35.string().optional().describe("Updated after date (ISO format)"),
2237
- "sys.updatedAt[lte]": z35.string().optional().describe("Updated before date (ISO format)"),
2689
+ "sys.id[in]": z38.array(z38.string()).optional().describe("Search by multiple entry IDs"),
2690
+ "sys.contentType.sys.id": z38.string().optional().describe("Filter by content type ID"),
2691
+ "sys.createdAt[gte]": z38.string().optional().describe("Created after date (ISO format)"),
2692
+ "sys.createdAt[lte]": z38.string().optional().describe("Created before date (ISO format)"),
2693
+ "sys.updatedAt[gte]": z38.string().optional().describe("Updated after date (ISO format)"),
2694
+ "sys.updatedAt[lte]": z38.string().optional().describe("Updated before date (ISO format)"),
2238
2695
  // Metadata searches
2239
- "metadata.tags.sys.id[in]": z35.array(z35.string()).optional().describe("Filter by tag IDs")
2240
- }).catchall(z35.any()).describe(
2696
+ "metadata.tags.sys.id[in]": z38.array(z38.string()).optional().describe("Filter by tag IDs")
2697
+ }).catchall(z38.any()).describe(
2241
2698
  "Flexible search parameters supporting ANY Contentful API query parameter. Use fields.* for field searches, sys.* for system fields, and any other Contentful API parameter."
2242
2699
  )
2243
2700
  });
@@ -2268,110 +2725,110 @@ function searchEntriesTool(config) {
2268
2725
  }
2269
2726
 
2270
2727
  // src/tools/entries/createEntry.ts
2271
- import { z as z38 } from "zod";
2728
+ import { z as z41 } from "zod";
2272
2729
 
2273
2730
  // src/types/entryFieldSchema.ts
2274
- import { z as z37 } from "zod";
2731
+ import { z as z40 } from "zod";
2275
2732
 
2276
2733
  // src/types/richTextSchema.ts
2277
2734
  import { BLOCKS as BLOCKS2, INLINES as INLINES2, MARKS } from "@contentful/rich-text-types";
2278
- import { z as z36 } from "zod";
2279
- var emptyNodeDataSchema = z36.object({});
2280
- var entryLinkTargetSchema = z36.object({
2281
- sys: z36.object({
2282
- id: z36.string(),
2283
- type: z36.literal("Link"),
2284
- linkType: z36.literal("Entry")
2735
+ import { z as z39 } from "zod";
2736
+ var emptyNodeDataSchema = z39.object({});
2737
+ var entryLinkTargetSchema = z39.object({
2738
+ sys: z39.object({
2739
+ id: z39.string(),
2740
+ type: z39.literal("Link"),
2741
+ linkType: z39.literal("Entry")
2285
2742
  })
2286
2743
  });
2287
- var assetLinkTargetSchema = z36.object({
2288
- sys: z36.object({
2289
- id: z36.string(),
2290
- type: z36.literal("Link"),
2291
- linkType: z36.literal("Asset")
2744
+ var assetLinkTargetSchema = z39.object({
2745
+ sys: z39.object({
2746
+ id: z39.string(),
2747
+ type: z39.literal("Link"),
2748
+ linkType: z39.literal("Asset")
2292
2749
  })
2293
2750
  });
2294
- var resourceLinkTargetSchema = z36.object({
2295
- sys: z36.object({
2296
- type: z36.literal("ResourceLink"),
2297
- linkType: z36.string(),
2298
- urn: z36.string()
2751
+ var resourceLinkTargetSchema = z39.object({
2752
+ sys: z39.object({
2753
+ type: z39.literal("ResourceLink"),
2754
+ linkType: z39.string(),
2755
+ urn: z39.string()
2299
2756
  })
2300
2757
  });
2301
- var richTextMarkSchema = z36.object({
2302
- type: z36.nativeEnum(MARKS)
2758
+ var richTextMarkSchema = z39.object({
2759
+ type: z39.nativeEnum(MARKS)
2303
2760
  });
2304
- var richTextTextNodeSchema = z36.object({
2305
- nodeType: z36.literal("text"),
2306
- value: z36.string(),
2307
- marks: z36.array(richTextMarkSchema),
2761
+ var richTextTextNodeSchema = z39.object({
2762
+ nodeType: z39.literal("text"),
2763
+ value: z39.string(),
2764
+ marks: z39.array(richTextMarkSchema),
2308
2765
  data: emptyNodeDataSchema
2309
2766
  });
2310
- var embeddedEntryBlockNodeSchema = z36.object({
2311
- nodeType: z36.literal(BLOCKS2.EMBEDDED_ENTRY),
2312
- data: z36.object({
2767
+ var embeddedEntryBlockNodeSchema = z39.object({
2768
+ nodeType: z39.literal(BLOCKS2.EMBEDDED_ENTRY),
2769
+ data: z39.object({
2313
2770
  target: entryLinkTargetSchema
2314
2771
  }),
2315
- content: z36.array(z36.never())
2772
+ content: z39.array(z39.never())
2316
2773
  });
2317
- var embeddedEntryInlineNodeSchema = z36.object({
2318
- nodeType: z36.literal(INLINES2.EMBEDDED_ENTRY),
2319
- data: z36.object({
2774
+ var embeddedEntryInlineNodeSchema = z39.object({
2775
+ nodeType: z39.literal(INLINES2.EMBEDDED_ENTRY),
2776
+ data: z39.object({
2320
2777
  target: entryLinkTargetSchema
2321
2778
  }),
2322
- content: z36.array(z36.never())
2779
+ content: z39.array(z39.never())
2323
2780
  });
2324
- var embeddedAssetBlockNodeSchema = z36.object({
2325
- nodeType: z36.literal(BLOCKS2.EMBEDDED_ASSET),
2326
- data: z36.object({
2781
+ var embeddedAssetBlockNodeSchema = z39.object({
2782
+ nodeType: z39.literal(BLOCKS2.EMBEDDED_ASSET),
2783
+ data: z39.object({
2327
2784
  target: assetLinkTargetSchema
2328
2785
  }),
2329
- content: z36.array(z36.never())
2786
+ content: z39.array(z39.never())
2330
2787
  });
2331
- var hyperlinkInlineNodeSchema = z36.object({
2332
- nodeType: z36.literal(INLINES2.HYPERLINK),
2333
- data: z36.object({
2334
- uri: z36.string().url()
2788
+ var hyperlinkInlineNodeSchema = z39.object({
2789
+ nodeType: z39.literal(INLINES2.HYPERLINK),
2790
+ data: z39.object({
2791
+ uri: z39.string().url()
2335
2792
  }),
2336
- content: z36.array(richTextTextNodeSchema)
2793
+ content: z39.array(richTextTextNodeSchema)
2337
2794
  });
2338
- var entryHyperlinkInlineNodeSchema = z36.object({
2339
- nodeType: z36.literal(INLINES2.ENTRY_HYPERLINK),
2340
- data: z36.object({
2795
+ var entryHyperlinkInlineNodeSchema = z39.object({
2796
+ nodeType: z39.literal(INLINES2.ENTRY_HYPERLINK),
2797
+ data: z39.object({
2341
2798
  target: entryLinkTargetSchema
2342
2799
  }),
2343
- content: z36.array(richTextTextNodeSchema)
2800
+ content: z39.array(richTextTextNodeSchema)
2344
2801
  });
2345
- var assetHyperlinkInlineNodeSchema = z36.object({
2346
- nodeType: z36.literal(INLINES2.ASSET_HYPERLINK),
2347
- data: z36.object({
2802
+ var assetHyperlinkInlineNodeSchema = z39.object({
2803
+ nodeType: z39.literal(INLINES2.ASSET_HYPERLINK),
2804
+ data: z39.object({
2348
2805
  target: assetLinkTargetSchema
2349
2806
  }),
2350
- content: z36.array(richTextTextNodeSchema)
2807
+ content: z39.array(richTextTextNodeSchema)
2351
2808
  });
2352
- var embeddedResourceBlockNodeSchema = z36.object({
2353
- nodeType: z36.literal(BLOCKS2.EMBEDDED_RESOURCE),
2354
- data: z36.object({
2809
+ var embeddedResourceBlockNodeSchema = z39.object({
2810
+ nodeType: z39.literal(BLOCKS2.EMBEDDED_RESOURCE),
2811
+ data: z39.object({
2355
2812
  target: resourceLinkTargetSchema
2356
2813
  }),
2357
- content: z36.array(z36.never())
2814
+ content: z39.array(z39.never())
2358
2815
  });
2359
- var embeddedResourceInlineNodeSchema = z36.object({
2360
- nodeType: z36.literal(INLINES2.EMBEDDED_RESOURCE),
2361
- data: z36.object({
2816
+ var embeddedResourceInlineNodeSchema = z39.object({
2817
+ nodeType: z39.literal(INLINES2.EMBEDDED_RESOURCE),
2818
+ data: z39.object({
2362
2819
  target: resourceLinkTargetSchema
2363
2820
  }),
2364
- content: z36.array(z36.never())
2821
+ content: z39.array(z39.never())
2365
2822
  });
2366
- var resourceHyperlinkInlineNodeSchema = z36.object({
2367
- nodeType: z36.literal(INLINES2.RESOURCE_HYPERLINK),
2368
- data: z36.object({
2823
+ var resourceHyperlinkInlineNodeSchema = z39.object({
2824
+ nodeType: z39.literal(INLINES2.RESOURCE_HYPERLINK),
2825
+ data: z39.object({
2369
2826
  target: resourceLinkTargetSchema
2370
2827
  }),
2371
- content: z36.array(richTextTextNodeSchema)
2828
+ content: z39.array(richTextTextNodeSchema)
2372
2829
  });
2373
- var richTextInlineNodeSchema = z36.lazy(
2374
- () => z36.union([
2830
+ var richTextInlineNodeSchema = z39.lazy(
2831
+ () => z39.union([
2375
2832
  richTextTextNodeSchema,
2376
2833
  embeddedEntryInlineNodeSchema,
2377
2834
  hyperlinkInlineNodeSchema,
@@ -2381,17 +2838,17 @@ var richTextInlineNodeSchema = z36.lazy(
2381
2838
  resourceHyperlinkInlineNodeSchema
2382
2839
  ])
2383
2840
  );
2384
- var paragraphNodeSchema = z36.lazy(
2385
- () => z36.object({
2386
- nodeType: z36.literal(BLOCKS2.PARAGRAPH),
2841
+ var paragraphNodeSchema = z39.lazy(
2842
+ () => z39.object({
2843
+ nodeType: z39.literal(BLOCKS2.PARAGRAPH),
2387
2844
  data: emptyNodeDataSchema,
2388
- content: z36.array(richTextInlineNodeSchema)
2845
+ content: z39.array(richTextInlineNodeSchema)
2389
2846
  })
2390
2847
  );
2391
- var headingNodeSchema = (headingNodeType) => z36.object({
2392
- nodeType: z36.literal(headingNodeType),
2848
+ var headingNodeSchema = (headingNodeType) => z39.object({
2849
+ nodeType: z39.literal(headingNodeType),
2393
2850
  data: emptyNodeDataSchema,
2394
- content: z36.array(richTextInlineNodeSchema)
2851
+ content: z39.array(richTextInlineNodeSchema)
2395
2852
  });
2396
2853
  var heading1NodeSchema = headingNodeSchema(BLOCKS2.HEADING_1);
2397
2854
  var heading2NodeSchema = headingNodeSchema(BLOCKS2.HEADING_2);
@@ -2399,56 +2856,56 @@ var heading3NodeSchema = headingNodeSchema(BLOCKS2.HEADING_3);
2399
2856
  var heading4NodeSchema = headingNodeSchema(BLOCKS2.HEADING_4);
2400
2857
  var heading5NodeSchema = headingNodeSchema(BLOCKS2.HEADING_5);
2401
2858
  var heading6NodeSchema = headingNodeSchema(BLOCKS2.HEADING_6);
2402
- var hrNodeSchema = z36.object({
2403
- nodeType: z36.literal(BLOCKS2.HR),
2859
+ var hrNodeSchema = z39.object({
2860
+ nodeType: z39.literal(BLOCKS2.HR),
2404
2861
  data: emptyNodeDataSchema,
2405
- content: z36.array(z36.never())
2862
+ content: z39.array(z39.never())
2406
2863
  });
2407
- var quoteNodeSchema = z36.object({
2408
- nodeType: z36.literal(BLOCKS2.QUOTE),
2864
+ var quoteNodeSchema = z39.object({
2865
+ nodeType: z39.literal(BLOCKS2.QUOTE),
2409
2866
  data: emptyNodeDataSchema,
2410
- content: z36.array(paragraphNodeSchema)
2867
+ content: z39.array(paragraphNodeSchema)
2411
2868
  });
2412
- var tableHeaderCellNodeSchema = z36.object({
2413
- nodeType: z36.literal(BLOCKS2.TABLE_HEADER_CELL),
2869
+ var tableHeaderCellNodeSchema = z39.object({
2870
+ nodeType: z39.literal(BLOCKS2.TABLE_HEADER_CELL),
2414
2871
  data: emptyNodeDataSchema,
2415
- content: z36.array(paragraphNodeSchema)
2872
+ content: z39.array(paragraphNodeSchema)
2416
2873
  });
2417
- var tableCellNodeSchema = z36.object({
2418
- nodeType: z36.literal(BLOCKS2.TABLE_CELL),
2874
+ var tableCellNodeSchema = z39.object({
2875
+ nodeType: z39.literal(BLOCKS2.TABLE_CELL),
2419
2876
  data: emptyNodeDataSchema,
2420
- content: z36.array(paragraphNodeSchema)
2877
+ content: z39.array(paragraphNodeSchema)
2421
2878
  });
2422
- var tableRowNodeSchema = z36.object({
2423
- nodeType: z36.literal(BLOCKS2.TABLE_ROW),
2879
+ var tableRowNodeSchema = z39.object({
2880
+ nodeType: z39.literal(BLOCKS2.TABLE_ROW),
2424
2881
  data: emptyNodeDataSchema,
2425
- content: z36.array(z36.union([tableHeaderCellNodeSchema, tableCellNodeSchema]))
2882
+ content: z39.array(z39.union([tableHeaderCellNodeSchema, tableCellNodeSchema]))
2426
2883
  });
2427
- var tableNodeSchema = z36.object({
2428
- nodeType: z36.literal(BLOCKS2.TABLE),
2884
+ var tableNodeSchema = z39.object({
2885
+ nodeType: z39.literal(BLOCKS2.TABLE),
2429
2886
  data: emptyNodeDataSchema,
2430
- content: z36.array(tableRowNodeSchema)
2887
+ content: z39.array(tableRowNodeSchema)
2431
2888
  });
2432
- var orderedListNodeSchema = z36.lazy(
2433
- () => z36.object({
2434
- nodeType: z36.literal(BLOCKS2.OL_LIST),
2889
+ var orderedListNodeSchema = z39.lazy(
2890
+ () => z39.object({
2891
+ nodeType: z39.literal(BLOCKS2.OL_LIST),
2435
2892
  data: emptyNodeDataSchema,
2436
- content: z36.array(listItemNodeSchema)
2893
+ content: z39.array(listItemNodeSchema)
2437
2894
  })
2438
2895
  );
2439
- var unorderedListNodeSchema = z36.lazy(
2440
- () => z36.object({
2441
- nodeType: z36.literal(BLOCKS2.UL_LIST),
2896
+ var unorderedListNodeSchema = z39.lazy(
2897
+ () => z39.object({
2898
+ nodeType: z39.literal(BLOCKS2.UL_LIST),
2442
2899
  data: emptyNodeDataSchema,
2443
- content: z36.array(listItemNodeSchema)
2900
+ content: z39.array(listItemNodeSchema)
2444
2901
  })
2445
2902
  );
2446
- var listItemNodeSchema = z36.lazy(
2447
- () => z36.object({
2448
- nodeType: z36.literal(BLOCKS2.LIST_ITEM),
2903
+ var listItemNodeSchema = z39.lazy(
2904
+ () => z39.object({
2905
+ nodeType: z39.literal(BLOCKS2.LIST_ITEM),
2449
2906
  data: emptyNodeDataSchema,
2450
- content: z36.array(
2451
- z36.union([
2907
+ content: z39.array(
2908
+ z39.union([
2452
2909
  paragraphNodeSchema,
2453
2910
  orderedListNodeSchema,
2454
2911
  unorderedListNodeSchema
@@ -2456,8 +2913,8 @@ var listItemNodeSchema = z36.lazy(
2456
2913
  )
2457
2914
  })
2458
2915
  );
2459
- var topLevelBlockNodeSchema = z36.lazy(
2460
- () => z36.union([
2916
+ var topLevelBlockNodeSchema = z39.lazy(
2917
+ () => z39.union([
2461
2918
  paragraphNodeSchema,
2462
2919
  heading1NodeSchema,
2463
2920
  heading2NodeSchema,
@@ -2475,56 +2932,56 @@ var topLevelBlockNodeSchema = z36.lazy(
2475
2932
  tableNodeSchema
2476
2933
  ])
2477
2934
  );
2478
- var richTextDocumentSchema = z36.object({
2479
- nodeType: z36.literal(BLOCKS2.DOCUMENT),
2935
+ var richTextDocumentSchema = z39.object({
2936
+ nodeType: z39.literal(BLOCKS2.DOCUMENT),
2480
2937
  data: emptyNodeDataSchema,
2481
- content: z36.array(topLevelBlockNodeSchema)
2938
+ content: z39.array(topLevelBlockNodeSchema)
2482
2939
  }).describe("Contentful Rich Text document");
2483
2940
 
2484
2941
  // src/types/entryFieldSchema.ts
2485
- var linkSchema = z37.object({
2486
- sys: z37.object({
2487
- type: z37.literal("Link"),
2488
- linkType: z37.enum(["Entry", "Asset"]),
2489
- id: z37.string()
2942
+ var linkSchema = z40.object({
2943
+ sys: z40.object({
2944
+ type: z40.literal("Link"),
2945
+ linkType: z40.enum(["Entry", "Asset"]),
2946
+ id: z40.string()
2490
2947
  })
2491
2948
  });
2492
- var resourceLinkSchema = z37.object({
2493
- sys: z37.object({
2494
- type: z37.literal("ResourceLink"),
2495
- linkType: z37.string(),
2496
- urn: z37.string()
2949
+ var resourceLinkSchema = z40.object({
2950
+ sys: z40.object({
2951
+ type: z40.literal("ResourceLink"),
2952
+ linkType: z40.string(),
2953
+ urn: z40.string()
2497
2954
  })
2498
2955
  });
2499
- var locationSchema = z37.object({
2500
- lat: z37.number(),
2501
- lon: z37.number()
2956
+ var locationSchema = z40.object({
2957
+ lat: z40.number(),
2958
+ lon: z40.number()
2502
2959
  });
2503
- var jsonPrimitive = z37.union([z37.string(), z37.number(), z37.boolean(), z37.null()]);
2504
- var jsonValueSchema = z37.lazy(
2505
- () => z37.union([jsonPrimitive, z37.array(jsonValueSchema), z37.record(jsonValueSchema)]).describe("Freeform JSON value (not for Rich Text)")
2960
+ var jsonPrimitive = z40.union([z40.string(), z40.number(), z40.boolean(), z40.null()]);
2961
+ var jsonValueSchema = z40.lazy(
2962
+ () => z40.union([jsonPrimitive, z40.array(jsonValueSchema), z40.record(jsonValueSchema)]).describe("Freeform JSON value (not for Rich Text)")
2506
2963
  );
2507
- var fieldValueSchema = z37.union([
2508
- z37.string().describe("Symbol, Text, or Date field"),
2509
- z37.number().describe("Integer or Number field"),
2510
- z37.boolean().describe("Boolean field"),
2964
+ var fieldValueSchema = z40.union([
2965
+ z40.string().describe("Symbol, Text, or Date field"),
2966
+ z40.number().describe("Integer or Number field"),
2967
+ z40.boolean().describe("Boolean field"),
2511
2968
  richTextDocumentSchema,
2512
2969
  linkSchema.describe("Link field (Entry or Asset reference)"),
2513
2970
  resourceLinkSchema.describe("ResourceLink field"),
2514
2971
  locationSchema.describe("Location field"),
2515
- z37.array(z37.string()).describe("Array field of Symbols"),
2516
- z37.array(linkSchema).describe("Array field of Links"),
2517
- z37.array(resourceLinkSchema).describe("Array field of ResourceLinks"),
2972
+ z40.array(z40.string()).describe("Array field of Symbols"),
2973
+ z40.array(linkSchema).describe("Array field of Links"),
2974
+ z40.array(resourceLinkSchema).describe("Array field of ResourceLinks"),
2518
2975
  jsonValueSchema
2519
2976
  ]);
2520
- var localizedFieldSchema = z37.record(fieldValueSchema);
2521
- var entryFieldsSchema = z37.record(localizedFieldSchema).describe(
2977
+ var localizedFieldSchema = z40.record(fieldValueSchema);
2978
+ var entryFieldsSchema = z40.record(localizedFieldSchema).describe(
2522
2979
  "Field values to update. Keys are field IDs, values are locale-keyed objects. Will be merged with existing fields."
2523
2980
  );
2524
2981
 
2525
2982
  // src/tools/entries/createEntry.ts
2526
2983
  var CreateEntryToolParams = BaseToolSchema.extend({
2527
- contentTypeId: z38.string().describe("The ID of the content type to create an entry for"),
2984
+ contentTypeId: z41.string().describe("The ID of the content type to create an entry for"),
2528
2985
  fields: entryFieldsSchema.describe(
2529
2986
  "The field values for the new entry. Keys should be field IDs and values should be the field content."
2530
2987
  ),
@@ -2532,6 +2989,10 @@ var CreateEntryToolParams = BaseToolSchema.extend({
2532
2989
  });
2533
2990
  function createEntryTool(config) {
2534
2991
  async function tool2(args) {
2992
+ assertEnvironmentNotProtected(
2993
+ args.environmentId,
2994
+ config.protectedEnvironments
2995
+ );
2535
2996
  const params = {
2536
2997
  spaceId: args.spaceId,
2537
2998
  environmentId: args.environmentId
@@ -2553,12 +3014,22 @@ function createEntryTool(config) {
2553
3014
  }
2554
3015
 
2555
3016
  // src/tools/entries/deleteEntry.ts
2556
- import { z as z39 } from "zod";
3017
+ import { z as z42 } from "zod";
2557
3018
  var DeleteEntryToolParams = BaseToolSchema.extend({
2558
- entryId: z39.string().describe("The ID of the entry to delete")
3019
+ entryId: z42.string().describe("The ID of the entry to delete"),
3020
+ confirm: z42.boolean().optional().describe(
3021
+ "Set to true on the second call to actually perform the deletion. Required together with confirmToken."
3022
+ ),
3023
+ confirmToken: z42.string().optional().describe(
3024
+ "Token returned by the preview call; must be supplied with confirm: true."
3025
+ )
2559
3026
  });
2560
3027
  function deleteEntryTool(config) {
2561
3028
  async function tool2(args) {
3029
+ assertEnvironmentNotProtected(
3030
+ args.environmentId,
3031
+ config.protectedEnvironments
3032
+ );
2562
3033
  const params = {
2563
3034
  spaceId: args.spaceId,
2564
3035
  environmentId: args.environmentId,
@@ -2566,6 +3037,22 @@ function deleteEntryTool(config) {
2566
3037
  };
2567
3038
  const contentfulClient = createToolClient(config, args);
2568
3039
  const entry = await contentfulClient.entry.get(params);
3040
+ const expectedToken = buildConfirmToken(
3041
+ "entry",
3042
+ args.entryId,
3043
+ entry.sys.version
3044
+ );
3045
+ if (args.confirm !== true || args.confirmToken !== expectedToken) {
3046
+ return createSuccessResponse(
3047
+ `${CONFIRMATION_MESSAGE_PREFIX} entry`,
3048
+ buildConfirmationPreview(
3049
+ "entry",
3050
+ args.entryId,
3051
+ { entry },
3052
+ expectedToken
3053
+ )
3054
+ );
3055
+ }
2569
3056
  await contentfulClient.entry.delete(params);
2570
3057
  return createSuccessResponse("Entry deleted successfully", { entry });
2571
3058
  }
@@ -2573,9 +3060,9 @@ function deleteEntryTool(config) {
2573
3060
  }
2574
3061
 
2575
3062
  // src/tools/entries/updateEntry.ts
2576
- import { z as z40 } from "zod";
3063
+ import { z as z43 } from "zod";
2577
3064
  var UpdateEntryToolParams = BaseToolSchema.extend({
2578
- entryId: z40.string().describe("The ID of the entry to update"),
3065
+ entryId: z43.string().describe("The ID of the entry to update"),
2579
3066
  fields: entryFieldsSchema.describe(
2580
3067
  "The field values to update. Keys should be field IDs and values should be the field content. Will be merged with existing fields."
2581
3068
  ),
@@ -2583,6 +3070,10 @@ var UpdateEntryToolParams = BaseToolSchema.extend({
2583
3070
  });
2584
3071
  function updateEntryTool(config) {
2585
3072
  async function tool2(args) {
3073
+ assertEnvironmentNotProtected(
3074
+ args.environmentId,
3075
+ config.protectedEnvironments
3076
+ );
2586
3077
  const params = {
2587
3078
  spaceId: args.spaceId,
2588
3079
  environmentId: args.environmentId,
@@ -2618,9 +3109,9 @@ function updateEntryTool(config) {
2618
3109
  }
2619
3110
 
2620
3111
  // src/tools/entries/getEntry.ts
2621
- import { z as z41 } from "zod";
3112
+ import { z as z44 } from "zod";
2622
3113
  var GetEntryToolParams = BaseToolSchema.extend({
2623
- entryId: z41.string().describe("The ID of the entry to retrieve")
3114
+ entryId: z44.string().describe("The ID of the entry to retrieve")
2624
3115
  });
2625
3116
  function getEntryTool(config) {
2626
3117
  async function tool2(args) {
@@ -2637,20 +3128,40 @@ function getEntryTool(config) {
2637
3128
  }
2638
3129
 
2639
3130
  // src/tools/entries/publishEntry.ts
2640
- import { z as z42 } from "zod";
3131
+ import { z as z45 } from "zod";
2641
3132
  var PublishEntryToolParams = BaseToolSchema.extend({
2642
- entryId: z42.union([z42.string(), z42.array(z42.string()).max(100)]).describe(
2643
- "The ID of the entry to publish (string) or an array of entry IDs (up to 100 entries)"
3133
+ entryId: z45.array(z45.string()).min(1).max(100).describe(
3134
+ "Array of entry IDs to publish. Single-element array for one entry, or up to MAX_BULK_SIZE per call (default 10, max 100 \u2014 configurable via MAX_BULK_SIZE env var)."
3135
+ ),
3136
+ dryRun: z45.boolean().optional().describe(
3137
+ "When true, returns a preview of the operation without executing it. Still subject to MAX_BULK_SIZE \u2014 use this to confirm intent for within-limit calls."
2644
3138
  )
2645
3139
  });
2646
3140
  function publishEntryTool(config) {
2647
3141
  async function tool2(args) {
3142
+ assertEnvironmentNotProtected(
3143
+ args.environmentId,
3144
+ config.protectedEnvironments
3145
+ );
3146
+ const entryIds = args.entryId;
3147
+ assertBulkSizeAllowed(entryIds.length, config.maxBulkSize);
3148
+ if (args.dryRun) {
3149
+ return createSuccessResponse(
3150
+ "Dry run: no changes were made",
3151
+ buildDryRunPreview({
3152
+ operation: "publish",
3153
+ entityType: "entry",
3154
+ ids: entryIds,
3155
+ spaceId: args.spaceId,
3156
+ environmentId: args.environmentId
3157
+ })
3158
+ );
3159
+ }
2648
3160
  const baseParams = {
2649
3161
  spaceId: args.spaceId,
2650
3162
  environmentId: args.environmentId
2651
3163
  };
2652
3164
  const contentfulClient = createToolClient(config, args);
2653
- const entryIds = Array.isArray(args.entryId) ? args.entryId : [args.entryId];
2654
3165
  if (entryIds.length === 1) {
2655
3166
  const entryId = entryIds[0];
2656
3167
  const params = {
@@ -2658,7 +3169,10 @@ function publishEntryTool(config) {
2658
3169
  entryId
2659
3170
  };
2660
3171
  const entry = await contentfulClient.entry.get(params);
2661
- const publishedEntry = await contentfulClient.entry.publish(params, entry);
3172
+ const publishedEntry = await contentfulClient.entry.publish(
3173
+ params,
3174
+ entry
3175
+ );
2662
3176
  return createSuccessResponse("Entry published successfully", {
2663
3177
  status: publishedEntry.sys.status,
2664
3178
  entryId
@@ -2687,20 +3201,40 @@ function publishEntryTool(config) {
2687
3201
  }
2688
3202
 
2689
3203
  // src/tools/entries/unpublishEntry.ts
2690
- import { z as z43 } from "zod";
3204
+ import { z as z46 } from "zod";
2691
3205
  var UnpublishEntryToolParams = BaseToolSchema.extend({
2692
- entryId: z43.union([z43.string(), z43.array(z43.string()).max(100)]).describe(
2693
- "The ID of the entry to unpublish (string) or an array of entry IDs (up to 100 entries)"
3206
+ entryId: z46.array(z46.string()).min(1).max(100).describe(
3207
+ "Array of entry IDs to unpublish. Single-element array for one entry, or up to MAX_BULK_SIZE per call (default 10, max 100 \u2014 configurable via MAX_BULK_SIZE env var)."
3208
+ ),
3209
+ dryRun: z46.boolean().optional().describe(
3210
+ "When true, returns a preview of the operation without executing it. Still subject to MAX_BULK_SIZE \u2014 use this to confirm intent for within-limit calls."
2694
3211
  )
2695
3212
  });
2696
3213
  function unpublishEntryTool(config) {
2697
3214
  async function tool2(args) {
3215
+ assertEnvironmentNotProtected(
3216
+ args.environmentId,
3217
+ config.protectedEnvironments
3218
+ );
3219
+ const entryIds = args.entryId;
3220
+ assertBulkSizeAllowed(entryIds.length, config.maxBulkSize);
3221
+ if (args.dryRun) {
3222
+ return createSuccessResponse(
3223
+ "Dry run: no changes were made",
3224
+ buildDryRunPreview({
3225
+ operation: "unpublish",
3226
+ entityType: "entry",
3227
+ ids: entryIds,
3228
+ spaceId: args.spaceId,
3229
+ environmentId: args.environmentId
3230
+ })
3231
+ );
3232
+ }
2698
3233
  const baseParams = {
2699
3234
  spaceId: args.spaceId,
2700
3235
  environmentId: args.environmentId
2701
3236
  };
2702
3237
  const contentfulClient = createToolClient(config, args);
2703
- const entryIds = Array.isArray(args.entryId) ? args.entryId : [args.entryId];
2704
3238
  if (entryIds.length === 1) {
2705
3239
  const entryId = entryIds[0];
2706
3240
  const params = {
@@ -2740,20 +3274,40 @@ function unpublishEntryTool(config) {
2740
3274
  }
2741
3275
 
2742
3276
  // src/tools/entries/archiveEntry.ts
2743
- import { z as z44 } from "zod";
3277
+ import { z as z47 } from "zod";
2744
3278
  var ArchiveEntryToolParams = BaseToolSchema.extend({
2745
- entryId: z44.union([z44.string(), z44.array(z44.string()).max(100)]).describe(
2746
- "The ID of the entry to archive (string) or an array of entry IDs (up to 100 entries)"
3279
+ entryId: z47.array(z47.string()).min(1).max(100).describe(
3280
+ "Array of entry IDs to archive. Single-element array for one entry, or up to MAX_BULK_SIZE per call (default 10, max 100 \u2014 configurable via MAX_BULK_SIZE env var)."
3281
+ ),
3282
+ dryRun: z47.boolean().optional().describe(
3283
+ "When true, returns a preview of the operation without executing it. Still subject to MAX_BULK_SIZE \u2014 use this to confirm intent for within-limit calls."
2747
3284
  )
2748
3285
  });
2749
3286
  function archiveEntryTool(config) {
2750
3287
  async function tool2(args) {
3288
+ assertEnvironmentNotProtected(
3289
+ args.environmentId,
3290
+ config.protectedEnvironments
3291
+ );
3292
+ const entryIds = args.entryId;
3293
+ assertBulkSizeAllowed(entryIds.length, config.maxBulkSize);
3294
+ if (args.dryRun) {
3295
+ return createSuccessResponse(
3296
+ "Dry run: no changes were made",
3297
+ buildDryRunPreview({
3298
+ operation: "archive",
3299
+ entityType: "entry",
3300
+ ids: entryIds,
3301
+ spaceId: args.spaceId,
3302
+ environmentId: args.environmentId
3303
+ })
3304
+ );
3305
+ }
2751
3306
  const baseParams = {
2752
3307
  spaceId: args.spaceId,
2753
3308
  environmentId: args.environmentId
2754
3309
  };
2755
3310
  const contentfulClient = createToolClient(config, args);
2756
- const entryIds = Array.isArray(args.entryId) ? args.entryId : [args.entryId];
2757
3311
  const successfullyArchived = [];
2758
3312
  for (const entryId of entryIds) {
2759
3313
  try {
@@ -2786,20 +3340,40 @@ function archiveEntryTool(config) {
2786
3340
  }
2787
3341
 
2788
3342
  // src/tools/entries/unarchiveEntry.ts
2789
- import { z as z45 } from "zod";
3343
+ import { z as z48 } from "zod";
2790
3344
  var UnarchiveEntryToolParams = BaseToolSchema.extend({
2791
- entryId: z45.union([z45.string(), z45.array(z45.string()).max(100)]).describe(
2792
- "The ID of the entry to unarchive (string) or an array of entry IDs (up to 100 entries)"
3345
+ entryId: z48.array(z48.string()).min(1).max(100).describe(
3346
+ "Array of entry IDs to unarchive. Single-element array for one entry, or up to MAX_BULK_SIZE per call (default 10, max 100 \u2014 configurable via MAX_BULK_SIZE env var)."
3347
+ ),
3348
+ dryRun: z48.boolean().optional().describe(
3349
+ "When true, returns a preview of the operation without executing it. Still subject to MAX_BULK_SIZE \u2014 use this to confirm intent for within-limit calls."
2793
3350
  )
2794
3351
  });
2795
3352
  function unarchiveEntryTool(config) {
2796
3353
  async function tool2(args) {
3354
+ assertEnvironmentNotProtected(
3355
+ args.environmentId,
3356
+ config.protectedEnvironments
3357
+ );
3358
+ const entryIds = args.entryId;
3359
+ assertBulkSizeAllowed(entryIds.length, config.maxBulkSize);
3360
+ if (args.dryRun) {
3361
+ return createSuccessResponse(
3362
+ "Dry run: no changes were made",
3363
+ buildDryRunPreview({
3364
+ operation: "unarchive",
3365
+ entityType: "entry",
3366
+ ids: entryIds,
3367
+ spaceId: args.spaceId,
3368
+ environmentId: args.environmentId
3369
+ })
3370
+ );
3371
+ }
2797
3372
  const baseParams = {
2798
3373
  spaceId: args.spaceId,
2799
3374
  environmentId: args.environmentId
2800
3375
  };
2801
3376
  const contentfulClient = createToolClient(config, args);
2802
- const entryIds = Array.isArray(args.entryId) ? args.entryId : [args.entryId];
2803
3377
  const successfullyUnarchived = [];
2804
3378
  for (const entryId of entryIds) {
2805
3379
  try {
@@ -2889,12 +3463,12 @@ function createEntryTools(config) {
2889
3463
  },
2890
3464
  deleteEntry: {
2891
3465
  title: "delete_entry",
2892
- description: "Delete a specific content entry from your Contentful space",
3466
+ description: "Delete a specific content entry from your Contentful space. This is a two-phase operation: the first call (without confirm/confirmToken) returns a preview of the entry and a confirmToken. To complete the deletion, call this tool again with the same entryId, confirm: true, and the confirmToken from the preview response.",
2893
3467
  inputParams: DeleteEntryToolParams.shape,
2894
3468
  annotations: {
2895
3469
  readOnlyHint: false,
2896
3470
  destructiveHint: true,
2897
- idempotentHint: true,
3471
+ idempotentHint: false,
2898
3472
  openWorldHint: false
2899
3473
  },
2900
3474
  tool: deleteEntry
@@ -2951,16 +3525,20 @@ function createEntryTools(config) {
2951
3525
  }
2952
3526
 
2953
3527
  // src/tools/environments/createEnvironment.ts
2954
- import { z as z46 } from "zod";
3528
+ import { z as z49 } from "zod";
2955
3529
  var CreateEnvironmentToolParams = BaseToolSchema.extend({
2956
- environmentId: z46.string().describe("The ID of the environment to create"),
2957
- name: z46.string().describe("The name of the environment to create"),
2958
- sourceEnvironmentId: z46.string().describe(
3530
+ environmentId: z49.string().describe("The ID of the environment to create"),
3531
+ name: z49.string().describe("The name of the environment to create"),
3532
+ sourceEnvironmentId: z49.string().describe(
2959
3533
  "The ID of the source environment to clone from (defaults to master)"
2960
3534
  ).optional()
2961
3535
  });
2962
3536
  function createEnvironmentTool(config) {
2963
3537
  async function tool2(args) {
3538
+ assertEnvironmentNotProtected(
3539
+ args.environmentId,
3540
+ config.protectedEnvironments
3541
+ );
2964
3542
  const contentfulClient = createToolClient(config, args);
2965
3543
  const environment = await contentfulClient.environment.createWithId(
2966
3544
  {
@@ -2982,15 +3560,15 @@ function createEnvironmentTool(config) {
2982
3560
  }
2983
3561
 
2984
3562
  // src/tools/environments/listEnvironments.ts
2985
- import { z as z47 } from "zod";
3563
+ import { z as z50 } from "zod";
2986
3564
  var ListEnvironmentsToolParams = BaseToolSchema.extend({
2987
- environmentId: z47.string().optional().describe(
3565
+ environmentId: z50.string().optional().describe(
2988
3566
  "The ID of the Contentful environment (not required for listing)"
2989
3567
  ),
2990
- limit: z47.number().optional().describe("Maximum number of environments to return (max 10)"),
2991
- skip: z47.number().optional().describe("Skip this many environments for pagination"),
2992
- select: z47.string().optional().describe("Comma-separated list of fields to return"),
2993
- order: z47.string().optional().describe("Order environments by this field")
3568
+ limit: z50.number().optional().describe("Maximum number of environments to return (max 10)"),
3569
+ skip: z50.number().optional().describe("Skip this many environments for pagination"),
3570
+ select: z50.string().optional().describe("Comma-separated list of fields to return"),
3571
+ order: z50.string().optional().describe("Order environments by this field")
2994
3572
  });
2995
3573
  function listEnvironmentsTool(config) {
2996
3574
  async function tool2(args) {
@@ -3036,17 +3614,44 @@ function listEnvironmentsTool(config) {
3036
3614
  }
3037
3615
 
3038
3616
  // src/tools/environments/deleteEnvironment.ts
3039
- import { z as z48 } from "zod";
3617
+ import { z as z51 } from "zod";
3040
3618
  var DeleteEnvironmentToolParams = BaseToolSchema.extend({
3041
- environmentId: z48.string().describe("The ID of the environment to delete")
3619
+ environmentId: z51.string().describe("The ID of the environment to delete"),
3620
+ confirm: z51.boolean().optional().describe(
3621
+ "Set to true on the second call to actually perform the deletion. Required together with confirmToken."
3622
+ ),
3623
+ confirmToken: z51.string().optional().describe(
3624
+ "Token returned by the preview call; must be supplied with confirm: true."
3625
+ )
3042
3626
  });
3043
3627
  function deleteEnvironmentTool(config) {
3044
3628
  async function tool2(args) {
3629
+ assertEnvironmentNotProtected(
3630
+ args.environmentId,
3631
+ config.protectedEnvironments
3632
+ );
3045
3633
  const params = {
3046
3634
  spaceId: args.spaceId,
3047
3635
  environmentId: args.environmentId
3048
3636
  };
3049
3637
  const contentfulClient = createToolClient(config, args);
3638
+ const environment = await contentfulClient.environment.get(params);
3639
+ const expectedToken = buildConfirmToken(
3640
+ "environment",
3641
+ args.environmentId,
3642
+ environment.sys.version
3643
+ );
3644
+ if (args.confirm !== true || args.confirmToken !== expectedToken) {
3645
+ return createSuccessResponse(
3646
+ `${CONFIRMATION_MESSAGE_PREFIX} environment`,
3647
+ buildConfirmationPreview(
3648
+ "environment",
3649
+ args.environmentId,
3650
+ { environment },
3651
+ expectedToken
3652
+ )
3653
+ );
3654
+ }
3050
3655
  await contentfulClient.environment.delete(params);
3051
3656
  return createSuccessResponse("Environment deleted successfully", {
3052
3657
  environmentId: args.environmentId
@@ -3085,12 +3690,12 @@ function createEnvironmentTools(config) {
3085
3690
  },
3086
3691
  deleteEnvironment: {
3087
3692
  title: "delete_environment",
3088
- description: "Delete an environment",
3693
+ description: "Delete an environment from your Contentful space. This is a two-phase operation: the first call (without confirm/confirmToken) returns a preview and a confirmToken. To complete the deletion, call this tool again with the same environmentId, confirm: true, and the confirmToken from the preview response.",
3089
3694
  inputParams: DeleteEnvironmentToolParams.shape,
3090
3695
  annotations: {
3091
3696
  readOnlyHint: false,
3092
3697
  destructiveHint: true,
3093
- idempotentHint: true,
3698
+ idempotentHint: false,
3094
3699
  openWorldHint: false
3095
3700
  },
3096
3701
  tool: deleteEnvironment
@@ -3099,9 +3704,9 @@ function createEnvironmentTools(config) {
3099
3704
  }
3100
3705
 
3101
3706
  // src/tools/locales/getLocale.ts
3102
- import { z as z49 } from "zod";
3707
+ import { z as z52 } from "zod";
3103
3708
  var GetLocaleToolParams = BaseToolSchema.extend({
3104
- localeId: z49.string().describe("The ID of the locale to retrieve")
3709
+ localeId: z52.string().describe("The ID of the locale to retrieve")
3105
3710
  });
3106
3711
  function getLocaleTool(config) {
3107
3712
  async function tool2(args) {
@@ -3118,24 +3723,28 @@ function getLocaleTool(config) {
3118
3723
  }
3119
3724
 
3120
3725
  // src/tools/locales/createLocale.ts
3121
- import { z as z50 } from "zod";
3726
+ import { z as z53 } from "zod";
3122
3727
  var CreateLocaleToolParams = BaseToolSchema.extend({
3123
- name: z50.string().describe("The name of the locale"),
3124
- code: z50.string().describe('The locale code (e.g., "en-US")'),
3125
- fallbackCode: z50.string().nullable().describe(
3728
+ name: z53.string().describe("The name of the locale"),
3729
+ code: z53.string().describe('The locale code (e.g., "en-US")'),
3730
+ fallbackCode: z53.string().nullable().describe(
3126
3731
  "The locale code to fallback to when there is no content for the current locale"
3127
3732
  ),
3128
- contentDeliveryApi: z50.boolean().optional().default(true).describe(
3733
+ contentDeliveryApi: z53.boolean().optional().default(true).describe(
3129
3734
  "If the content under this locale should be available on the CDA (for public reading)"
3130
3735
  ),
3131
- contentManagementApi: z50.boolean().optional().default(true).describe(
3736
+ contentManagementApi: z53.boolean().optional().default(true).describe(
3132
3737
  "If the content under this locale should be available on the CMA (for editing)"
3133
3738
  ),
3134
- default: z50.boolean().optional().default(false).describe("If this is the default locale"),
3135
- optional: z50.boolean().optional().default(false).describe("If the locale needs to be filled in on entries or not")
3739
+ default: z53.boolean().optional().default(false).describe("If this is the default locale"),
3740
+ optional: z53.boolean().optional().default(false).describe("If the locale needs to be filled in on entries or not")
3136
3741
  });
3137
3742
  function createLocaleTool(config) {
3138
3743
  async function tool2(args) {
3744
+ assertEnvironmentNotProtected(
3745
+ args.environmentId,
3746
+ config.protectedEnvironments
3747
+ );
3139
3748
  const params = {
3140
3749
  spaceId: args.spaceId,
3141
3750
  environmentId: args.environmentId
@@ -3155,13 +3764,13 @@ function createLocaleTool(config) {
3155
3764
  }
3156
3765
 
3157
3766
  // src/tools/locales/listLocales.ts
3158
- import { z as z51 } from "zod";
3767
+ import { z as z54 } from "zod";
3159
3768
  var ListLocaleToolParams = BaseToolSchema.extend({
3160
- limit: z51.number().optional().describe("Maximum number of locales to return"),
3161
- skip: z51.number().optional().describe("Skip this many locales for pagination"),
3162
- select: z51.string().optional().describe("Comma-separated list of fields to return"),
3163
- include: z51.number().optional().describe("Include this many levels of linked entries"),
3164
- order: z51.string().optional().describe("Order locales by this field")
3769
+ limit: z54.number().optional().describe("Maximum number of locales to return"),
3770
+ skip: z54.number().optional().describe("Skip this many locales for pagination"),
3771
+ select: z54.string().optional().describe("Comma-separated list of fields to return"),
3772
+ include: z54.number().optional().describe("Include this many levels of linked entries"),
3773
+ order: z54.string().optional().describe("Order locales by this field")
3165
3774
  });
3166
3775
  function listLocaleTool(config) {
3167
3776
  async function tool2(args) {
@@ -3214,27 +3823,31 @@ function listLocaleTool(config) {
3214
3823
  }
3215
3824
 
3216
3825
  // src/tools/locales/updateLocale.ts
3217
- import { z as z52 } from "zod";
3826
+ import { z as z55 } from "zod";
3218
3827
  var UpdateLocaleToolParams = BaseToolSchema.extend({
3219
- localeId: z52.string().describe("The ID of the locale to update"),
3220
- fields: z52.object({
3221
- name: z52.string().optional().describe("The name of the locale"),
3828
+ localeId: z55.string().describe("The ID of the locale to update"),
3829
+ fields: z55.object({
3830
+ name: z55.string().optional().describe("The name of the locale"),
3222
3831
  // NOTE: internal_code changes are not allowed
3223
- code: z52.string().optional().describe("The code of the locale"),
3224
- fallbackCode: z52.string().optional().describe(
3832
+ code: z55.string().optional().describe("The code of the locale"),
3833
+ fallbackCode: z55.string().optional().describe(
3225
3834
  "The locale code to fallback to when there is no content for the current locale"
3226
3835
  ),
3227
- contentDeliveryApi: z52.boolean().optional().describe(
3836
+ contentDeliveryApi: z55.boolean().optional().describe(
3228
3837
  "If the content under this locale should be available on the CDA (for public reading)"
3229
3838
  ),
3230
- contentManagementApi: z52.boolean().optional().describe(
3839
+ contentManagementApi: z55.boolean().optional().describe(
3231
3840
  "If the content under this locale should be available on the CMA (for editing)"
3232
3841
  ),
3233
- optional: z52.boolean().optional().describe("If the locale needs to be filled in on entries or not")
3842
+ optional: z55.boolean().optional().describe("If the locale needs to be filled in on entries or not")
3234
3843
  })
3235
3844
  });
3236
3845
  function updateLocaleTool(config) {
3237
3846
  async function tool2(args) {
3847
+ assertEnvironmentNotProtected(
3848
+ args.environmentId,
3849
+ config.protectedEnvironments
3850
+ );
3238
3851
  const params = {
3239
3852
  spaceId: args.spaceId,
3240
3853
  environmentId: args.environmentId,
@@ -3256,12 +3869,22 @@ function updateLocaleTool(config) {
3256
3869
  }
3257
3870
 
3258
3871
  // src/tools/locales/deleteLocale.ts
3259
- import { z as z53 } from "zod";
3872
+ import { z as z56 } from "zod";
3260
3873
  var DeleteLocaleToolParams = BaseToolSchema.extend({
3261
- localeId: z53.string().describe("The ID of the locale to delete")
3874
+ localeId: z56.string().describe("The ID of the locale to delete"),
3875
+ confirm: z56.boolean().optional().describe(
3876
+ "Set to true on the second call to actually perform the deletion. Required together with confirmToken."
3877
+ ),
3878
+ confirmToken: z56.string().optional().describe(
3879
+ "Token returned by the preview call; must be supplied with confirm: true."
3880
+ )
3262
3881
  });
3263
3882
  function deleteLocaleTool(config) {
3264
3883
  async function tool2(args) {
3884
+ assertEnvironmentNotProtected(
3885
+ args.environmentId,
3886
+ config.protectedEnvironments
3887
+ );
3265
3888
  const params = {
3266
3889
  spaceId: args.spaceId,
3267
3890
  environmentId: args.environmentId,
@@ -3269,6 +3892,22 @@ function deleteLocaleTool(config) {
3269
3892
  };
3270
3893
  const contentfulClient = createToolClient(config, args);
3271
3894
  const locale = await contentfulClient.locale.get(params);
3895
+ const expectedToken = buildConfirmToken(
3896
+ "locale",
3897
+ args.localeId,
3898
+ locale.sys.version
3899
+ );
3900
+ if (args.confirm !== true || args.confirmToken !== expectedToken) {
3901
+ return createSuccessResponse(
3902
+ `${CONFIRMATION_MESSAGE_PREFIX} locale`,
3903
+ buildConfirmationPreview(
3904
+ "locale",
3905
+ args.localeId,
3906
+ { locale },
3907
+ expectedToken
3908
+ )
3909
+ );
3910
+ }
3272
3911
  await contentfulClient.locale.delete(params);
3273
3912
  return createSuccessResponse("Locale deleted successfully", { locale });
3274
3913
  }
@@ -3329,12 +3968,12 @@ function createLocaleTools(config) {
3329
3968
  },
3330
3969
  deleteLocale: {
3331
3970
  title: "delete_locale",
3332
- description: "Delete a specific locale from your Contentful environment. This operation permanently removes the locale and cannot be undone.",
3971
+ description: "Delete a specific locale from your Contentful environment. This is a two-phase operation: the first call (without confirm/confirmToken) returns a preview of the locale and a confirmToken. To complete the deletion, call this tool again with the same localeId, confirm: true, and the confirmToken from the preview response.",
3333
3972
  inputParams: DeleteLocaleToolParams.shape,
3334
3973
  annotations: {
3335
3974
  readOnlyHint: false,
3336
3975
  destructiveHint: true,
3337
- idempotentHint: true,
3976
+ idempotentHint: false,
3338
3977
  openWorldHint: false
3339
3978
  },
3340
3979
  tool: deleteLocale
@@ -3343,13 +3982,13 @@ function createLocaleTools(config) {
3343
3982
  }
3344
3983
 
3345
3984
  // src/tools/orgs/listOrgs.ts
3346
- import { z as z54 } from "zod";
3985
+ import { z as z57 } from "zod";
3347
3986
  import { createClient as createClient2 } from "contentful-management";
3348
- var ListOrgsToolParams = z54.object({
3349
- limit: z54.number().optional().describe("Maximum number of organizations to return (max 10)"),
3350
- skip: z54.number().optional().describe("Skip this many organizations for pagination"),
3351
- select: z54.string().optional().describe("Comma-separated list of fields to return"),
3352
- order: z54.string().optional().describe("Order organizations by this field")
3987
+ var ListOrgsToolParams = z57.object({
3988
+ limit: z57.number().optional().describe("Maximum number of organizations to return (max 10)"),
3989
+ skip: z57.number().optional().describe("Skip this many organizations for pagination"),
3990
+ select: z57.string().optional().describe("Comma-separated list of fields to return"),
3991
+ order: z57.string().optional().describe("Order organizations by this field")
3353
3992
  });
3354
3993
  function listOrgsTool(config) {
3355
3994
  async function tool2(args) {
@@ -3391,10 +4030,10 @@ function listOrgsTool(config) {
3391
4030
  }
3392
4031
 
3393
4032
  // src/tools/orgs/getOrg.ts
3394
- import { z as z55 } from "zod";
4033
+ import { z as z58 } from "zod";
3395
4034
  import { createClient as createClient3 } from "contentful-management";
3396
- var GetOrgToolParams = z55.object({
3397
- organizationId: z55.string().describe("The ID of the organization to retrieve")
4035
+ var GetOrgToolParams = z58.object({
4036
+ organizationId: z58.string().describe("The ID of the organization to retrieve")
3398
4037
  });
3399
4038
  function getOrgTool(config) {
3400
4039
  async function tool2(args) {
@@ -3440,13 +4079,13 @@ function createOrgTools(config) {
3440
4079
  }
3441
4080
 
3442
4081
  // src/tools/spaces/listSpaces.ts
3443
- import { z as z56 } from "zod";
4082
+ import { z as z59 } from "zod";
3444
4083
  import { createClient as createClient4 } from "contentful-management";
3445
- var ListSpacesToolParams = z56.object({
3446
- limit: z56.number().optional().describe("Maximum number of spaces to return (max 10)"),
3447
- skip: z56.number().optional().describe("Skip this many spaces for pagination"),
3448
- select: z56.string().optional().describe("Comma-separated list of fields to return"),
3449
- order: z56.string().optional().describe("Order spaces by this field")
4084
+ var ListSpacesToolParams = z59.object({
4085
+ limit: z59.number().optional().describe("Maximum number of spaces to return (max 10)"),
4086
+ skip: z59.number().optional().describe("Skip this many spaces for pagination"),
4087
+ select: z59.string().optional().describe("Comma-separated list of fields to return"),
4088
+ order: z59.string().optional().describe("Order spaces by this field")
3450
4089
  });
3451
4090
  function listSpacesTool(config) {
3452
4091
  async function tool2(args) {
@@ -3488,10 +4127,10 @@ function listSpacesTool(config) {
3488
4127
  }
3489
4128
 
3490
4129
  // src/tools/spaces/getSpace.ts
3491
- import { z as z57 } from "zod";
4130
+ import { z as z60 } from "zod";
3492
4131
  import { createClient as createClient5 } from "contentful-management";
3493
- var GetSpaceToolParams = z57.object({
3494
- spaceId: z57.string().describe("The ID of the space to retrieve")
4132
+ var GetSpaceToolParams = z60.object({
4133
+ spaceId: z60.string().describe("The ID of the space to retrieve")
3495
4134
  });
3496
4135
  function getSpaceTool(config) {
3497
4136
  async function tool2(args) {
@@ -3535,12 +4174,12 @@ function createSpaceTools(config) {
3535
4174
  }
3536
4175
 
3537
4176
  // src/tools/tags/listTags.ts
3538
- import { z as z58 } from "zod";
4177
+ import { z as z61 } from "zod";
3539
4178
  var ListTagsToolParams = BaseToolSchema.extend({
3540
- limit: z58.number().optional().describe("Maximum number of tags to return"),
3541
- skip: z58.number().optional().describe("Skip this many tags for pagination"),
3542
- select: z58.string().optional().describe("Comma-separated list of fields to return"),
3543
- order: z58.string().optional().describe("Order tags by this field")
4179
+ limit: z61.number().optional().describe("Maximum number of tags to return"),
4180
+ skip: z61.number().optional().describe("Skip this many tags for pagination"),
4181
+ select: z61.string().optional().describe("Comma-separated list of fields to return"),
4182
+ order: z61.string().optional().describe("Order tags by this field")
3544
4183
  });
3545
4184
  function listTagsTool(config) {
3546
4185
  async function tool2(args) {
@@ -3586,14 +4225,18 @@ function listTagsTool(config) {
3586
4225
  }
3587
4226
 
3588
4227
  // src/tools/tags/createTag.ts
3589
- import { z as z59 } from "zod";
4228
+ import { z as z62 } from "zod";
3590
4229
  var CreateTagToolParams = BaseToolSchema.extend({
3591
- name: z59.string().describe("The name of the tag"),
3592
- id: z59.string().describe("The ID of the tag"),
3593
- visibility: z59.enum(["public", "private"]).describe("The visibility of the tag. Default to private if not specified")
4230
+ name: z62.string().describe("The name of the tag"),
4231
+ id: z62.string().describe("The ID of the tag"),
4232
+ visibility: z62.enum(["public", "private"]).describe("The visibility of the tag. Default to private if not specified")
3594
4233
  });
3595
4234
  function createTagTool(config) {
3596
4235
  async function tool2(args) {
4236
+ assertEnvironmentNotProtected(
4237
+ args.environmentId,
4238
+ config.protectedEnvironments
4239
+ );
3597
4240
  const params = {
3598
4241
  spaceId: args.spaceId,
3599
4242
  environmentId: args.environmentId,
@@ -3640,34 +4283,34 @@ function createTagTools(config) {
3640
4283
  }
3641
4284
 
3642
4285
  // src/tools/taxonomies/concept-schemes/createConceptScheme.ts
3643
- import { z as z61 } from "zod";
4286
+ import { z as z64 } from "zod";
3644
4287
  import { createClient as createClient6 } from "contentful-management";
3645
4288
 
3646
4289
  // src/types/conceptPayloadTypes.ts
3647
- import { z as z60 } from "zod";
3648
- var TaxonomyConceptLinkSchema = z60.object({
3649
- sys: z60.object({
3650
- type: z60.literal("Link"),
3651
- linkType: z60.literal("TaxonomyConcept"),
3652
- id: z60.string()
4290
+ import { z as z63 } from "zod";
4291
+ var TaxonomyConceptLinkSchema = z63.object({
4292
+ sys: z63.object({
4293
+ type: z63.literal("Link"),
4294
+ linkType: z63.literal("TaxonomyConcept"),
4295
+ id: z63.string()
3653
4296
  })
3654
4297
  });
3655
4298
 
3656
4299
  // src/tools/taxonomies/concept-schemes/createConceptScheme.ts
3657
- var CreateConceptSchemeToolParams = z61.object({
3658
- organizationId: z61.string().describe("The ID of the Contentful organization"),
3659
- conceptSchemeId: z61.string().optional().describe(
4300
+ var CreateConceptSchemeToolParams = z64.object({
4301
+ organizationId: z64.string().describe("The ID of the Contentful organization"),
4302
+ conceptSchemeId: z64.string().optional().describe(
3660
4303
  "Optional user-defined ID for the concept scheme. If not provided, Contentful will generate one automatically."
3661
4304
  ),
3662
- prefLabel: z61.record(z61.string()).describe("The preferred label for the concept scheme (localized)"),
3663
- uri: z61.string().nullable().optional().describe("The URI for the concept scheme"),
3664
- definition: z61.record(z61.string().nullable()).optional().describe("Definition of the concept scheme (localized)"),
3665
- editorialNote: z61.record(z61.string().nullable()).optional().describe("Editorial note for the concept scheme (localized)"),
3666
- historyNote: z61.record(z61.string().nullable()).optional().describe("History note for the concept scheme (localized)"),
3667
- example: z61.record(z61.string().nullable()).optional().describe("Example for the concept scheme (localized)"),
3668
- note: z61.record(z61.string().nullable()).optional().describe("General note for the concept scheme (localized)"),
3669
- scopeNote: z61.record(z61.string().nullable()).optional().describe("Scope note for the concept scheme (localized)"),
3670
- topConcepts: z61.array(TaxonomyConceptLinkSchema).optional().describe("Links to top-level concepts in this scheme")
4305
+ prefLabel: z64.record(z64.string()).describe("The preferred label for the concept scheme (localized)"),
4306
+ uri: z64.string().nullable().optional().describe("The URI for the concept scheme"),
4307
+ definition: z64.record(z64.string().nullable()).optional().describe("Definition of the concept scheme (localized)"),
4308
+ editorialNote: z64.record(z64.string().nullable()).optional().describe("Editorial note for the concept scheme (localized)"),
4309
+ historyNote: z64.record(z64.string().nullable()).optional().describe("History note for the concept scheme (localized)"),
4310
+ example: z64.record(z64.string().nullable()).optional().describe("Example for the concept scheme (localized)"),
4311
+ note: z64.record(z64.string().nullable()).optional().describe("General note for the concept scheme (localized)"),
4312
+ scopeNote: z64.record(z64.string().nullable()).optional().describe("Scope note for the concept scheme (localized)"),
4313
+ topConcepts: z64.array(TaxonomyConceptLinkSchema).optional().describe("Links to top-level concepts in this scheme")
3671
4314
  });
3672
4315
  function createConceptSchemeTool(config) {
3673
4316
  async function tool2(args) {
@@ -3707,11 +4350,11 @@ function createConceptSchemeTool(config) {
3707
4350
  }
3708
4351
 
3709
4352
  // src/tools/taxonomies/concept-schemes/getConceptScheme.ts
3710
- import { z as z62 } from "zod";
4353
+ import { z as z65 } from "zod";
3711
4354
  import { createClient as createClient7 } from "contentful-management";
3712
- var GetConceptSchemeToolParams = z62.object({
3713
- organizationId: z62.string().describe("The ID of the Contentful organization"),
3714
- conceptSchemeId: z62.string().describe("The ID of the concept scheme to retrieve")
4355
+ var GetConceptSchemeToolParams = z65.object({
4356
+ organizationId: z65.string().describe("The ID of the Contentful organization"),
4357
+ conceptSchemeId: z65.string().describe("The ID of the concept scheme to retrieve")
3715
4358
  });
3716
4359
  function getConceptSchemeTool(config) {
3717
4360
  async function tool2(args) {
@@ -3731,25 +4374,25 @@ function getConceptSchemeTool(config) {
3731
4374
  }
3732
4375
 
3733
4376
  // src/tools/taxonomies/concept-schemes/listConceptSchemes.ts
3734
- import { z as z63 } from "zod";
4377
+ import { z as z66 } from "zod";
3735
4378
  import { createClient as createClient8 } from "contentful-management";
3736
4379
  import { cloneDeep } from "lodash-es";
3737
- var ListConceptSchemesToolParams = z63.object({
3738
- organizationId: z63.string(),
3739
- query: z63.union([
3740
- z63.object({
3741
- query: z63.string().optional(),
3742
- pageNext: z63.string().optional().describe("Cursor token for the next page of concept schemes"),
3743
- pagePrev: z63.string().optional().describe(
4380
+ var ListConceptSchemesToolParams = z66.object({
4381
+ organizationId: z66.string(),
4382
+ query: z66.union([
4383
+ z66.object({
4384
+ query: z66.string().optional(),
4385
+ pageNext: z66.string().optional().describe("Cursor token for the next page of concept schemes"),
4386
+ pagePrev: z66.string().optional().describe(
3744
4387
  "Cursor token for the previous page of concept schemes"
3745
4388
  ),
3746
- limit: z63.number().optional().describe("Maximum number of concept schemes to return"),
3747
- order: z63.string().optional().describe("Order concept schemes by this field"),
3748
- skip: z63.never().optional()
4389
+ limit: z66.number().optional().describe("Maximum number of concept schemes to return"),
4390
+ order: z66.string().optional().describe("Order concept schemes by this field"),
4391
+ skip: z66.never().optional()
3749
4392
  }).passthrough(),
3750
4393
  // handles [key: string]: any from BasicQueryOptions
3751
- z63.object({
3752
- pageUrl: z63.string().optional()
4394
+ z66.object({
4395
+ pageUrl: z66.string().optional()
3753
4396
  })
3754
4397
  ]).optional().describe(
3755
4398
  'Query parameters for listing concept schemes, supports either pageUrl for cursor-based pagination. Offset "skip" pagination is not supported.'
@@ -3819,22 +4462,22 @@ function listConceptSchemesTool(config) {
3819
4462
  }
3820
4463
 
3821
4464
  // src/tools/taxonomies/concept-schemes/updateConceptScheme.ts
3822
- import { z as z64 } from "zod";
4465
+ import { z as z67 } from "zod";
3823
4466
  import { createClient as createClient9 } from "contentful-management";
3824
- var UpdateConceptSchemeToolParams = z64.object({
3825
- organizationId: z64.string().describe("The ID of the Contentful organization"),
3826
- conceptSchemeId: z64.string().describe("The ID of the concept scheme to update"),
3827
- version: z64.number().describe("The current version of the concept scheme"),
3828
- prefLabel: z64.record(z64.string()).optional().describe("The preferred label for the concept scheme (localized)"),
3829
- uri: z64.string().nullable().optional().describe("The URI for the concept scheme"),
3830
- definition: z64.record(z64.string().nullable()).optional().describe("Definition of the concept scheme (localized)"),
3831
- editorialNote: z64.record(z64.string().nullable()).optional().describe("Editorial note for the concept scheme (localized)"),
3832
- historyNote: z64.record(z64.string().nullable()).optional().describe("History note for the concept scheme (localized)"),
3833
- example: z64.record(z64.string().nullable()).optional().describe("Example for the concept scheme (localized)"),
3834
- note: z64.record(z64.string().nullable()).optional().describe("General note for the concept scheme (localized)"),
3835
- scopeNote: z64.record(z64.string().nullable()).optional().describe("Scope note for the concept scheme (localized)"),
3836
- topConcepts: z64.array(TaxonomyConceptLinkSchema).optional().describe("Links to top-level concepts in this scheme"),
3837
- addConcept: z64.string().optional().describe(
4467
+ var UpdateConceptSchemeToolParams = z67.object({
4468
+ organizationId: z67.string().describe("The ID of the Contentful organization"),
4469
+ conceptSchemeId: z67.string().describe("The ID of the concept scheme to update"),
4470
+ version: z67.number().describe("The current version of the concept scheme"),
4471
+ prefLabel: z67.record(z67.string()).optional().describe("The preferred label for the concept scheme (localized)"),
4472
+ uri: z67.string().nullable().optional().describe("The URI for the concept scheme"),
4473
+ definition: z67.record(z67.string().nullable()).optional().describe("Definition of the concept scheme (localized)"),
4474
+ editorialNote: z67.record(z67.string().nullable()).optional().describe("Editorial note for the concept scheme (localized)"),
4475
+ historyNote: z67.record(z67.string().nullable()).optional().describe("History note for the concept scheme (localized)"),
4476
+ example: z67.record(z67.string().nullable()).optional().describe("Example for the concept scheme (localized)"),
4477
+ note: z67.record(z67.string().nullable()).optional().describe("General note for the concept scheme (localized)"),
4478
+ scopeNote: z67.record(z67.string().nullable()).optional().describe("Scope note for the concept scheme (localized)"),
4479
+ topConcepts: z67.array(TaxonomyConceptLinkSchema).optional().describe("Links to top-level concepts in this scheme"),
4480
+ addConcept: z67.string().optional().describe(
3838
4481
  "ID of a concept to add to this scheme (adds to both concepts and topConcepts)"
3839
4482
  )
3840
4483
  });
@@ -3909,22 +4552,47 @@ function updateConceptSchemeTool(config) {
3909
4552
  }
3910
4553
 
3911
4554
  // src/tools/taxonomies/concept-schemes/deleteConceptScheme.ts
3912
- import { z as z65 } from "zod";
4555
+ import { z as z68 } from "zod";
3913
4556
  import { createClient as createClient10 } from "contentful-management";
3914
- var DeleteConceptSchemeToolParams = z65.object({
3915
- organizationId: z65.string().describe("The ID of the Contentful organization"),
3916
- conceptSchemeId: z65.string().describe("The ID of the concept scheme to delete"),
3917
- version: z65.number().describe("The version of the concept scheme to delete")
4557
+ var DeleteConceptSchemeToolParams = z68.object({
4558
+ organizationId: z68.string().describe("The ID of the Contentful organization"),
4559
+ conceptSchemeId: z68.string().describe("The ID of the concept scheme to delete"),
4560
+ confirm: z68.boolean().optional().describe(
4561
+ "Set to true on the second call to actually perform the deletion. Required together with confirmToken."
4562
+ ),
4563
+ confirmToken: z68.string().optional().describe(
4564
+ "Token returned by the preview call; must be supplied with confirm: true."
4565
+ )
3918
4566
  });
3919
4567
  function deleteConceptSchemeTool(config) {
3920
4568
  async function tool2(args) {
3921
4569
  const clientConfig = createClientConfig(config);
3922
4570
  delete clientConfig.space;
3923
4571
  const contentfulClient = createClient10(clientConfig);
4572
+ const conceptScheme = await contentfulClient.conceptScheme.get({
4573
+ organizationId: args.organizationId,
4574
+ conceptSchemeId: args.conceptSchemeId
4575
+ });
4576
+ const expectedToken = buildConfirmToken(
4577
+ "conceptScheme",
4578
+ args.conceptSchemeId,
4579
+ conceptScheme.sys.version
4580
+ );
4581
+ if (args.confirm !== true || args.confirmToken !== expectedToken) {
4582
+ return createSuccessResponse(
4583
+ `${CONFIRMATION_MESSAGE_PREFIX} concept scheme`,
4584
+ buildConfirmationPreview(
4585
+ "conceptScheme",
4586
+ args.conceptSchemeId,
4587
+ { conceptScheme },
4588
+ expectedToken
4589
+ )
4590
+ );
4591
+ }
3924
4592
  await contentfulClient.conceptScheme.delete({
3925
4593
  organizationId: args.organizationId,
3926
4594
  conceptSchemeId: args.conceptSchemeId,
3927
- version: args.version
4595
+ version: conceptScheme.sys.version
3928
4596
  });
3929
4597
  return createSuccessResponse("Concept scheme deleted successfully", {
3930
4598
  conceptSchemeId: args.conceptSchemeId
@@ -3987,12 +4655,12 @@ function createConceptSchemeTools(config) {
3987
4655
  },
3988
4656
  deleteConceptScheme: {
3989
4657
  title: "delete_concept_scheme",
3990
- description: "Delete a taxonomy concept scheme from Contentful. Requires the concept scheme ID and version number for optimistic concurrency control. This operation permanently removes the concept scheme and cannot be undone.",
4658
+ description: "Delete a taxonomy concept scheme from Contentful. This is a two-phase operation: the first call (without confirm/confirmToken) returns a preview of the concept scheme and a confirmToken. To complete the deletion, call this tool again with the same conceptSchemeId, confirm: true, and the confirmToken from the preview response. The concept scheme version is fetched server-side and used for optimistic concurrency control.",
3991
4659
  inputParams: DeleteConceptSchemeToolParams.shape,
3992
4660
  annotations: {
3993
4661
  readOnlyHint: false,
3994
4662
  destructiveHint: true,
3995
- idempotentHint: true,
4663
+ idempotentHint: false,
3996
4664
  openWorldHint: false
3997
4665
  },
3998
4666
  tool: deleteConceptScheme
@@ -4001,26 +4669,26 @@ function createConceptSchemeTools(config) {
4001
4669
  }
4002
4670
 
4003
4671
  // src/tools/taxonomies/concepts/createConcept.ts
4004
- import { z as z66 } from "zod";
4672
+ import { z as z69 } from "zod";
4005
4673
  import { createClient as createClient11 } from "contentful-management";
4006
- var CreateConceptToolParams = z66.object({
4007
- organizationId: z66.string().describe("The ID of the Contentful organization"),
4008
- conceptId: z66.string().optional().describe(
4674
+ var CreateConceptToolParams = z69.object({
4675
+ organizationId: z69.string().describe("The ID of the Contentful organization"),
4676
+ conceptId: z69.string().optional().describe(
4009
4677
  "Optional user-defined ID for the concept. If not provided, Contentful will generate one automatically."
4010
4678
  ),
4011
- prefLabel: z66.record(z66.string()).describe("The preferred label for the concept (localized)"),
4012
- uri: z66.string().nullable().optional().describe("The URI for the concept"),
4013
- altLabels: z66.record(z66.array(z66.string())).optional().describe("Alternative labels for the concept (localized)"),
4014
- hiddenLabels: z66.record(z66.array(z66.string())).optional().describe("Hidden labels for the concept (localized)"),
4015
- definition: z66.record(z66.string().nullable()).optional().describe("Definition of the concept (localized)"),
4016
- editorialNote: z66.record(z66.string().nullable()).optional().describe("Editorial note for the concept (localized)"),
4017
- historyNote: z66.record(z66.string().nullable()).optional().describe("History note for the concept (localized)"),
4018
- example: z66.record(z66.string().nullable()).optional().describe("Example for the concept (localized)"),
4019
- note: z66.record(z66.string().nullable()).optional().describe("General note for the concept (localized)"),
4020
- scopeNote: z66.record(z66.string().nullable()).optional().describe("Scope note for the concept (localized)"),
4021
- notations: z66.array(z66.string()).optional().describe("Notations for the concept"),
4022
- broader: z66.array(TaxonomyConceptLinkSchema).optional().describe("Links to broader concepts"),
4023
- related: z66.array(TaxonomyConceptLinkSchema).optional().describe("Links to related concepts")
4679
+ prefLabel: z69.record(z69.string()).describe("The preferred label for the concept (localized)"),
4680
+ uri: z69.string().nullable().optional().describe("The URI for the concept"),
4681
+ altLabels: z69.record(z69.array(z69.string())).optional().describe("Alternative labels for the concept (localized)"),
4682
+ hiddenLabels: z69.record(z69.array(z69.string())).optional().describe("Hidden labels for the concept (localized)"),
4683
+ definition: z69.record(z69.string().nullable()).optional().describe("Definition of the concept (localized)"),
4684
+ editorialNote: z69.record(z69.string().nullable()).optional().describe("Editorial note for the concept (localized)"),
4685
+ historyNote: z69.record(z69.string().nullable()).optional().describe("History note for the concept (localized)"),
4686
+ example: z69.record(z69.string().nullable()).optional().describe("Example for the concept (localized)"),
4687
+ note: z69.record(z69.string().nullable()).optional().describe("General note for the concept (localized)"),
4688
+ scopeNote: z69.record(z69.string().nullable()).optional().describe("Scope note for the concept (localized)"),
4689
+ notations: z69.array(z69.string()).optional().describe("Notations for the concept"),
4690
+ broader: z69.array(TaxonomyConceptLinkSchema).optional().describe("Links to broader concepts"),
4691
+ related: z69.array(TaxonomyConceptLinkSchema).optional().describe("Links to related concepts")
4024
4692
  });
4025
4693
  function createConceptTool(config) {
4026
4694
  async function tool2(args) {
@@ -4055,22 +4723,42 @@ function createConceptTool(config) {
4055
4723
  }
4056
4724
 
4057
4725
  // src/tools/taxonomies/concepts/deleteConcept.ts
4058
- import { z as z67 } from "zod";
4726
+ import { z as z70 } from "zod";
4059
4727
  import { createClient as createClient12 } from "contentful-management";
4060
- var DeleteConceptToolParams = z67.object({
4061
- organizationId: z67.string().describe("The ID of the Contentful organization"),
4062
- conceptId: z67.string().describe("The ID of the concept to delete"),
4063
- version: z67.number().describe("The version of the concept to delete")
4728
+ var DeleteConceptToolParams = z70.object({
4729
+ organizationId: z70.string().describe("The ID of the Contentful organization"),
4730
+ conceptId: z70.string().describe("The ID of the concept to delete"),
4731
+ confirm: z70.boolean().optional().describe(
4732
+ "Set to true on the second call to actually perform the deletion. Required together with confirmToken."
4733
+ ),
4734
+ confirmToken: z70.string().optional().describe(
4735
+ "Token returned by the preview call; must be supplied with confirm: true."
4736
+ )
4064
4737
  });
4065
4738
  function deleteConceptTool(config) {
4066
4739
  async function tool2(args) {
4067
4740
  const clientConfig = createClientConfig(config);
4068
4741
  delete clientConfig.space;
4069
4742
  const contentfulClient = createClient12(clientConfig);
4743
+ const concept = await contentfulClient.concept.get({
4744
+ organizationId: args.organizationId,
4745
+ conceptId: args.conceptId
4746
+ });
4747
+ const expectedToken = buildConfirmToken(
4748
+ "concept",
4749
+ args.conceptId,
4750
+ concept.sys.version
4751
+ );
4752
+ if (args.confirm !== true || args.confirmToken !== expectedToken) {
4753
+ return createSuccessResponse(
4754
+ `${CONFIRMATION_MESSAGE_PREFIX} concept`,
4755
+ buildConfirmationPreview("concept", args.conceptId, { concept }, expectedToken)
4756
+ );
4757
+ }
4070
4758
  await contentfulClient.concept.delete({
4071
4759
  organizationId: args.organizationId,
4072
4760
  conceptId: args.conceptId,
4073
- version: args.version
4761
+ version: concept.sys.version
4074
4762
  });
4075
4763
  return createSuccessResponse("Concept deleted successfully", {
4076
4764
  conceptId: args.conceptId
@@ -4080,25 +4768,25 @@ function deleteConceptTool(config) {
4080
4768
  }
4081
4769
 
4082
4770
  // src/tools/taxonomies/concepts/updateConcept.ts
4083
- import { z as z68 } from "zod";
4771
+ import { z as z71 } from "zod";
4084
4772
  import { createClient as createClient13 } from "contentful-management";
4085
- var UpdateConceptToolParams = z68.object({
4086
- organizationId: z68.string().describe("The ID of the Contentful organization"),
4087
- conceptId: z68.string().describe("The ID of the concept to update"),
4088
- version: z68.number().describe("The current version of the concept"),
4089
- prefLabel: z68.record(z68.string()).optional().describe("The preferred label for the concept (localized)"),
4090
- uri: z68.string().nullable().optional().describe("The URI for the concept"),
4091
- altLabels: z68.record(z68.array(z68.string())).optional().describe("Alternative labels for the concept (localized)"),
4092
- hiddenLabels: z68.record(z68.array(z68.string())).optional().describe("Hidden labels for the concept (localized)"),
4093
- definition: z68.record(z68.string().nullable()).optional().describe("Definition of the concept (localized)"),
4094
- editorialNote: z68.record(z68.string().nullable()).optional().describe("Editorial note for the concept (localized)"),
4095
- historyNote: z68.record(z68.string().nullable()).optional().describe("History note for the concept (localized)"),
4096
- example: z68.record(z68.string().nullable()).optional().describe("Example for the concept (localized)"),
4097
- note: z68.record(z68.string().nullable()).optional().describe("General note for the concept (localized)"),
4098
- scopeNote: z68.record(z68.string().nullable()).optional().describe("Scope note for the concept (localized)"),
4099
- notations: z68.array(z68.string()).optional().describe("Notations for the concept"),
4100
- broader: z68.array(TaxonomyConceptLinkSchema).optional().describe("Links to broader concepts"),
4101
- related: z68.array(TaxonomyConceptLinkSchema).optional().describe("Links to related concepts")
4773
+ var UpdateConceptToolParams = z71.object({
4774
+ organizationId: z71.string().describe("The ID of the Contentful organization"),
4775
+ conceptId: z71.string().describe("The ID of the concept to update"),
4776
+ version: z71.number().describe("The current version of the concept"),
4777
+ prefLabel: z71.record(z71.string()).optional().describe("The preferred label for the concept (localized)"),
4778
+ uri: z71.string().nullable().optional().describe("The URI for the concept"),
4779
+ altLabels: z71.record(z71.array(z71.string())).optional().describe("Alternative labels for the concept (localized)"),
4780
+ hiddenLabels: z71.record(z71.array(z71.string())).optional().describe("Hidden labels for the concept (localized)"),
4781
+ definition: z71.record(z71.string().nullable()).optional().describe("Definition of the concept (localized)"),
4782
+ editorialNote: z71.record(z71.string().nullable()).optional().describe("Editorial note for the concept (localized)"),
4783
+ historyNote: z71.record(z71.string().nullable()).optional().describe("History note for the concept (localized)"),
4784
+ example: z71.record(z71.string().nullable()).optional().describe("Example for the concept (localized)"),
4785
+ note: z71.record(z71.string().nullable()).optional().describe("General note for the concept (localized)"),
4786
+ scopeNote: z71.record(z71.string().nullable()).optional().describe("Scope note for the concept (localized)"),
4787
+ notations: z71.array(z71.string()).optional().describe("Notations for the concept"),
4788
+ broader: z71.array(TaxonomyConceptLinkSchema).optional().describe("Links to broader concepts"),
4789
+ related: z71.array(TaxonomyConceptLinkSchema).optional().describe("Links to related concepts")
4102
4790
  });
4103
4791
  function updateConceptTool(config) {
4104
4792
  async function tool2(args) {
@@ -4140,11 +4828,11 @@ function updateConceptTool(config) {
4140
4828
  }
4141
4829
 
4142
4830
  // src/tools/taxonomies/concepts/getConcept.ts
4143
- import { z as z69 } from "zod";
4831
+ import { z as z72 } from "zod";
4144
4832
  import { createClient as createClient14 } from "contentful-management";
4145
- var GetConceptToolParams = z69.object({
4146
- organizationId: z69.string().describe("The ID of the Contentful organization"),
4147
- conceptId: z69.string().describe("The ID of the concept to retrieve")
4833
+ var GetConceptToolParams = z72.object({
4834
+ organizationId: z72.string().describe("The ID of the Contentful organization"),
4835
+ conceptId: z72.string().describe("The ID of the concept to retrieve")
4148
4836
  });
4149
4837
  function getConceptTool(config) {
4150
4838
  async function tool2(args) {
@@ -4161,18 +4849,18 @@ function getConceptTool(config) {
4161
4849
  }
4162
4850
 
4163
4851
  // src/tools/taxonomies/concepts/listConcepts.ts
4164
- import { z as z70 } from "zod";
4852
+ import { z as z73 } from "zod";
4165
4853
  import { createClient as createClient15 } from "contentful-management";
4166
- var ListConceptsToolParams = z70.object({
4167
- organizationId: z70.string().describe("The ID of the Contentful organization"),
4168
- conceptId: z70.string().optional().describe("The ID of the concept (required for descendants/ancestors)"),
4169
- limit: z70.number().optional().describe("Maximum number of concepts to return"),
4170
- select: z70.string().optional().describe("Comma-separated list of fields to return"),
4171
- include: z70.number().optional().describe("Include this many levels of linked entries"),
4172
- order: z70.string().optional().describe("Order concepts by this field"),
4173
- getDescendants: z70.boolean().optional().describe("Get descendants of the specified concept (requires conceptId)"),
4174
- getAncestors: z70.boolean().optional().describe("Get ancestors of the specified concept (requires conceptId)"),
4175
- getTotalOnly: z70.boolean().optional().describe("Get only the total number of concepts without full data")
4854
+ var ListConceptsToolParams = z73.object({
4855
+ organizationId: z73.string().describe("The ID of the Contentful organization"),
4856
+ conceptId: z73.string().optional().describe("The ID of the concept (required for descendants/ancestors)"),
4857
+ limit: z73.number().optional().describe("Maximum number of concepts to return"),
4858
+ select: z73.string().optional().describe("Comma-separated list of fields to return"),
4859
+ include: z73.number().optional().describe("Include this many levels of linked entries"),
4860
+ order: z73.string().optional().describe("Order concepts by this field"),
4861
+ getDescendants: z73.boolean().optional().describe("Get descendants of the specified concept (requires conceptId)"),
4862
+ getAncestors: z73.boolean().optional().describe("Get ancestors of the specified concept (requires conceptId)"),
4863
+ getTotalOnly: z73.boolean().optional().describe("Get only the total number of concepts without full data")
4176
4864
  });
4177
4865
  function listConceptsTool(config) {
4178
4866
  async function tool2(args) {
@@ -4324,12 +5012,12 @@ function createConceptTools(config) {
4324
5012
  },
4325
5013
  deleteConcept: {
4326
5014
  title: "delete_concept",
4327
- description: "Delete a taxonomy concept from Contentful. Requires the concept ID and version number for optimistic concurrency control. This operation permanently removes the concept and cannot be undone.",
5015
+ description: "Delete a taxonomy concept from Contentful. This is a two-phase operation: the first call (without confirm/confirmToken) returns a preview of the concept and a confirmToken. To complete the deletion, call this tool again with the same conceptId, confirm: true, and the confirmToken from the preview response. The concept version is fetched server-side and used for optimistic concurrency control.",
4328
5016
  inputParams: DeleteConceptToolParams.shape,
4329
5017
  annotations: {
4330
5018
  readOnlyHint: false,
4331
5019
  destructiveHint: true,
4332
- idempotentHint: true,
5020
+ idempotentHint: false,
4333
5021
  openWorldHint: false
4334
5022
  },
4335
5023
  tool: deleteConcept
@@ -4348,54 +5036,54 @@ function createTaxonomyTools(config) {
4348
5036
  }
4349
5037
 
4350
5038
  // src/tools/jobs/space-to-space-migration/exportSpace.ts
4351
- import { z as z72 } from "zod";
5039
+ import { z as z75 } from "zod";
4352
5040
 
4353
5041
  // src/types/querySchema.ts
4354
- import { z as z71 } from "zod";
4355
- var EntryQuerySchema = z71.object({
4356
- content_type: z71.string().optional().describe("Filter by content type"),
4357
- include: z71.number().optional().describe("Include this many levels of linked entries"),
4358
- select: z71.string().optional().describe("Comma-separated list of fields to return"),
4359
- links_to_entry: z71.string().optional().describe("Find entries that link to the specified entry ID"),
4360
- limit: z71.number().optional().describe("Maximum number of entries to return"),
4361
- skip: z71.number().optional().describe("Skip this many entries"),
4362
- order: z71.string().optional().describe("Order entries by this field")
5042
+ import { z as z74 } from "zod";
5043
+ var EntryQuerySchema = z74.object({
5044
+ content_type: z74.string().optional().describe("Filter by content type"),
5045
+ include: z74.number().optional().describe("Include this many levels of linked entries"),
5046
+ select: z74.string().optional().describe("Comma-separated list of fields to return"),
5047
+ links_to_entry: z74.string().optional().describe("Find entries that link to the specified entry ID"),
5048
+ limit: z74.number().optional().describe("Maximum number of entries to return"),
5049
+ skip: z74.number().optional().describe("Skip this many entries"),
5050
+ order: z74.string().optional().describe("Order entries by this field")
4363
5051
  });
4364
- var AssetQuerySchema = z71.object({
4365
- mimetype_group: z71.string().optional().describe("Filter by MIME type group"),
4366
- select: z71.string().optional().describe("Comma-separated list of fields to return"),
4367
- limit: z71.number().optional().describe("Maximum number of assets to return"),
4368
- skip: z71.number().optional().describe("Skip this many assets"),
4369
- order: z71.string().optional().describe("Order assets by this field")
5052
+ var AssetQuerySchema = z74.object({
5053
+ mimetype_group: z74.string().optional().describe("Filter by MIME type group"),
5054
+ select: z74.string().optional().describe("Comma-separated list of fields to return"),
5055
+ limit: z74.number().optional().describe("Maximum number of assets to return"),
5056
+ skip: z74.number().optional().describe("Skip this many assets"),
5057
+ order: z74.string().optional().describe("Order assets by this field")
4370
5058
  });
4371
5059
 
4372
5060
  // src/tools/jobs/space-to-space-migration/exportSpace.ts
4373
5061
  var ExportSpaceToolParams = BaseToolSchema.extend({
4374
- exportDir: z72.string().optional().describe(
5062
+ exportDir: z75.string().optional().describe(
4375
5063
  "Directory to save the exported space data (optional, defaults to current directory)"
4376
5064
  ),
4377
- saveFile: z72.boolean().optional().default(true).describe("Save the exported space data to a file"),
4378
- contentFile: z72.string().optional().describe("Custom filename for the exported space data (optional)"),
4379
- includeDrafts: z72.boolean().optional().default(false).describe("Include draft entries in the export"),
4380
- includeArchived: z72.boolean().optional().default(false).describe("Include archived entries in the export"),
4381
- skipContentModel: z72.boolean().optional().default(false).describe("Skip exporting content types"),
4382
- skipEditorInterfaces: z72.boolean().optional().default(false).describe("Skip exporting editor interfaces"),
4383
- skipContent: z72.boolean().optional().default(false).describe("Skip exporting entries and assets"),
4384
- skipRoles: z72.boolean().optional().default(false).describe("Skip exporting roles and permissions"),
4385
- skipTags: z72.boolean().optional().default(false).describe("Skip exporting tags"),
4386
- skipWebhooks: z72.boolean().optional().default(false).describe("Skip exporting webhooks"),
4387
- stripTags: z72.boolean().optional().default(false).describe("Untag assets and entries"),
4388
- contentOnly: z72.boolean().optional().default(false).describe("Only export assets and entries"),
5065
+ saveFile: z75.boolean().optional().default(true).describe("Save the exported space data to a file"),
5066
+ contentFile: z75.string().optional().describe("Custom filename for the exported space data (optional)"),
5067
+ includeDrafts: z75.boolean().optional().default(false).describe("Include draft entries in the export"),
5068
+ includeArchived: z75.boolean().optional().default(false).describe("Include archived entries in the export"),
5069
+ skipContentModel: z75.boolean().optional().default(false).describe("Skip exporting content types"),
5070
+ skipEditorInterfaces: z75.boolean().optional().default(false).describe("Skip exporting editor interfaces"),
5071
+ skipContent: z75.boolean().optional().default(false).describe("Skip exporting entries and assets"),
5072
+ skipRoles: z75.boolean().optional().default(false).describe("Skip exporting roles and permissions"),
5073
+ skipTags: z75.boolean().optional().default(false).describe("Skip exporting tags"),
5074
+ skipWebhooks: z75.boolean().optional().default(false).describe("Skip exporting webhooks"),
5075
+ stripTags: z75.boolean().optional().default(false).describe("Untag assets and entries"),
5076
+ contentOnly: z75.boolean().optional().default(false).describe("Only export assets and entries"),
4389
5077
  queryEntries: EntryQuerySchema.optional().describe(
4390
5078
  "Export only entries that match query parameters"
4391
5079
  ),
4392
5080
  queryAssets: AssetQuerySchema.optional().describe(
4393
5081
  "Export only assets that match query parameters"
4394
5082
  ),
4395
- downloadAssets: z72.boolean().optional().default(false).describe("Download actual asset files"),
4396
- maxAllowedLimit: z72.number().optional().default(1e3).describe("Maximum number of items per request"),
4397
- errorLogFile: z72.string().optional().describe("Path to error log output file"),
4398
- useVerboseRenderer: z72.boolean().optional().describe("Line-by-line logging, useful for CI")
5083
+ downloadAssets: z75.boolean().optional().default(false).describe("Download actual asset files"),
5084
+ maxAllowedLimit: z75.number().optional().default(1e3).describe("Maximum number of items per request"),
5085
+ errorLogFile: z75.string().optional().describe("Path to error log output file"),
5086
+ useVerboseRenderer: z75.boolean().optional().describe("Line-by-line logging, useful for CI")
4399
5087
  });
4400
5088
  function createExportSpaceTool(config) {
4401
5089
  async function tool2(args) {
@@ -4445,70 +5133,70 @@ function createExportSpaceTool(config) {
4445
5133
  }
4446
5134
 
4447
5135
  // src/tools/jobs/space-to-space-migration/paramCollection.ts
4448
- import { z as z73 } from "zod";
5136
+ import { z as z76 } from "zod";
4449
5137
  var ParamCollectionToolParams = BaseToolSchema.extend({
4450
- confirmation: z73.boolean().optional().describe(
5138
+ confirmation: z76.boolean().optional().describe(
4451
5139
  "User confirmation that they are ready to proceed with the workflow"
4452
5140
  ),
4453
- export: z73.object({
4454
- spaceId: z73.string().optional().describe("ID of the space with source data"),
4455
- environmentId: z73.string().optional().describe("ID of the environment in the source space"),
4456
- deliveryToken: z73.string().optional().describe("CDA token to export only published content (excludes tags)"),
4457
- exportDir: z73.string().optional().describe("Path to export JSON output"),
4458
- saveFile: z73.boolean().optional().describe("Save the export as a JSON file"),
4459
- contentFile: z73.string().optional().describe("Filename for exported data"),
4460
- includeDrafts: z73.boolean().optional().describe("Include drafts in exported entries"),
4461
- includeArchived: z73.boolean().optional().describe("Include archived entries"),
4462
- skipContentModel: z73.boolean().optional().describe("Skip exporting content models"),
4463
- skipEditorInterfaces: z73.boolean().optional().describe("Skip exporting editor interfaces"),
4464
- skipContent: z73.boolean().optional().describe("Skip exporting entries and assets"),
4465
- skipRoles: z73.boolean().optional().describe("Skip exporting roles and permissions"),
4466
- skipTags: z73.boolean().optional().describe("Skip exporting tags"),
4467
- skipWebhooks: z73.boolean().optional().describe("Skip exporting webhooks"),
4468
- stripTags: z73.boolean().optional().describe("Remove tags from entries and assets"),
4469
- contentOnly: z73.boolean().optional().describe("Export only entries and assets"),
5141
+ export: z76.object({
5142
+ spaceId: z76.string().optional().describe("ID of the space with source data"),
5143
+ environmentId: z76.string().optional().describe("ID of the environment in the source space"),
5144
+ deliveryToken: z76.string().optional().describe("CDA token to export only published content (excludes tags)"),
5145
+ exportDir: z76.string().optional().describe("Path to export JSON output"),
5146
+ saveFile: z76.boolean().optional().describe("Save the export as a JSON file"),
5147
+ contentFile: z76.string().optional().describe("Filename for exported data"),
5148
+ includeDrafts: z76.boolean().optional().describe("Include drafts in exported entries"),
5149
+ includeArchived: z76.boolean().optional().describe("Include archived entries"),
5150
+ skipContentModel: z76.boolean().optional().describe("Skip exporting content models"),
5151
+ skipEditorInterfaces: z76.boolean().optional().describe("Skip exporting editor interfaces"),
5152
+ skipContent: z76.boolean().optional().describe("Skip exporting entries and assets"),
5153
+ skipRoles: z76.boolean().optional().describe("Skip exporting roles and permissions"),
5154
+ skipTags: z76.boolean().optional().describe("Skip exporting tags"),
5155
+ skipWebhooks: z76.boolean().optional().describe("Skip exporting webhooks"),
5156
+ stripTags: z76.boolean().optional().describe("Remove tags from entries and assets"),
5157
+ contentOnly: z76.boolean().optional().describe("Export only entries and assets"),
4470
5158
  queryEntries: EntryQuerySchema.optional().describe(
4471
5159
  "Export only entries that match query parameters"
4472
5160
  ),
4473
5161
  queryAssets: AssetQuerySchema.optional().describe(
4474
5162
  "Export only assets that match query parameters"
4475
5163
  ),
4476
- downloadAssets: z73.boolean().optional().describe("Download asset files to disk"),
4477
- host: z73.string().optional().describe("Management API host"),
4478
- hostDelivery: z73.string().optional().describe("Delivery API host"),
4479
- proxy: z73.string().optional().describe("HTTP/HTTPS proxy config"),
4480
- rawProxy: z73.boolean().optional().describe("Pass raw proxy config directly to Axios"),
4481
- maxAllowedLimit: z73.number().optional().describe("Page size for requests"),
4482
- headers: z73.record(z73.any()).optional().describe("Additional headers to include in requests"),
4483
- errorLogFile: z73.string().optional().describe("Path to error log output file"),
4484
- useVerboseRenderer: z73.boolean().optional().describe("Line-by-line logging, useful for CI"),
4485
- config: z73.string().optional().describe("Path to a JSON config file with all options")
5164
+ downloadAssets: z76.boolean().optional().describe("Download asset files to disk"),
5165
+ host: z76.string().optional().describe("Management API host"),
5166
+ hostDelivery: z76.string().optional().describe("Delivery API host"),
5167
+ proxy: z76.string().optional().describe("HTTP/HTTPS proxy config"),
5168
+ rawProxy: z76.boolean().optional().describe("Pass raw proxy config directly to Axios"),
5169
+ maxAllowedLimit: z76.number().optional().describe("Page size for requests"),
5170
+ headers: z76.record(z76.any()).optional().describe("Additional headers to include in requests"),
5171
+ errorLogFile: z76.string().optional().describe("Path to error log output file"),
5172
+ useVerboseRenderer: z76.boolean().optional().describe("Line-by-line logging, useful for CI"),
5173
+ config: z76.string().optional().describe("Path to a JSON config file with all options")
4486
5174
  }).optional(),
4487
- import: z73.object({
4488
- spaceId: z73.string().optional().describe("ID of the space to import into"),
4489
- environmentId: z73.string().optional().describe("Target environment in destination space"),
4490
- contentFile: z73.string().optional().describe("Path to JSON file containing the content to import"),
4491
- content: z73.record(z73.any()).optional().describe(
5175
+ import: z76.object({
5176
+ spaceId: z76.string().optional().describe("ID of the space to import into"),
5177
+ environmentId: z76.string().optional().describe("Target environment in destination space"),
5178
+ contentFile: z76.string().optional().describe("Path to JSON file containing the content to import"),
5179
+ content: z76.record(z76.any()).optional().describe(
4492
5180
  "JS object containing import content (must match expected structure)"
4493
5181
  ),
4494
- contentModelOnly: z73.boolean().optional().describe("Import only content types"),
4495
- skipContentModel: z73.boolean().optional().describe("Skip importing content types and locales"),
4496
- skipLocales: z73.boolean().optional().describe("Skip importing locales"),
4497
- skipContentUpdates: z73.boolean().optional().describe("Do not update existing content"),
4498
- skipContentPublishing: z73.boolean().optional().describe("Create but do not publish content"),
4499
- uploadAssets: z73.boolean().optional().describe("Upload asset files (requires assetsDirectory)"),
4500
- skipAssetUpdates: z73.boolean().optional().describe("Do not update existing assets"),
4501
- assetsDirectory: z73.string().optional().describe("Path to directory containing exported asset files"),
4502
- timeout: z73.number().optional().describe("Time between retries during asset processing (ms)"),
4503
- retryLimit: z73.number().optional().describe("Max retries for asset processing"),
4504
- host: z73.string().optional().describe("Management API host"),
4505
- proxy: z73.string().optional().describe("HTTP/HTTPS proxy string (host:port or user:pass@host:port)"),
4506
- rawProxy: z73.boolean().optional().describe("Pass proxy config directly to Axios"),
4507
- rateLimit: z73.number().optional().describe("Max requests per second to the API"),
4508
- headers: z73.record(z73.any()).optional().describe("Additional headers to attach to requests"),
4509
- errorLogFile: z73.string().optional().describe("Path to error log file"),
4510
- useVerboseRenderer: z73.boolean().optional().describe("Line-by-line progress output (good for CI)"),
4511
- config: z73.string().optional().describe("Path to config JSON file (merged with CLI args)")
5182
+ contentModelOnly: z76.boolean().optional().describe("Import only content types"),
5183
+ skipContentModel: z76.boolean().optional().describe("Skip importing content types and locales"),
5184
+ skipLocales: z76.boolean().optional().describe("Skip importing locales"),
5185
+ skipContentUpdates: z76.boolean().optional().describe("Do not update existing content"),
5186
+ skipContentPublishing: z76.boolean().optional().describe("Create but do not publish content"),
5187
+ uploadAssets: z76.boolean().optional().describe("Upload asset files (requires assetsDirectory)"),
5188
+ skipAssetUpdates: z76.boolean().optional().describe("Do not update existing assets"),
5189
+ assetsDirectory: z76.string().optional().describe("Path to directory containing exported asset files"),
5190
+ timeout: z76.number().optional().describe("Time between retries during asset processing (ms)"),
5191
+ retryLimit: z76.number().optional().describe("Max retries for asset processing"),
5192
+ host: z76.string().optional().describe("Management API host"),
5193
+ proxy: z76.string().optional().describe("HTTP/HTTPS proxy string (host:port or user:pass@host:port)"),
5194
+ rawProxy: z76.boolean().optional().describe("Pass proxy config directly to Axios"),
5195
+ rateLimit: z76.number().optional().describe("Max requests per second to the API"),
5196
+ headers: z76.record(z76.any()).optional().describe("Additional headers to attach to requests"),
5197
+ errorLogFile: z76.string().optional().describe("Path to error log file"),
5198
+ useVerboseRenderer: z76.boolean().optional().describe("Line-by-line progress output (good for CI)"),
5199
+ config: z76.string().optional().describe("Path to config JSON file (merged with CLI args)")
4512
5200
  }).optional()
4513
5201
  });
4514
5202
  var paramCollectionConfig = {
@@ -4624,28 +5312,33 @@ var createParamCollectionTool = withErrorHandling(
4624
5312
  );
4625
5313
 
4626
5314
  // src/tools/jobs/space-to-space-migration/importSpace.ts
4627
- import { z as z74 } from "zod";
5315
+ import { z as z77 } from "zod";
4628
5316
  var ImportSpaceToolParams = BaseToolSchema.extend({
4629
- contentFile: z74.string().optional().describe("Path to JSON file containing the content to import"),
4630
- content: z74.record(z74.any()).optional().describe(
5317
+ contentFile: z77.string().optional().describe("Path to JSON file containing the content to import"),
5318
+ content: z77.record(z77.any()).optional().describe(
4631
5319
  "JS object containing import content (must match expected structure)"
4632
5320
  ),
4633
- contentModelOnly: z74.boolean().optional().default(false).describe("Import only content types"),
4634
- skipContentModel: z74.boolean().optional().default(false).describe("Skip importing content types and locales"),
4635
- skipLocales: z74.boolean().optional().default(false).describe("Skip importing locales"),
4636
- skipContentUpdates: z74.boolean().optional().default(false).describe("Do not update existing content"),
4637
- skipContentPublishing: z74.boolean().optional().default(false).describe("Create but do not publish content"),
4638
- uploadAssets: z74.boolean().optional().default(false).describe("Upload asset files (requires assetsDirectory)"),
4639
- skipAssetUpdates: z74.boolean().optional().default(false).describe("Do not update existing assets"),
4640
- assetsDirectory: z74.string().optional().describe("Path to directory containing exported asset files"),
4641
- timeout: z74.number().optional().default(3e3).describe("Time between retries during asset processing (ms)"),
4642
- retryLimit: z74.number().optional().default(10).describe("Max retries for asset processing"),
4643
- rateLimit: z74.number().optional().default(7).describe("Max requests per second to the API"),
4644
- errorLogFile: z74.string().optional().describe("Path to error log file"),
4645
- useVerboseRenderer: z74.boolean().optional().describe("Line-by-line progress output (good for CI)")
5321
+ contentModelOnly: z77.boolean().optional().default(false).describe("Import only content types"),
5322
+ skipContentModel: z77.boolean().optional().default(false).describe("Skip importing content types and locales"),
5323
+ skipLocales: z77.boolean().optional().default(false).describe("Skip importing locales"),
5324
+ skipContentUpdates: z77.boolean().optional().default(false).describe("Do not update existing content"),
5325
+ skipContentPublishing: z77.boolean().optional().default(false).describe("Create but do not publish content"),
5326
+ uploadAssets: z77.boolean().optional().default(false).describe("Upload asset files (requires assetsDirectory)"),
5327
+ skipAssetUpdates: z77.boolean().optional().default(false).describe("Do not update existing assets"),
5328
+ assetsDirectory: z77.string().optional().describe("Path to directory containing exported asset files"),
5329
+ timeout: z77.number().optional().default(3e3).describe("Time between retries during asset processing (ms)"),
5330
+ retryLimit: z77.number().optional().default(10).describe("Max retries for asset processing"),
5331
+ rateLimit: z77.number().optional().default(7).describe("Max requests per second to the API"),
5332
+ errorLogFile: z77.string().optional().describe("Path to error log file"),
5333
+ useVerboseRenderer: z77.boolean().optional().describe("Line-by-line progress output (good for CI)")
4646
5334
  });
4647
5335
  function createImportSpaceTool(config) {
4648
5336
  async function tool2(args) {
5337
+ const targetEnvironmentId = args.environmentId || "master";
5338
+ assertEnvironmentNotProtected(
5339
+ targetEnvironmentId,
5340
+ config.protectedEnvironments
5341
+ );
4649
5342
  const clientConfig = createClientConfig(config);
4650
5343
  const managementToken = clientConfig.accessToken;
4651
5344
  if (!managementToken) {
@@ -4655,14 +5348,14 @@ function createImportSpaceTool(config) {
4655
5348
  ...args,
4656
5349
  managementToken,
4657
5350
  host: config.host ?? "api.contentful.com",
4658
- environmentId: args.environmentId || "master"
5351
+ environmentId: targetEnvironmentId
4659
5352
  };
4660
5353
  try {
4661
5354
  const contentfulImport = await import("contentful-import");
4662
5355
  const result = await contentfulImport.default(importOptions);
4663
5356
  return createSuccessResponse("Space imported successfully", {
4664
5357
  spaceId: args.spaceId,
4665
- environmentId: args.environmentId || "master",
5358
+ environmentId: targetEnvironmentId,
4666
5359
  contentTypes: result.contentTypes?.length || 0,
4667
5360
  entries: result.entries?.length || 0,
4668
5361
  assets: result.assets?.length || 0,
@@ -4682,7 +5375,7 @@ function createImportSpaceTool(config) {
4682
5375
  }
4683
5376
 
4684
5377
  // src/tools/jobs/space-to-space-migration/migrationHandler.ts
4685
- import { z as z75 } from "zod";
5378
+ import { z as z78 } from "zod";
4686
5379
 
4687
5380
  // src/tools/jobs/space-to-space-migration/instructions.ts
4688
5381
  var S2S_MIGRATION_INSTRUCTIONS = `
@@ -4725,7 +5418,7 @@ The space to space migration workflow has been concluded and all related tools h
4725
5418
  The workflow is now complete. You can start a new migration workflow by calling space_to_space_migration_handler with enableWorkflow=true if needed.
4726
5419
  `;
4727
5420
  var SpaceToSpaceMigrationHandlerToolParams = BaseToolSchema.extend({
4728
- enableWorkflow: z75.boolean().describe(
5421
+ enableWorkflow: z78.boolean().describe(
4729
5422
  "Set to true to enable the workflow tools, false to disable them and conclude the workflow"
4730
5423
  )
4731
5424
  });