@contentful/mcp-tools 0.4.4 → 0.7.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 +134 -49
  2. package/dist/index.js +1056 -533
  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
  }
@@ -1071,6 +1188,10 @@ var PublishAssetToolParams = BaseToolSchema.extend({
1071
1188
  });
1072
1189
  function publishAssetTool(config) {
1073
1190
  async function tool2(args) {
1191
+ assertEnvironmentNotProtected(
1192
+ args.environmentId,
1193
+ config.protectedEnvironments
1194
+ );
1074
1195
  const baseParams = {
1075
1196
  spaceId: args.spaceId,
1076
1197
  environmentId: args.environmentId
@@ -1131,6 +1252,10 @@ var UnpublishAssetToolParams = BaseToolSchema.extend({
1131
1252
  });
1132
1253
  function unpublishAssetTool(config) {
1133
1254
  async function tool2(args) {
1255
+ assertEnvironmentNotProtected(
1256
+ args.environmentId,
1257
+ config.protectedEnvironments
1258
+ );
1134
1259
  const baseParams = {
1135
1260
  spaceId: args.spaceId,
1136
1261
  environmentId: args.environmentId
@@ -1191,6 +1316,10 @@ var ArchiveAssetToolParams = BaseToolSchema.extend({
1191
1316
  });
1192
1317
  function archiveAssetTool(config) {
1193
1318
  async function tool2(args) {
1319
+ assertEnvironmentNotProtected(
1320
+ args.environmentId,
1321
+ config.protectedEnvironments
1322
+ );
1194
1323
  const baseParams = {
1195
1324
  spaceId: args.spaceId,
1196
1325
  environmentId: args.environmentId
@@ -1237,6 +1366,10 @@ var UnarchiveAssetToolParams = BaseToolSchema.extend({
1237
1366
  });
1238
1367
  function unarchiveAssetTool(config) {
1239
1368
  async function tool2(args) {
1369
+ assertEnvironmentNotProtected(
1370
+ args.environmentId,
1371
+ config.protectedEnvironments
1372
+ );
1240
1373
  const baseParams = {
1241
1374
  spaceId: args.spaceId,
1242
1375
  environmentId: args.environmentId
@@ -1332,12 +1465,12 @@ function createAssetTools(config) {
1332
1465
  },
1333
1466
  deleteAsset: {
1334
1467
  title: "delete_asset",
1335
- description: "Delete an asset",
1468
+ 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
1469
  inputParams: DeleteAssetToolParams.shape,
1337
1470
  annotations: {
1338
1471
  readOnlyHint: false,
1339
1472
  destructiveHint: true,
1340
- idempotentHint: true,
1473
+ idempotentHint: false,
1341
1474
  openWorldHint: false
1342
1475
  },
1343
1476
  tool: deleteAsset
@@ -1577,6 +1710,10 @@ var CreateContentTypeToolParams = BaseToolSchema.extend({
1577
1710
  });
1578
1711
  function createContentTypeTool(config) {
1579
1712
  async function tool2(args) {
1713
+ assertEnvironmentNotProtected(
1714
+ args.environmentId,
1715
+ config.protectedEnvironments
1716
+ );
1580
1717
  const params = {
1581
1718
  spaceId: args.spaceId,
1582
1719
  environmentId: args.environmentId
@@ -1614,6 +1751,10 @@ var UpdateContentTypeToolParams = BaseToolSchema.extend({
1614
1751
  });
1615
1752
  function updateContentTypeTool(config) {
1616
1753
  async function tool2(args) {
1754
+ assertEnvironmentNotProtected(
1755
+ args.environmentId,
1756
+ config.protectedEnvironments
1757
+ );
1617
1758
  const params = {
1618
1759
  spaceId: args.spaceId,
1619
1760
  environmentId: args.environmentId,
@@ -1664,16 +1805,43 @@ function updateContentTypeTool(config) {
1664
1805
  // src/tools/content-types/deleteContentType.ts
1665
1806
  import { z as z29 } from "zod";
1666
1807
  var DeleteContentTypeToolParams = BaseToolSchema.extend({
1667
- contentTypeId: z29.string().describe("The ID of the content type to delete")
1808
+ contentTypeId: z29.string().describe("The ID of the content type to delete"),
1809
+ confirm: z29.boolean().optional().describe(
1810
+ "Set to true on the second call to actually perform the deletion. Required together with confirmToken."
1811
+ ),
1812
+ confirmToken: z29.string().optional().describe(
1813
+ "Token returned by the preview call; must be supplied with confirm: true."
1814
+ )
1668
1815
  });
1669
1816
  function deleteContentTypeTool(config) {
1670
1817
  async function tool2(args) {
1818
+ assertEnvironmentNotProtected(
1819
+ args.environmentId,
1820
+ config.protectedEnvironments
1821
+ );
1671
1822
  const params = {
1672
1823
  spaceId: args.spaceId,
1673
1824
  environmentId: args.environmentId,
1674
1825
  contentTypeId: args.contentTypeId
1675
1826
  };
1676
1827
  const contentfulClient = createToolClient(config, args);
1828
+ const contentType = await contentfulClient.contentType.get(params);
1829
+ const expectedToken = buildConfirmToken(
1830
+ "contentType",
1831
+ args.contentTypeId,
1832
+ contentType.sys.version
1833
+ );
1834
+ if (args.confirm !== true || args.confirmToken !== expectedToken) {
1835
+ return createSuccessResponse(
1836
+ `${CONFIRMATION_MESSAGE_PREFIX} content type`,
1837
+ buildConfirmationPreview(
1838
+ "contentType",
1839
+ args.contentTypeId,
1840
+ { contentType },
1841
+ expectedToken
1842
+ )
1843
+ );
1844
+ }
1677
1845
  await contentfulClient.contentType.delete(params);
1678
1846
  return createSuccessResponse("Content type deleted successfully", {
1679
1847
  contentTypeId: args.contentTypeId
@@ -1689,6 +1857,10 @@ var PublishContentTypeToolParams = BaseToolSchema.extend({
1689
1857
  });
1690
1858
  function publishContentTypeTool(config) {
1691
1859
  async function tool2(args) {
1860
+ assertEnvironmentNotProtected(
1861
+ args.environmentId,
1862
+ config.protectedEnvironments
1863
+ );
1692
1864
  const params = {
1693
1865
  spaceId: args.spaceId,
1694
1866
  environmentId: args.environmentId,
@@ -1714,6 +1886,10 @@ var UnpublishContentTypeToolParams = BaseToolSchema.extend({
1714
1886
  });
1715
1887
  function unpublishContentTypeTool(config) {
1716
1888
  async function tool2(args) {
1889
+ assertEnvironmentNotProtected(
1890
+ args.environmentId,
1891
+ config.protectedEnvironments
1892
+ );
1717
1893
  const params = {
1718
1894
  spaceId: args.spaceId,
1719
1895
  environmentId: args.environmentId,
@@ -1728,6 +1904,146 @@ function unpublishContentTypeTool(config) {
1728
1904
  return withErrorHandling(tool2, "Error unpublishing content type");
1729
1905
  }
1730
1906
 
1907
+ // src/tools/content-types/omitContentTypeField.ts
1908
+ import { z as z32 } from "zod";
1909
+ var OmitContentTypeFieldToolParams = BaseToolSchema.extend({
1910
+ contentTypeId: z32.string().describe("The ID of the content type containing the field"),
1911
+ fieldId: z32.string().describe("The ID of the field to omit"),
1912
+ omitted: z32.boolean().default(true).describe(
1913
+ "Whether the field should be omitted. Defaults to true. Set to false to un-omit a field."
1914
+ )
1915
+ });
1916
+ function omitContentTypeFieldTool(config) {
1917
+ async function tool2(args) {
1918
+ const params = {
1919
+ spaceId: args.spaceId,
1920
+ environmentId: args.environmentId,
1921
+ contentTypeId: args.contentTypeId
1922
+ };
1923
+ const contentfulClient = createToolClient(config, args);
1924
+ const currentContentType = await contentfulClient.contentType.get(params);
1925
+ const field = currentContentType.fields.find((f) => f.id === args.fieldId);
1926
+ if (!field) {
1927
+ throw new Error(
1928
+ `Field "${args.fieldId}" not found on content type "${args.contentTypeId}"`
1929
+ );
1930
+ }
1931
+ const updatedFields = currentContentType.fields.map(
1932
+ (f) => f.id === args.fieldId ? { ...f, omitted: args.omitted } : f
1933
+ );
1934
+ const updatedContentType = await contentfulClient.contentType.update(
1935
+ params,
1936
+ { ...currentContentType, fields: updatedFields }
1937
+ );
1938
+ return createSuccessResponse(
1939
+ `Field "${args.fieldId}" updated (omitted=${args.omitted}) on content type "${args.contentTypeId}". Publish the content type for the change to take effect.`,
1940
+ { contentType: updatedContentType }
1941
+ );
1942
+ }
1943
+ return withErrorHandling(tool2, "Error omitting field");
1944
+ }
1945
+
1946
+ // src/tools/content-types/deleteContentTypeField.ts
1947
+ import { z as z33 } from "zod";
1948
+ var DeleteContentTypeFieldToolParams = BaseToolSchema.extend({
1949
+ contentTypeId: z33.string().describe("The ID of the content type containing the field"),
1950
+ fieldId: z33.string().describe("The ID of the field to delete")
1951
+ });
1952
+ function deleteContentTypeFieldTool(config) {
1953
+ async function tool2(args) {
1954
+ const params = {
1955
+ spaceId: args.spaceId,
1956
+ environmentId: args.environmentId,
1957
+ contentTypeId: args.contentTypeId
1958
+ };
1959
+ const contentfulClient = createToolClient(config, args);
1960
+ const currentContentType = await contentfulClient.contentType.get(params);
1961
+ const field = currentContentType.fields.find((f) => f.id === args.fieldId);
1962
+ if (!field) {
1963
+ throw new Error(
1964
+ `Field "${args.fieldId}" not found on content type "${args.contentTypeId}"`
1965
+ );
1966
+ }
1967
+ if (field.required) {
1968
+ throw new Error(
1969
+ `Field "${args.fieldId}" is required. Set required=false via update_content_type and publish before deleting.`
1970
+ );
1971
+ }
1972
+ if (!field.omitted) {
1973
+ throw new Error(
1974
+ `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.`
1975
+ );
1976
+ }
1977
+ const updatedFields = currentContentType.fields.map(
1978
+ (f) => f.id === args.fieldId ? { ...f, deleted: true } : f
1979
+ );
1980
+ const updatedContentType = await contentfulClient.contentType.update(
1981
+ params,
1982
+ { ...currentContentType, fields: updatedFields }
1983
+ );
1984
+ return createSuccessResponse(
1985
+ `Field "${args.fieldId}" marked deleted on content type "${args.contentTypeId}". Publish the content type for the deletion to take effect.`,
1986
+ { contentType: updatedContentType }
1987
+ );
1988
+ }
1989
+ return withErrorHandling(tool2, "Error deleting field");
1990
+ }
1991
+
1992
+ // src/tools/content-types/disableContentTypeField.ts
1993
+ import { z as z34 } from "zod";
1994
+ var DisableContentTypeFieldToolParams = BaseToolSchema.extend({
1995
+ contentTypeId: z34.string().describe("The ID of the content type containing the field"),
1996
+ fieldId: z34.string().describe("The ID of the field to update"),
1997
+ disabled: z34.boolean().optional().describe(
1998
+ "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."
1999
+ ),
2000
+ omitted: z34.boolean().optional().describe(
2001
+ "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."
2002
+ )
2003
+ });
2004
+ function disableContentTypeFieldTool(config) {
2005
+ async function tool2(args) {
2006
+ if (args.disabled === void 0 && args.omitted === void 0) {
2007
+ throw new Error(
2008
+ 'At least one of "disabled" or "omitted" must be provided'
2009
+ );
2010
+ }
2011
+ const params = {
2012
+ spaceId: args.spaceId,
2013
+ environmentId: args.environmentId,
2014
+ contentTypeId: args.contentTypeId
2015
+ };
2016
+ const contentfulClient = createToolClient(config, args);
2017
+ const currentContentType = await contentfulClient.contentType.get(params);
2018
+ const field = currentContentType.fields.find((f) => f.id === args.fieldId);
2019
+ if (!field) {
2020
+ throw new Error(
2021
+ `Field "${args.fieldId}" not found on content type "${args.contentTypeId}"`
2022
+ );
2023
+ }
2024
+ const updatedFields = currentContentType.fields.map((f) => {
2025
+ if (f.id !== args.fieldId) return f;
2026
+ return {
2027
+ ...f,
2028
+ ...args.disabled !== void 0 && { disabled: args.disabled },
2029
+ ...args.omitted !== void 0 && { omitted: args.omitted }
2030
+ };
2031
+ });
2032
+ const updatedContentType = await contentfulClient.contentType.update(
2033
+ params,
2034
+ { ...currentContentType, fields: updatedFields }
2035
+ );
2036
+ const changes = [];
2037
+ if (args.disabled !== void 0) changes.push(`disabled=${args.disabled}`);
2038
+ if (args.omitted !== void 0) changes.push(`omitted=${args.omitted}`);
2039
+ return createSuccessResponse(
2040
+ `Field "${args.fieldId}" updated (${changes.join(", ")}) on content type "${args.contentTypeId}". Publish the content type for the change to take effect.`,
2041
+ { contentType: updatedContentType }
2042
+ );
2043
+ }
2044
+ return withErrorHandling(tool2, "Error updating field");
2045
+ }
2046
+
1731
2047
  // src/tools/content-types/register.ts
1732
2048
  function createContentTypeTools(config) {
1733
2049
  const getContentType = getContentTypeTool(config);
@@ -1737,6 +2053,9 @@ function createContentTypeTools(config) {
1737
2053
  const deleteContentType = deleteContentTypeTool(config);
1738
2054
  const publishContentType = publishContentTypeTool(config);
1739
2055
  const unpublishContentType = unpublishContentTypeTool(config);
2056
+ const omitContentTypeField = omitContentTypeFieldTool(config);
2057
+ const deleteContentTypeField = deleteContentTypeFieldTool(config);
2058
+ const disableContentTypeField = disableContentTypeFieldTool(config);
1740
2059
  return {
1741
2060
  getContentType: {
1742
2061
  title: "get_content_type",
@@ -1784,12 +2103,12 @@ function createContentTypeTools(config) {
1784
2103
  },
1785
2104
  deleteContentType: {
1786
2105
  title: "delete_content_type",
1787
- description: "Delete a content type",
2106
+ 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
2107
  inputParams: DeleteContentTypeToolParams.shape,
1789
2108
  annotations: {
1790
2109
  readOnlyHint: false,
1791
2110
  destructiveHint: true,
1792
- idempotentHint: true,
2111
+ idempotentHint: false,
1793
2112
  openWorldHint: false
1794
2113
  },
1795
2114
  tool: deleteContentType
@@ -1817,12 +2136,48 @@ function createContentTypeTools(config) {
1817
2136
  openWorldHint: false
1818
2137
  },
1819
2138
  tool: unpublishContentType
2139
+ },
2140
+ omitContentTypeField: {
2141
+ title: "omit_content_type_field",
2142
+ 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.",
2143
+ inputParams: OmitContentTypeFieldToolParams.shape,
2144
+ annotations: {
2145
+ readOnlyHint: false,
2146
+ destructiveHint: false,
2147
+ idempotentHint: false,
2148
+ openWorldHint: false
2149
+ },
2150
+ tool: omitContentTypeField
2151
+ },
2152
+ deleteContentTypeField: {
2153
+ title: "delete_content_type_field",
2154
+ 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.",
2155
+ inputParams: DeleteContentTypeFieldToolParams.shape,
2156
+ annotations: {
2157
+ readOnlyHint: false,
2158
+ destructiveHint: true,
2159
+ idempotentHint: false,
2160
+ openWorldHint: false
2161
+ },
2162
+ tool: deleteContentTypeField
2163
+ },
2164
+ disableContentTypeField: {
2165
+ title: "disable_content_type_field",
2166
+ 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.",
2167
+ inputParams: DisableContentTypeFieldToolParams.shape,
2168
+ annotations: {
2169
+ readOnlyHint: false,
2170
+ destructiveHint: false,
2171
+ idempotentHint: false,
2172
+ openWorldHint: false
2173
+ },
2174
+ tool: disableContentTypeField
1820
2175
  }
1821
2176
  };
1822
2177
  }
1823
2178
 
1824
2179
  // src/tools/context/getInitialContextTool.ts
1825
- import { z as z32 } from "zod";
2180
+ import { z as z35 } from "zod";
1826
2181
  import { outdent } from "outdent";
1827
2182
 
1828
2183
  // src/tools/context/store.ts
@@ -1959,7 +2314,7 @@ Before running a tool:
1959
2314
  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
2315
 
1961
2316
  // src/tools/context/getInitialContextTool.ts
1962
- var GetInitialContextToolParams = z32.object({});
2317
+ var GetInitialContextToolParams = z35.object({});
1963
2318
  function getInitialContextTool(config) {
1964
2319
  async function tool2(_params) {
1965
2320
  const configInfo = `Current Contentful Configuration:
@@ -2046,9 +2401,9 @@ function listEditorInterfacesTool(config) {
2046
2401
  }
2047
2402
 
2048
2403
  // src/tools/editor-interfaces/getEditorInterface.ts
2049
- import { z as z33 } from "zod";
2404
+ import { z as z36 } from "zod";
2050
2405
  var GetEditorInterfaceToolParams = BaseToolSchema.extend({
2051
- contentTypeId: z33.string().describe(
2406
+ contentTypeId: z36.string().describe(
2052
2407
  "The ID of the content type to retrieve the editor interface for"
2053
2408
  )
2054
2409
  });
@@ -2069,45 +2424,49 @@ function getEditorInterfaceTool(config) {
2069
2424
  }
2070
2425
 
2071
2426
  // 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(
2427
+ import { z as z37 } from "zod";
2428
+ var ControlSchema = z37.object({
2429
+ fieldId: z37.string().describe("The field ID this control applies to"),
2430
+ widgetId: z37.string().describe("The widget ID to use for this field"),
2431
+ widgetNamespace: z37.enum(["builtin", "extension", "app", "editor-builtin"]).optional().describe(
2077
2432
  "The namespace of the widget (builtin, extension, app, or editor-builtin)"
2078
2433
  ),
2079
- settings: z34.record(z34.any()).optional().describe("Settings object for the widget")
2434
+ settings: z37.record(z37.any()).optional().describe("Settings object for the widget")
2080
2435
  });
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")
2436
+ var SidebarItemSchema = z37.object({
2437
+ widgetId: z37.string().describe("The widget ID for the sidebar item"),
2438
+ widgetNamespace: z37.enum(["sidebar-builtin", "extension", "app"]).describe("The namespace of the sidebar widget"),
2439
+ settings: z37.record(z37.any()).optional().describe("Settings object for the sidebar widget"),
2440
+ disabled: z37.boolean().optional().describe("Whether the sidebar item is disabled")
2086
2441
  });
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")
2442
+ var EditorLayoutItemSchema = z37.object({
2443
+ fieldId: z37.string().describe("The field ID"),
2444
+ settings: z37.record(z37.any()).optional().describe("Layout settings for the field")
2090
2445
  });
2091
- var EditorLayoutSchema = z34.object({
2092
- items: z34.array(EditorLayoutItemSchema).optional().describe("Array of editor layout items")
2446
+ var EditorLayoutSchema = z37.object({
2447
+ items: z37.array(EditorLayoutItemSchema).optional().describe("Array of editor layout items")
2093
2448
  });
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")
2449
+ var GroupControlSchema = z37.object({
2450
+ groupId: z37.string().describe("The group ID"),
2451
+ widgetId: z37.string().describe("The widget ID for the group control"),
2452
+ widgetNamespace: z37.enum(["builtin", "extension", "app"]).optional().describe("The namespace of the group control widget"),
2453
+ settings: z37.record(z37.any()).optional().describe("Settings object for the group control")
2099
2454
  });
2100
2455
  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(
2456
+ contentTypeId: z37.string().describe("The ID of the content type to update the editor interface for"),
2457
+ controls: z37.array(ControlSchema).optional().describe(
2103
2458
  "Array of control definitions for fields in the content type. Each control defines which widget to use for a field."
2104
2459
  ),
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")
2460
+ sidebar: z37.array(SidebarItemSchema).optional().describe("Array of sidebar widget configurations"),
2461
+ editorLayout: z37.array(EditorLayoutSchema).optional().describe("Editor layout configuration for organizing fields"),
2462
+ groupControls: z37.array(GroupControlSchema).optional().describe("Array of group control definitions for field groups")
2108
2463
  });
2109
2464
  function updateEditorInterfaceTool(config) {
2110
2465
  async function tool2(args) {
2466
+ assertEnvironmentNotProtected(
2467
+ args.environmentId,
2468
+ config.protectedEnvironments
2469
+ );
2111
2470
  const params = {
2112
2471
  spaceId: args.spaceId,
2113
2472
  environmentId: args.environmentId,
@@ -2183,7 +2542,7 @@ function createEditorInterfaceTools(config) {
2183
2542
  }
2184
2543
 
2185
2544
  // src/tools/entries/searchEntries.ts
2186
- import { z as z35 } from "zod";
2545
+ import { z as z38 } from "zod";
2187
2546
 
2188
2547
  // src/utils/limits.ts
2189
2548
  function searchLimit(userLimit) {
@@ -2206,38 +2565,38 @@ function normalizeArrayFilters(query) {
2206
2565
 
2207
2566
  // src/tools/entries/searchEntries.ts
2208
2567
  var SearchEntriesToolParams = BaseToolSchema.extend({
2209
- query: z35.object({
2568
+ query: z38.object({
2210
2569
  // 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(
2570
+ content_type: z38.string().optional().describe("Filter by content type"),
2571
+ include: z38.number().optional().describe("Include this many levels of linked entries"),
2572
+ select: z38.string().optional().describe("Comma-separated list of fields to return"),
2573
+ links_to_entry: z38.string().optional().describe("Find entries that link to the specified entry ID"),
2574
+ limit: z38.number().optional().describe(
2216
2575
  "Maximum number of entries to return (default: 10, max: 100)"
2217
2576
  ),
2218
- skip: z35.number().optional().describe("Skip this many entries for pagination"),
2219
- order: z35.string().optional().describe("Order entries by this field"),
2577
+ skip: z38.number().optional().describe("Skip this many entries for pagination"),
2578
+ order: z38.string().optional().describe("Order entries by this field"),
2220
2579
  // Full-text search
2221
- query: z35.string().optional().describe("Full-text search across all fields"),
2580
+ query: z38.string().optional().describe("Full-text search across all fields"),
2222
2581
  // 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"),
2582
+ "fields.title": z38.string().optional().describe("Search by title field"),
2583
+ "fields.slug": z38.string().optional().describe("Search by slug field"),
2584
+ "fields.internalName": z38.string().optional().describe("Search by internal name field"),
2585
+ "fields.text": z38.string().optional().describe("Search by text field (useful for testimonials)"),
2586
+ "fields.title[match]": z38.string().optional().describe("Pattern match on title field"),
2587
+ "fields.slug[match]": z38.string().optional().describe("Pattern match on slug field"),
2588
+ "fields.title[exists]": z38.boolean().optional().describe("Check if title field exists"),
2589
+ "fields.slug[exists]": z38.boolean().optional().describe("Check if slug field exists"),
2231
2590
  // 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)"),
2591
+ "sys.id[in]": z38.array(z38.string()).optional().describe("Search by multiple entry IDs"),
2592
+ "sys.contentType.sys.id": z38.string().optional().describe("Filter by content type ID"),
2593
+ "sys.createdAt[gte]": z38.string().optional().describe("Created after date (ISO format)"),
2594
+ "sys.createdAt[lte]": z38.string().optional().describe("Created before date (ISO format)"),
2595
+ "sys.updatedAt[gte]": z38.string().optional().describe("Updated after date (ISO format)"),
2596
+ "sys.updatedAt[lte]": z38.string().optional().describe("Updated before date (ISO format)"),
2238
2597
  // Metadata searches
2239
- "metadata.tags.sys.id[in]": z35.array(z35.string()).optional().describe("Filter by tag IDs")
2240
- }).catchall(z35.any()).describe(
2598
+ "metadata.tags.sys.id[in]": z38.array(z38.string()).optional().describe("Filter by tag IDs")
2599
+ }).catchall(z38.any()).describe(
2241
2600
  "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
2601
  )
2243
2602
  });
@@ -2268,110 +2627,110 @@ function searchEntriesTool(config) {
2268
2627
  }
2269
2628
 
2270
2629
  // src/tools/entries/createEntry.ts
2271
- import { z as z38 } from "zod";
2630
+ import { z as z41 } from "zod";
2272
2631
 
2273
2632
  // src/types/entryFieldSchema.ts
2274
- import { z as z37 } from "zod";
2633
+ import { z as z40 } from "zod";
2275
2634
 
2276
2635
  // src/types/richTextSchema.ts
2277
2636
  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")
2637
+ import { z as z39 } from "zod";
2638
+ var emptyNodeDataSchema = z39.object({});
2639
+ var entryLinkTargetSchema = z39.object({
2640
+ sys: z39.object({
2641
+ id: z39.string(),
2642
+ type: z39.literal("Link"),
2643
+ linkType: z39.literal("Entry")
2285
2644
  })
2286
2645
  });
2287
- var assetLinkTargetSchema = z36.object({
2288
- sys: z36.object({
2289
- id: z36.string(),
2290
- type: z36.literal("Link"),
2291
- linkType: z36.literal("Asset")
2646
+ var assetLinkTargetSchema = z39.object({
2647
+ sys: z39.object({
2648
+ id: z39.string(),
2649
+ type: z39.literal("Link"),
2650
+ linkType: z39.literal("Asset")
2292
2651
  })
2293
2652
  });
2294
- var resourceLinkTargetSchema = z36.object({
2295
- sys: z36.object({
2296
- type: z36.literal("ResourceLink"),
2297
- linkType: z36.string(),
2298
- urn: z36.string()
2653
+ var resourceLinkTargetSchema = z39.object({
2654
+ sys: z39.object({
2655
+ type: z39.literal("ResourceLink"),
2656
+ linkType: z39.string(),
2657
+ urn: z39.string()
2299
2658
  })
2300
2659
  });
2301
- var richTextMarkSchema = z36.object({
2302
- type: z36.nativeEnum(MARKS)
2660
+ var richTextMarkSchema = z39.object({
2661
+ type: z39.nativeEnum(MARKS)
2303
2662
  });
2304
- var richTextTextNodeSchema = z36.object({
2305
- nodeType: z36.literal("text"),
2306
- value: z36.string(),
2307
- marks: z36.array(richTextMarkSchema),
2663
+ var richTextTextNodeSchema = z39.object({
2664
+ nodeType: z39.literal("text"),
2665
+ value: z39.string(),
2666
+ marks: z39.array(richTextMarkSchema),
2308
2667
  data: emptyNodeDataSchema
2309
2668
  });
2310
- var embeddedEntryBlockNodeSchema = z36.object({
2311
- nodeType: z36.literal(BLOCKS2.EMBEDDED_ENTRY),
2312
- data: z36.object({
2669
+ var embeddedEntryBlockNodeSchema = z39.object({
2670
+ nodeType: z39.literal(BLOCKS2.EMBEDDED_ENTRY),
2671
+ data: z39.object({
2313
2672
  target: entryLinkTargetSchema
2314
2673
  }),
2315
- content: z36.array(z36.never())
2674
+ content: z39.array(z39.never())
2316
2675
  });
2317
- var embeddedEntryInlineNodeSchema = z36.object({
2318
- nodeType: z36.literal(INLINES2.EMBEDDED_ENTRY),
2319
- data: z36.object({
2676
+ var embeddedEntryInlineNodeSchema = z39.object({
2677
+ nodeType: z39.literal(INLINES2.EMBEDDED_ENTRY),
2678
+ data: z39.object({
2320
2679
  target: entryLinkTargetSchema
2321
2680
  }),
2322
- content: z36.array(z36.never())
2681
+ content: z39.array(z39.never())
2323
2682
  });
2324
- var embeddedAssetBlockNodeSchema = z36.object({
2325
- nodeType: z36.literal(BLOCKS2.EMBEDDED_ASSET),
2326
- data: z36.object({
2683
+ var embeddedAssetBlockNodeSchema = z39.object({
2684
+ nodeType: z39.literal(BLOCKS2.EMBEDDED_ASSET),
2685
+ data: z39.object({
2327
2686
  target: assetLinkTargetSchema
2328
2687
  }),
2329
- content: z36.array(z36.never())
2688
+ content: z39.array(z39.never())
2330
2689
  });
2331
- var hyperlinkInlineNodeSchema = z36.object({
2332
- nodeType: z36.literal(INLINES2.HYPERLINK),
2333
- data: z36.object({
2334
- uri: z36.string().url()
2690
+ var hyperlinkInlineNodeSchema = z39.object({
2691
+ nodeType: z39.literal(INLINES2.HYPERLINK),
2692
+ data: z39.object({
2693
+ uri: z39.string().url()
2335
2694
  }),
2336
- content: z36.array(richTextTextNodeSchema)
2695
+ content: z39.array(richTextTextNodeSchema)
2337
2696
  });
2338
- var entryHyperlinkInlineNodeSchema = z36.object({
2339
- nodeType: z36.literal(INLINES2.ENTRY_HYPERLINK),
2340
- data: z36.object({
2697
+ var entryHyperlinkInlineNodeSchema = z39.object({
2698
+ nodeType: z39.literal(INLINES2.ENTRY_HYPERLINK),
2699
+ data: z39.object({
2341
2700
  target: entryLinkTargetSchema
2342
2701
  }),
2343
- content: z36.array(richTextTextNodeSchema)
2702
+ content: z39.array(richTextTextNodeSchema)
2344
2703
  });
2345
- var assetHyperlinkInlineNodeSchema = z36.object({
2346
- nodeType: z36.literal(INLINES2.ASSET_HYPERLINK),
2347
- data: z36.object({
2704
+ var assetHyperlinkInlineNodeSchema = z39.object({
2705
+ nodeType: z39.literal(INLINES2.ASSET_HYPERLINK),
2706
+ data: z39.object({
2348
2707
  target: assetLinkTargetSchema
2349
2708
  }),
2350
- content: z36.array(richTextTextNodeSchema)
2709
+ content: z39.array(richTextTextNodeSchema)
2351
2710
  });
2352
- var embeddedResourceBlockNodeSchema = z36.object({
2353
- nodeType: z36.literal(BLOCKS2.EMBEDDED_RESOURCE),
2354
- data: z36.object({
2711
+ var embeddedResourceBlockNodeSchema = z39.object({
2712
+ nodeType: z39.literal(BLOCKS2.EMBEDDED_RESOURCE),
2713
+ data: z39.object({
2355
2714
  target: resourceLinkTargetSchema
2356
2715
  }),
2357
- content: z36.array(z36.never())
2716
+ content: z39.array(z39.never())
2358
2717
  });
2359
- var embeddedResourceInlineNodeSchema = z36.object({
2360
- nodeType: z36.literal(INLINES2.EMBEDDED_RESOURCE),
2361
- data: z36.object({
2718
+ var embeddedResourceInlineNodeSchema = z39.object({
2719
+ nodeType: z39.literal(INLINES2.EMBEDDED_RESOURCE),
2720
+ data: z39.object({
2362
2721
  target: resourceLinkTargetSchema
2363
2722
  }),
2364
- content: z36.array(z36.never())
2723
+ content: z39.array(z39.never())
2365
2724
  });
2366
- var resourceHyperlinkInlineNodeSchema = z36.object({
2367
- nodeType: z36.literal(INLINES2.RESOURCE_HYPERLINK),
2368
- data: z36.object({
2725
+ var resourceHyperlinkInlineNodeSchema = z39.object({
2726
+ nodeType: z39.literal(INLINES2.RESOURCE_HYPERLINK),
2727
+ data: z39.object({
2369
2728
  target: resourceLinkTargetSchema
2370
2729
  }),
2371
- content: z36.array(richTextTextNodeSchema)
2730
+ content: z39.array(richTextTextNodeSchema)
2372
2731
  });
2373
- var richTextInlineNodeSchema = z36.lazy(
2374
- () => z36.union([
2732
+ var richTextInlineNodeSchema = z39.lazy(
2733
+ () => z39.union([
2375
2734
  richTextTextNodeSchema,
2376
2735
  embeddedEntryInlineNodeSchema,
2377
2736
  hyperlinkInlineNodeSchema,
@@ -2381,17 +2740,17 @@ var richTextInlineNodeSchema = z36.lazy(
2381
2740
  resourceHyperlinkInlineNodeSchema
2382
2741
  ])
2383
2742
  );
2384
- var paragraphNodeSchema = z36.lazy(
2385
- () => z36.object({
2386
- nodeType: z36.literal(BLOCKS2.PARAGRAPH),
2743
+ var paragraphNodeSchema = z39.lazy(
2744
+ () => z39.object({
2745
+ nodeType: z39.literal(BLOCKS2.PARAGRAPH),
2387
2746
  data: emptyNodeDataSchema,
2388
- content: z36.array(richTextInlineNodeSchema)
2747
+ content: z39.array(richTextInlineNodeSchema)
2389
2748
  })
2390
2749
  );
2391
- var headingNodeSchema = (headingNodeType) => z36.object({
2392
- nodeType: z36.literal(headingNodeType),
2750
+ var headingNodeSchema = (headingNodeType) => z39.object({
2751
+ nodeType: z39.literal(headingNodeType),
2393
2752
  data: emptyNodeDataSchema,
2394
- content: z36.array(richTextInlineNodeSchema)
2753
+ content: z39.array(richTextInlineNodeSchema)
2395
2754
  });
2396
2755
  var heading1NodeSchema = headingNodeSchema(BLOCKS2.HEADING_1);
2397
2756
  var heading2NodeSchema = headingNodeSchema(BLOCKS2.HEADING_2);
@@ -2399,56 +2758,56 @@ var heading3NodeSchema = headingNodeSchema(BLOCKS2.HEADING_3);
2399
2758
  var heading4NodeSchema = headingNodeSchema(BLOCKS2.HEADING_4);
2400
2759
  var heading5NodeSchema = headingNodeSchema(BLOCKS2.HEADING_5);
2401
2760
  var heading6NodeSchema = headingNodeSchema(BLOCKS2.HEADING_6);
2402
- var hrNodeSchema = z36.object({
2403
- nodeType: z36.literal(BLOCKS2.HR),
2761
+ var hrNodeSchema = z39.object({
2762
+ nodeType: z39.literal(BLOCKS2.HR),
2404
2763
  data: emptyNodeDataSchema,
2405
- content: z36.array(z36.never())
2764
+ content: z39.array(z39.never())
2406
2765
  });
2407
- var quoteNodeSchema = z36.object({
2408
- nodeType: z36.literal(BLOCKS2.QUOTE),
2766
+ var quoteNodeSchema = z39.object({
2767
+ nodeType: z39.literal(BLOCKS2.QUOTE),
2409
2768
  data: emptyNodeDataSchema,
2410
- content: z36.array(paragraphNodeSchema)
2769
+ content: z39.array(paragraphNodeSchema)
2411
2770
  });
2412
- var tableHeaderCellNodeSchema = z36.object({
2413
- nodeType: z36.literal(BLOCKS2.TABLE_HEADER_CELL),
2771
+ var tableHeaderCellNodeSchema = z39.object({
2772
+ nodeType: z39.literal(BLOCKS2.TABLE_HEADER_CELL),
2414
2773
  data: emptyNodeDataSchema,
2415
- content: z36.array(paragraphNodeSchema)
2774
+ content: z39.array(paragraphNodeSchema)
2416
2775
  });
2417
- var tableCellNodeSchema = z36.object({
2418
- nodeType: z36.literal(BLOCKS2.TABLE_CELL),
2776
+ var tableCellNodeSchema = z39.object({
2777
+ nodeType: z39.literal(BLOCKS2.TABLE_CELL),
2419
2778
  data: emptyNodeDataSchema,
2420
- content: z36.array(paragraphNodeSchema)
2779
+ content: z39.array(paragraphNodeSchema)
2421
2780
  });
2422
- var tableRowNodeSchema = z36.object({
2423
- nodeType: z36.literal(BLOCKS2.TABLE_ROW),
2781
+ var tableRowNodeSchema = z39.object({
2782
+ nodeType: z39.literal(BLOCKS2.TABLE_ROW),
2424
2783
  data: emptyNodeDataSchema,
2425
- content: z36.array(z36.union([tableHeaderCellNodeSchema, tableCellNodeSchema]))
2784
+ content: z39.array(z39.union([tableHeaderCellNodeSchema, tableCellNodeSchema]))
2426
2785
  });
2427
- var tableNodeSchema = z36.object({
2428
- nodeType: z36.literal(BLOCKS2.TABLE),
2786
+ var tableNodeSchema = z39.object({
2787
+ nodeType: z39.literal(BLOCKS2.TABLE),
2429
2788
  data: emptyNodeDataSchema,
2430
- content: z36.array(tableRowNodeSchema)
2789
+ content: z39.array(tableRowNodeSchema)
2431
2790
  });
2432
- var orderedListNodeSchema = z36.lazy(
2433
- () => z36.object({
2434
- nodeType: z36.literal(BLOCKS2.OL_LIST),
2791
+ var orderedListNodeSchema = z39.lazy(
2792
+ () => z39.object({
2793
+ nodeType: z39.literal(BLOCKS2.OL_LIST),
2435
2794
  data: emptyNodeDataSchema,
2436
- content: z36.array(listItemNodeSchema)
2795
+ content: z39.array(listItemNodeSchema)
2437
2796
  })
2438
2797
  );
2439
- var unorderedListNodeSchema = z36.lazy(
2440
- () => z36.object({
2441
- nodeType: z36.literal(BLOCKS2.UL_LIST),
2798
+ var unorderedListNodeSchema = z39.lazy(
2799
+ () => z39.object({
2800
+ nodeType: z39.literal(BLOCKS2.UL_LIST),
2442
2801
  data: emptyNodeDataSchema,
2443
- content: z36.array(listItemNodeSchema)
2802
+ content: z39.array(listItemNodeSchema)
2444
2803
  })
2445
2804
  );
2446
- var listItemNodeSchema = z36.lazy(
2447
- () => z36.object({
2448
- nodeType: z36.literal(BLOCKS2.LIST_ITEM),
2805
+ var listItemNodeSchema = z39.lazy(
2806
+ () => z39.object({
2807
+ nodeType: z39.literal(BLOCKS2.LIST_ITEM),
2449
2808
  data: emptyNodeDataSchema,
2450
- content: z36.array(
2451
- z36.union([
2809
+ content: z39.array(
2810
+ z39.union([
2452
2811
  paragraphNodeSchema,
2453
2812
  orderedListNodeSchema,
2454
2813
  unorderedListNodeSchema
@@ -2456,8 +2815,8 @@ var listItemNodeSchema = z36.lazy(
2456
2815
  )
2457
2816
  })
2458
2817
  );
2459
- var topLevelBlockNodeSchema = z36.lazy(
2460
- () => z36.union([
2818
+ var topLevelBlockNodeSchema = z39.lazy(
2819
+ () => z39.union([
2461
2820
  paragraphNodeSchema,
2462
2821
  heading1NodeSchema,
2463
2822
  heading2NodeSchema,
@@ -2475,56 +2834,56 @@ var topLevelBlockNodeSchema = z36.lazy(
2475
2834
  tableNodeSchema
2476
2835
  ])
2477
2836
  );
2478
- var richTextDocumentSchema = z36.object({
2479
- nodeType: z36.literal(BLOCKS2.DOCUMENT),
2837
+ var richTextDocumentSchema = z39.object({
2838
+ nodeType: z39.literal(BLOCKS2.DOCUMENT),
2480
2839
  data: emptyNodeDataSchema,
2481
- content: z36.array(topLevelBlockNodeSchema)
2840
+ content: z39.array(topLevelBlockNodeSchema)
2482
2841
  }).describe("Contentful Rich Text document");
2483
2842
 
2484
2843
  // 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()
2844
+ var linkSchema = z40.object({
2845
+ sys: z40.object({
2846
+ type: z40.literal("Link"),
2847
+ linkType: z40.enum(["Entry", "Asset"]),
2848
+ id: z40.string()
2490
2849
  })
2491
2850
  });
2492
- var resourceLinkSchema = z37.object({
2493
- sys: z37.object({
2494
- type: z37.literal("ResourceLink"),
2495
- linkType: z37.string(),
2496
- urn: z37.string()
2851
+ var resourceLinkSchema = z40.object({
2852
+ sys: z40.object({
2853
+ type: z40.literal("ResourceLink"),
2854
+ linkType: z40.string(),
2855
+ urn: z40.string()
2497
2856
  })
2498
2857
  });
2499
- var locationSchema = z37.object({
2500
- lat: z37.number(),
2501
- lon: z37.number()
2858
+ var locationSchema = z40.object({
2859
+ lat: z40.number(),
2860
+ lon: z40.number()
2502
2861
  });
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)")
2862
+ var jsonPrimitive = z40.union([z40.string(), z40.number(), z40.boolean(), z40.null()]);
2863
+ var jsonValueSchema = z40.lazy(
2864
+ () => z40.union([jsonPrimitive, z40.array(jsonValueSchema), z40.record(jsonValueSchema)]).describe("Freeform JSON value (not for Rich Text)")
2506
2865
  );
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"),
2866
+ var fieldValueSchema = z40.union([
2867
+ z40.string().describe("Symbol, Text, or Date field"),
2868
+ z40.number().describe("Integer or Number field"),
2869
+ z40.boolean().describe("Boolean field"),
2511
2870
  richTextDocumentSchema,
2512
2871
  linkSchema.describe("Link field (Entry or Asset reference)"),
2513
2872
  resourceLinkSchema.describe("ResourceLink field"),
2514
2873
  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"),
2874
+ z40.array(z40.string()).describe("Array field of Symbols"),
2875
+ z40.array(linkSchema).describe("Array field of Links"),
2876
+ z40.array(resourceLinkSchema).describe("Array field of ResourceLinks"),
2518
2877
  jsonValueSchema
2519
2878
  ]);
2520
- var localizedFieldSchema = z37.record(fieldValueSchema);
2521
- var entryFieldsSchema = z37.record(localizedFieldSchema).describe(
2879
+ var localizedFieldSchema = z40.record(fieldValueSchema);
2880
+ var entryFieldsSchema = z40.record(localizedFieldSchema).describe(
2522
2881
  "Field values to update. Keys are field IDs, values are locale-keyed objects. Will be merged with existing fields."
2523
2882
  );
2524
2883
 
2525
2884
  // src/tools/entries/createEntry.ts
2526
2885
  var CreateEntryToolParams = BaseToolSchema.extend({
2527
- contentTypeId: z38.string().describe("The ID of the content type to create an entry for"),
2886
+ contentTypeId: z41.string().describe("The ID of the content type to create an entry for"),
2528
2887
  fields: entryFieldsSchema.describe(
2529
2888
  "The field values for the new entry. Keys should be field IDs and values should be the field content."
2530
2889
  ),
@@ -2532,6 +2891,10 @@ var CreateEntryToolParams = BaseToolSchema.extend({
2532
2891
  });
2533
2892
  function createEntryTool(config) {
2534
2893
  async function tool2(args) {
2894
+ assertEnvironmentNotProtected(
2895
+ args.environmentId,
2896
+ config.protectedEnvironments
2897
+ );
2535
2898
  const params = {
2536
2899
  spaceId: args.spaceId,
2537
2900
  environmentId: args.environmentId
@@ -2553,12 +2916,22 @@ function createEntryTool(config) {
2553
2916
  }
2554
2917
 
2555
2918
  // src/tools/entries/deleteEntry.ts
2556
- import { z as z39 } from "zod";
2919
+ import { z as z42 } from "zod";
2557
2920
  var DeleteEntryToolParams = BaseToolSchema.extend({
2558
- entryId: z39.string().describe("The ID of the entry to delete")
2921
+ entryId: z42.string().describe("The ID of the entry to delete"),
2922
+ confirm: z42.boolean().optional().describe(
2923
+ "Set to true on the second call to actually perform the deletion. Required together with confirmToken."
2924
+ ),
2925
+ confirmToken: z42.string().optional().describe(
2926
+ "Token returned by the preview call; must be supplied with confirm: true."
2927
+ )
2559
2928
  });
2560
2929
  function deleteEntryTool(config) {
2561
2930
  async function tool2(args) {
2931
+ assertEnvironmentNotProtected(
2932
+ args.environmentId,
2933
+ config.protectedEnvironments
2934
+ );
2562
2935
  const params = {
2563
2936
  spaceId: args.spaceId,
2564
2937
  environmentId: args.environmentId,
@@ -2566,6 +2939,22 @@ function deleteEntryTool(config) {
2566
2939
  };
2567
2940
  const contentfulClient = createToolClient(config, args);
2568
2941
  const entry = await contentfulClient.entry.get(params);
2942
+ const expectedToken = buildConfirmToken(
2943
+ "entry",
2944
+ args.entryId,
2945
+ entry.sys.version
2946
+ );
2947
+ if (args.confirm !== true || args.confirmToken !== expectedToken) {
2948
+ return createSuccessResponse(
2949
+ `${CONFIRMATION_MESSAGE_PREFIX} entry`,
2950
+ buildConfirmationPreview(
2951
+ "entry",
2952
+ args.entryId,
2953
+ { entry },
2954
+ expectedToken
2955
+ )
2956
+ );
2957
+ }
2569
2958
  await contentfulClient.entry.delete(params);
2570
2959
  return createSuccessResponse("Entry deleted successfully", { entry });
2571
2960
  }
@@ -2573,9 +2962,9 @@ function deleteEntryTool(config) {
2573
2962
  }
2574
2963
 
2575
2964
  // src/tools/entries/updateEntry.ts
2576
- import { z as z40 } from "zod";
2965
+ import { z as z43 } from "zod";
2577
2966
  var UpdateEntryToolParams = BaseToolSchema.extend({
2578
- entryId: z40.string().describe("The ID of the entry to update"),
2967
+ entryId: z43.string().describe("The ID of the entry to update"),
2579
2968
  fields: entryFieldsSchema.describe(
2580
2969
  "The field values to update. Keys should be field IDs and values should be the field content. Will be merged with existing fields."
2581
2970
  ),
@@ -2583,6 +2972,10 @@ var UpdateEntryToolParams = BaseToolSchema.extend({
2583
2972
  });
2584
2973
  function updateEntryTool(config) {
2585
2974
  async function tool2(args) {
2975
+ assertEnvironmentNotProtected(
2976
+ args.environmentId,
2977
+ config.protectedEnvironments
2978
+ );
2586
2979
  const params = {
2587
2980
  spaceId: args.spaceId,
2588
2981
  environmentId: args.environmentId,
@@ -2618,9 +3011,9 @@ function updateEntryTool(config) {
2618
3011
  }
2619
3012
 
2620
3013
  // src/tools/entries/getEntry.ts
2621
- import { z as z41 } from "zod";
3014
+ import { z as z44 } from "zod";
2622
3015
  var GetEntryToolParams = BaseToolSchema.extend({
2623
- entryId: z41.string().describe("The ID of the entry to retrieve")
3016
+ entryId: z44.string().describe("The ID of the entry to retrieve")
2624
3017
  });
2625
3018
  function getEntryTool(config) {
2626
3019
  async function tool2(args) {
@@ -2637,20 +3030,24 @@ function getEntryTool(config) {
2637
3030
  }
2638
3031
 
2639
3032
  // src/tools/entries/publishEntry.ts
2640
- import { z as z42 } from "zod";
3033
+ import { z as z45 } from "zod";
2641
3034
  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)"
3035
+ entryId: z45.array(z45.string()).min(1).max(100).describe(
3036
+ "Array of entry IDs to publish. Pass a single-element array for one entry, or up to 100 IDs for bulk operations."
2644
3037
  )
2645
3038
  });
2646
3039
  function publishEntryTool(config) {
2647
3040
  async function tool2(args) {
3041
+ assertEnvironmentNotProtected(
3042
+ args.environmentId,
3043
+ config.protectedEnvironments
3044
+ );
2648
3045
  const baseParams = {
2649
3046
  spaceId: args.spaceId,
2650
3047
  environmentId: args.environmentId
2651
3048
  };
2652
3049
  const contentfulClient = createToolClient(config, args);
2653
- const entryIds = Array.isArray(args.entryId) ? args.entryId : [args.entryId];
3050
+ const entryIds = args.entryId;
2654
3051
  if (entryIds.length === 1) {
2655
3052
  const entryId = entryIds[0];
2656
3053
  const params = {
@@ -2658,7 +3055,10 @@ function publishEntryTool(config) {
2658
3055
  entryId
2659
3056
  };
2660
3057
  const entry = await contentfulClient.entry.get(params);
2661
- const publishedEntry = await contentfulClient.entry.publish(params, entry);
3058
+ const publishedEntry = await contentfulClient.entry.publish(
3059
+ params,
3060
+ entry
3061
+ );
2662
3062
  return createSuccessResponse("Entry published successfully", {
2663
3063
  status: publishedEntry.sys.status,
2664
3064
  entryId
@@ -2687,20 +3087,24 @@ function publishEntryTool(config) {
2687
3087
  }
2688
3088
 
2689
3089
  // src/tools/entries/unpublishEntry.ts
2690
- import { z as z43 } from "zod";
3090
+ import { z as z46 } from "zod";
2691
3091
  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)"
3092
+ entryId: z46.array(z46.string()).min(1).max(100).describe(
3093
+ "Array of entry IDs to unpublish. Pass a single-element array for one entry, or up to 100 IDs for bulk operations."
2694
3094
  )
2695
3095
  });
2696
3096
  function unpublishEntryTool(config) {
2697
3097
  async function tool2(args) {
3098
+ assertEnvironmentNotProtected(
3099
+ args.environmentId,
3100
+ config.protectedEnvironments
3101
+ );
2698
3102
  const baseParams = {
2699
3103
  spaceId: args.spaceId,
2700
3104
  environmentId: args.environmentId
2701
3105
  };
2702
3106
  const contentfulClient = createToolClient(config, args);
2703
- const entryIds = Array.isArray(args.entryId) ? args.entryId : [args.entryId];
3107
+ const entryIds = args.entryId;
2704
3108
  if (entryIds.length === 1) {
2705
3109
  const entryId = entryIds[0];
2706
3110
  const params = {
@@ -2740,20 +3144,24 @@ function unpublishEntryTool(config) {
2740
3144
  }
2741
3145
 
2742
3146
  // src/tools/entries/archiveEntry.ts
2743
- import { z as z44 } from "zod";
3147
+ import { z as z47 } from "zod";
2744
3148
  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)"
3149
+ entryId: z47.array(z47.string()).min(1).max(100).describe(
3150
+ "Array of entry IDs to archive. Pass a single-element array for one entry, or up to 100 IDs for batch operations."
2747
3151
  )
2748
3152
  });
2749
3153
  function archiveEntryTool(config) {
2750
3154
  async function tool2(args) {
3155
+ assertEnvironmentNotProtected(
3156
+ args.environmentId,
3157
+ config.protectedEnvironments
3158
+ );
2751
3159
  const baseParams = {
2752
3160
  spaceId: args.spaceId,
2753
3161
  environmentId: args.environmentId
2754
3162
  };
2755
3163
  const contentfulClient = createToolClient(config, args);
2756
- const entryIds = Array.isArray(args.entryId) ? args.entryId : [args.entryId];
3164
+ const entryIds = args.entryId;
2757
3165
  const successfullyArchived = [];
2758
3166
  for (const entryId of entryIds) {
2759
3167
  try {
@@ -2786,20 +3194,24 @@ function archiveEntryTool(config) {
2786
3194
  }
2787
3195
 
2788
3196
  // src/tools/entries/unarchiveEntry.ts
2789
- import { z as z45 } from "zod";
3197
+ import { z as z48 } from "zod";
2790
3198
  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)"
3199
+ entryId: z48.array(z48.string()).min(1).max(100).describe(
3200
+ "Array of entry IDs to unarchive. Pass a single-element array for one entry, or up to 100 IDs for batch operations."
2793
3201
  )
2794
3202
  });
2795
3203
  function unarchiveEntryTool(config) {
2796
3204
  async function tool2(args) {
3205
+ assertEnvironmentNotProtected(
3206
+ args.environmentId,
3207
+ config.protectedEnvironments
3208
+ );
2797
3209
  const baseParams = {
2798
3210
  spaceId: args.spaceId,
2799
3211
  environmentId: args.environmentId
2800
3212
  };
2801
3213
  const contentfulClient = createToolClient(config, args);
2802
- const entryIds = Array.isArray(args.entryId) ? args.entryId : [args.entryId];
3214
+ const entryIds = args.entryId;
2803
3215
  const successfullyUnarchived = [];
2804
3216
  for (const entryId of entryIds) {
2805
3217
  try {
@@ -2889,12 +3301,12 @@ function createEntryTools(config) {
2889
3301
  },
2890
3302
  deleteEntry: {
2891
3303
  title: "delete_entry",
2892
- description: "Delete a specific content entry from your Contentful space",
3304
+ 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
3305
  inputParams: DeleteEntryToolParams.shape,
2894
3306
  annotations: {
2895
3307
  readOnlyHint: false,
2896
3308
  destructiveHint: true,
2897
- idempotentHint: true,
3309
+ idempotentHint: false,
2898
3310
  openWorldHint: false
2899
3311
  },
2900
3312
  tool: deleteEntry
@@ -2951,16 +3363,20 @@ function createEntryTools(config) {
2951
3363
  }
2952
3364
 
2953
3365
  // src/tools/environments/createEnvironment.ts
2954
- import { z as z46 } from "zod";
3366
+ import { z as z49 } from "zod";
2955
3367
  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(
3368
+ environmentId: z49.string().describe("The ID of the environment to create"),
3369
+ name: z49.string().describe("The name of the environment to create"),
3370
+ sourceEnvironmentId: z49.string().describe(
2959
3371
  "The ID of the source environment to clone from (defaults to master)"
2960
3372
  ).optional()
2961
3373
  });
2962
3374
  function createEnvironmentTool(config) {
2963
3375
  async function tool2(args) {
3376
+ assertEnvironmentNotProtected(
3377
+ args.environmentId,
3378
+ config.protectedEnvironments
3379
+ );
2964
3380
  const contentfulClient = createToolClient(config, args);
2965
3381
  const environment = await contentfulClient.environment.createWithId(
2966
3382
  {
@@ -2982,15 +3398,15 @@ function createEnvironmentTool(config) {
2982
3398
  }
2983
3399
 
2984
3400
  // src/tools/environments/listEnvironments.ts
2985
- import { z as z47 } from "zod";
3401
+ import { z as z50 } from "zod";
2986
3402
  var ListEnvironmentsToolParams = BaseToolSchema.extend({
2987
- environmentId: z47.string().optional().describe(
3403
+ environmentId: z50.string().optional().describe(
2988
3404
  "The ID of the Contentful environment (not required for listing)"
2989
3405
  ),
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")
3406
+ limit: z50.number().optional().describe("Maximum number of environments to return (max 10)"),
3407
+ skip: z50.number().optional().describe("Skip this many environments for pagination"),
3408
+ select: z50.string().optional().describe("Comma-separated list of fields to return"),
3409
+ order: z50.string().optional().describe("Order environments by this field")
2994
3410
  });
2995
3411
  function listEnvironmentsTool(config) {
2996
3412
  async function tool2(args) {
@@ -3036,17 +3452,44 @@ function listEnvironmentsTool(config) {
3036
3452
  }
3037
3453
 
3038
3454
  // src/tools/environments/deleteEnvironment.ts
3039
- import { z as z48 } from "zod";
3455
+ import { z as z51 } from "zod";
3040
3456
  var DeleteEnvironmentToolParams = BaseToolSchema.extend({
3041
- environmentId: z48.string().describe("The ID of the environment to delete")
3457
+ environmentId: z51.string().describe("The ID of the environment to delete"),
3458
+ confirm: z51.boolean().optional().describe(
3459
+ "Set to true on the second call to actually perform the deletion. Required together with confirmToken."
3460
+ ),
3461
+ confirmToken: z51.string().optional().describe(
3462
+ "Token returned by the preview call; must be supplied with confirm: true."
3463
+ )
3042
3464
  });
3043
3465
  function deleteEnvironmentTool(config) {
3044
3466
  async function tool2(args) {
3467
+ assertEnvironmentNotProtected(
3468
+ args.environmentId,
3469
+ config.protectedEnvironments
3470
+ );
3045
3471
  const params = {
3046
3472
  spaceId: args.spaceId,
3047
3473
  environmentId: args.environmentId
3048
3474
  };
3049
3475
  const contentfulClient = createToolClient(config, args);
3476
+ const environment = await contentfulClient.environment.get(params);
3477
+ const expectedToken = buildConfirmToken(
3478
+ "environment",
3479
+ args.environmentId,
3480
+ environment.sys.version
3481
+ );
3482
+ if (args.confirm !== true || args.confirmToken !== expectedToken) {
3483
+ return createSuccessResponse(
3484
+ `${CONFIRMATION_MESSAGE_PREFIX} environment`,
3485
+ buildConfirmationPreview(
3486
+ "environment",
3487
+ args.environmentId,
3488
+ { environment },
3489
+ expectedToken
3490
+ )
3491
+ );
3492
+ }
3050
3493
  await contentfulClient.environment.delete(params);
3051
3494
  return createSuccessResponse("Environment deleted successfully", {
3052
3495
  environmentId: args.environmentId
@@ -3085,12 +3528,12 @@ function createEnvironmentTools(config) {
3085
3528
  },
3086
3529
  deleteEnvironment: {
3087
3530
  title: "delete_environment",
3088
- description: "Delete an environment",
3531
+ 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
3532
  inputParams: DeleteEnvironmentToolParams.shape,
3090
3533
  annotations: {
3091
3534
  readOnlyHint: false,
3092
3535
  destructiveHint: true,
3093
- idempotentHint: true,
3536
+ idempotentHint: false,
3094
3537
  openWorldHint: false
3095
3538
  },
3096
3539
  tool: deleteEnvironment
@@ -3099,9 +3542,9 @@ function createEnvironmentTools(config) {
3099
3542
  }
3100
3543
 
3101
3544
  // src/tools/locales/getLocale.ts
3102
- import { z as z49 } from "zod";
3545
+ import { z as z52 } from "zod";
3103
3546
  var GetLocaleToolParams = BaseToolSchema.extend({
3104
- localeId: z49.string().describe("The ID of the locale to retrieve")
3547
+ localeId: z52.string().describe("The ID of the locale to retrieve")
3105
3548
  });
3106
3549
  function getLocaleTool(config) {
3107
3550
  async function tool2(args) {
@@ -3118,24 +3561,28 @@ function getLocaleTool(config) {
3118
3561
  }
3119
3562
 
3120
3563
  // src/tools/locales/createLocale.ts
3121
- import { z as z50 } from "zod";
3564
+ import { z as z53 } from "zod";
3122
3565
  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(
3566
+ name: z53.string().describe("The name of the locale"),
3567
+ code: z53.string().describe('The locale code (e.g., "en-US")'),
3568
+ fallbackCode: z53.string().nullable().describe(
3126
3569
  "The locale code to fallback to when there is no content for the current locale"
3127
3570
  ),
3128
- contentDeliveryApi: z50.boolean().optional().default(true).describe(
3571
+ contentDeliveryApi: z53.boolean().optional().default(true).describe(
3129
3572
  "If the content under this locale should be available on the CDA (for public reading)"
3130
3573
  ),
3131
- contentManagementApi: z50.boolean().optional().default(true).describe(
3574
+ contentManagementApi: z53.boolean().optional().default(true).describe(
3132
3575
  "If the content under this locale should be available on the CMA (for editing)"
3133
3576
  ),
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")
3577
+ default: z53.boolean().optional().default(false).describe("If this is the default locale"),
3578
+ optional: z53.boolean().optional().default(false).describe("If the locale needs to be filled in on entries or not")
3136
3579
  });
3137
3580
  function createLocaleTool(config) {
3138
3581
  async function tool2(args) {
3582
+ assertEnvironmentNotProtected(
3583
+ args.environmentId,
3584
+ config.protectedEnvironments
3585
+ );
3139
3586
  const params = {
3140
3587
  spaceId: args.spaceId,
3141
3588
  environmentId: args.environmentId
@@ -3155,13 +3602,13 @@ function createLocaleTool(config) {
3155
3602
  }
3156
3603
 
3157
3604
  // src/tools/locales/listLocales.ts
3158
- import { z as z51 } from "zod";
3605
+ import { z as z54 } from "zod";
3159
3606
  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")
3607
+ limit: z54.number().optional().describe("Maximum number of locales to return"),
3608
+ skip: z54.number().optional().describe("Skip this many locales for pagination"),
3609
+ select: z54.string().optional().describe("Comma-separated list of fields to return"),
3610
+ include: z54.number().optional().describe("Include this many levels of linked entries"),
3611
+ order: z54.string().optional().describe("Order locales by this field")
3165
3612
  });
3166
3613
  function listLocaleTool(config) {
3167
3614
  async function tool2(args) {
@@ -3214,27 +3661,31 @@ function listLocaleTool(config) {
3214
3661
  }
3215
3662
 
3216
3663
  // src/tools/locales/updateLocale.ts
3217
- import { z as z52 } from "zod";
3664
+ import { z as z55 } from "zod";
3218
3665
  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"),
3666
+ localeId: z55.string().describe("The ID of the locale to update"),
3667
+ fields: z55.object({
3668
+ name: z55.string().optional().describe("The name of the locale"),
3222
3669
  // NOTE: internal_code changes are not allowed
3223
- code: z52.string().optional().describe("The code of the locale"),
3224
- fallbackCode: z52.string().optional().describe(
3670
+ code: z55.string().optional().describe("The code of the locale"),
3671
+ fallbackCode: z55.string().optional().describe(
3225
3672
  "The locale code to fallback to when there is no content for the current locale"
3226
3673
  ),
3227
- contentDeliveryApi: z52.boolean().optional().describe(
3674
+ contentDeliveryApi: z55.boolean().optional().describe(
3228
3675
  "If the content under this locale should be available on the CDA (for public reading)"
3229
3676
  ),
3230
- contentManagementApi: z52.boolean().optional().describe(
3677
+ contentManagementApi: z55.boolean().optional().describe(
3231
3678
  "If the content under this locale should be available on the CMA (for editing)"
3232
3679
  ),
3233
- optional: z52.boolean().optional().describe("If the locale needs to be filled in on entries or not")
3680
+ optional: z55.boolean().optional().describe("If the locale needs to be filled in on entries or not")
3234
3681
  })
3235
3682
  });
3236
3683
  function updateLocaleTool(config) {
3237
3684
  async function tool2(args) {
3685
+ assertEnvironmentNotProtected(
3686
+ args.environmentId,
3687
+ config.protectedEnvironments
3688
+ );
3238
3689
  const params = {
3239
3690
  spaceId: args.spaceId,
3240
3691
  environmentId: args.environmentId,
@@ -3256,12 +3707,22 @@ function updateLocaleTool(config) {
3256
3707
  }
3257
3708
 
3258
3709
  // src/tools/locales/deleteLocale.ts
3259
- import { z as z53 } from "zod";
3710
+ import { z as z56 } from "zod";
3260
3711
  var DeleteLocaleToolParams = BaseToolSchema.extend({
3261
- localeId: z53.string().describe("The ID of the locale to delete")
3712
+ localeId: z56.string().describe("The ID of the locale to delete"),
3713
+ confirm: z56.boolean().optional().describe(
3714
+ "Set to true on the second call to actually perform the deletion. Required together with confirmToken."
3715
+ ),
3716
+ confirmToken: z56.string().optional().describe(
3717
+ "Token returned by the preview call; must be supplied with confirm: true."
3718
+ )
3262
3719
  });
3263
3720
  function deleteLocaleTool(config) {
3264
3721
  async function tool2(args) {
3722
+ assertEnvironmentNotProtected(
3723
+ args.environmentId,
3724
+ config.protectedEnvironments
3725
+ );
3265
3726
  const params = {
3266
3727
  spaceId: args.spaceId,
3267
3728
  environmentId: args.environmentId,
@@ -3269,6 +3730,22 @@ function deleteLocaleTool(config) {
3269
3730
  };
3270
3731
  const contentfulClient = createToolClient(config, args);
3271
3732
  const locale = await contentfulClient.locale.get(params);
3733
+ const expectedToken = buildConfirmToken(
3734
+ "locale",
3735
+ args.localeId,
3736
+ locale.sys.version
3737
+ );
3738
+ if (args.confirm !== true || args.confirmToken !== expectedToken) {
3739
+ return createSuccessResponse(
3740
+ `${CONFIRMATION_MESSAGE_PREFIX} locale`,
3741
+ buildConfirmationPreview(
3742
+ "locale",
3743
+ args.localeId,
3744
+ { locale },
3745
+ expectedToken
3746
+ )
3747
+ );
3748
+ }
3272
3749
  await contentfulClient.locale.delete(params);
3273
3750
  return createSuccessResponse("Locale deleted successfully", { locale });
3274
3751
  }
@@ -3329,12 +3806,12 @@ function createLocaleTools(config) {
3329
3806
  },
3330
3807
  deleteLocale: {
3331
3808
  title: "delete_locale",
3332
- description: "Delete a specific locale from your Contentful environment. This operation permanently removes the locale and cannot be undone.",
3809
+ 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
3810
  inputParams: DeleteLocaleToolParams.shape,
3334
3811
  annotations: {
3335
3812
  readOnlyHint: false,
3336
3813
  destructiveHint: true,
3337
- idempotentHint: true,
3814
+ idempotentHint: false,
3338
3815
  openWorldHint: false
3339
3816
  },
3340
3817
  tool: deleteLocale
@@ -3343,13 +3820,13 @@ function createLocaleTools(config) {
3343
3820
  }
3344
3821
 
3345
3822
  // src/tools/orgs/listOrgs.ts
3346
- import { z as z54 } from "zod";
3823
+ import { z as z57 } from "zod";
3347
3824
  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")
3825
+ var ListOrgsToolParams = z57.object({
3826
+ limit: z57.number().optional().describe("Maximum number of organizations to return (max 10)"),
3827
+ skip: z57.number().optional().describe("Skip this many organizations for pagination"),
3828
+ select: z57.string().optional().describe("Comma-separated list of fields to return"),
3829
+ order: z57.string().optional().describe("Order organizations by this field")
3353
3830
  });
3354
3831
  function listOrgsTool(config) {
3355
3832
  async function tool2(args) {
@@ -3391,10 +3868,10 @@ function listOrgsTool(config) {
3391
3868
  }
3392
3869
 
3393
3870
  // src/tools/orgs/getOrg.ts
3394
- import { z as z55 } from "zod";
3871
+ import { z as z58 } from "zod";
3395
3872
  import { createClient as createClient3 } from "contentful-management";
3396
- var GetOrgToolParams = z55.object({
3397
- organizationId: z55.string().describe("The ID of the organization to retrieve")
3873
+ var GetOrgToolParams = z58.object({
3874
+ organizationId: z58.string().describe("The ID of the organization to retrieve")
3398
3875
  });
3399
3876
  function getOrgTool(config) {
3400
3877
  async function tool2(args) {
@@ -3440,13 +3917,13 @@ function createOrgTools(config) {
3440
3917
  }
3441
3918
 
3442
3919
  // src/tools/spaces/listSpaces.ts
3443
- import { z as z56 } from "zod";
3920
+ import { z as z59 } from "zod";
3444
3921
  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")
3922
+ var ListSpacesToolParams = z59.object({
3923
+ limit: z59.number().optional().describe("Maximum number of spaces to return (max 10)"),
3924
+ skip: z59.number().optional().describe("Skip this many spaces for pagination"),
3925
+ select: z59.string().optional().describe("Comma-separated list of fields to return"),
3926
+ order: z59.string().optional().describe("Order spaces by this field")
3450
3927
  });
3451
3928
  function listSpacesTool(config) {
3452
3929
  async function tool2(args) {
@@ -3488,10 +3965,10 @@ function listSpacesTool(config) {
3488
3965
  }
3489
3966
 
3490
3967
  // src/tools/spaces/getSpace.ts
3491
- import { z as z57 } from "zod";
3968
+ import { z as z60 } from "zod";
3492
3969
  import { createClient as createClient5 } from "contentful-management";
3493
- var GetSpaceToolParams = z57.object({
3494
- spaceId: z57.string().describe("The ID of the space to retrieve")
3970
+ var GetSpaceToolParams = z60.object({
3971
+ spaceId: z60.string().describe("The ID of the space to retrieve")
3495
3972
  });
3496
3973
  function getSpaceTool(config) {
3497
3974
  async function tool2(args) {
@@ -3535,12 +4012,12 @@ function createSpaceTools(config) {
3535
4012
  }
3536
4013
 
3537
4014
  // src/tools/tags/listTags.ts
3538
- import { z as z58 } from "zod";
4015
+ import { z as z61 } from "zod";
3539
4016
  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")
4017
+ limit: z61.number().optional().describe("Maximum number of tags to return"),
4018
+ skip: z61.number().optional().describe("Skip this many tags for pagination"),
4019
+ select: z61.string().optional().describe("Comma-separated list of fields to return"),
4020
+ order: z61.string().optional().describe("Order tags by this field")
3544
4021
  });
3545
4022
  function listTagsTool(config) {
3546
4023
  async function tool2(args) {
@@ -3586,14 +4063,18 @@ function listTagsTool(config) {
3586
4063
  }
3587
4064
 
3588
4065
  // src/tools/tags/createTag.ts
3589
- import { z as z59 } from "zod";
4066
+ import { z as z62 } from "zod";
3590
4067
  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")
4068
+ name: z62.string().describe("The name of the tag"),
4069
+ id: z62.string().describe("The ID of the tag"),
4070
+ visibility: z62.enum(["public", "private"]).describe("The visibility of the tag. Default to private if not specified")
3594
4071
  });
3595
4072
  function createTagTool(config) {
3596
4073
  async function tool2(args) {
4074
+ assertEnvironmentNotProtected(
4075
+ args.environmentId,
4076
+ config.protectedEnvironments
4077
+ );
3597
4078
  const params = {
3598
4079
  spaceId: args.spaceId,
3599
4080
  environmentId: args.environmentId,
@@ -3640,34 +4121,34 @@ function createTagTools(config) {
3640
4121
  }
3641
4122
 
3642
4123
  // src/tools/taxonomies/concept-schemes/createConceptScheme.ts
3643
- import { z as z61 } from "zod";
4124
+ import { z as z64 } from "zod";
3644
4125
  import { createClient as createClient6 } from "contentful-management";
3645
4126
 
3646
4127
  // 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()
4128
+ import { z as z63 } from "zod";
4129
+ var TaxonomyConceptLinkSchema = z63.object({
4130
+ sys: z63.object({
4131
+ type: z63.literal("Link"),
4132
+ linkType: z63.literal("TaxonomyConcept"),
4133
+ id: z63.string()
3653
4134
  })
3654
4135
  });
3655
4136
 
3656
4137
  // 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(
4138
+ var CreateConceptSchemeToolParams = z64.object({
4139
+ organizationId: z64.string().describe("The ID of the Contentful organization"),
4140
+ conceptSchemeId: z64.string().optional().describe(
3660
4141
  "Optional user-defined ID for the concept scheme. If not provided, Contentful will generate one automatically."
3661
4142
  ),
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")
4143
+ prefLabel: z64.record(z64.string()).describe("The preferred label for the concept scheme (localized)"),
4144
+ uri: z64.string().nullable().optional().describe("The URI for the concept scheme"),
4145
+ definition: z64.record(z64.string().nullable()).optional().describe("Definition of the concept scheme (localized)"),
4146
+ editorialNote: z64.record(z64.string().nullable()).optional().describe("Editorial note for the concept scheme (localized)"),
4147
+ historyNote: z64.record(z64.string().nullable()).optional().describe("History note for the concept scheme (localized)"),
4148
+ example: z64.record(z64.string().nullable()).optional().describe("Example for the concept scheme (localized)"),
4149
+ note: z64.record(z64.string().nullable()).optional().describe("General note for the concept scheme (localized)"),
4150
+ scopeNote: z64.record(z64.string().nullable()).optional().describe("Scope note for the concept scheme (localized)"),
4151
+ topConcepts: z64.array(TaxonomyConceptLinkSchema).optional().describe("Links to top-level concepts in this scheme")
3671
4152
  });
3672
4153
  function createConceptSchemeTool(config) {
3673
4154
  async function tool2(args) {
@@ -3707,11 +4188,11 @@ function createConceptSchemeTool(config) {
3707
4188
  }
3708
4189
 
3709
4190
  // src/tools/taxonomies/concept-schemes/getConceptScheme.ts
3710
- import { z as z62 } from "zod";
4191
+ import { z as z65 } from "zod";
3711
4192
  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")
4193
+ var GetConceptSchemeToolParams = z65.object({
4194
+ organizationId: z65.string().describe("The ID of the Contentful organization"),
4195
+ conceptSchemeId: z65.string().describe("The ID of the concept scheme to retrieve")
3715
4196
  });
3716
4197
  function getConceptSchemeTool(config) {
3717
4198
  async function tool2(args) {
@@ -3731,25 +4212,25 @@ function getConceptSchemeTool(config) {
3731
4212
  }
3732
4213
 
3733
4214
  // src/tools/taxonomies/concept-schemes/listConceptSchemes.ts
3734
- import { z as z63 } from "zod";
4215
+ import { z as z66 } from "zod";
3735
4216
  import { createClient as createClient8 } from "contentful-management";
3736
4217
  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(
4218
+ var ListConceptSchemesToolParams = z66.object({
4219
+ organizationId: z66.string(),
4220
+ query: z66.union([
4221
+ z66.object({
4222
+ query: z66.string().optional(),
4223
+ pageNext: z66.string().optional().describe("Cursor token for the next page of concept schemes"),
4224
+ pagePrev: z66.string().optional().describe(
3744
4225
  "Cursor token for the previous page of concept schemes"
3745
4226
  ),
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()
4227
+ limit: z66.number().optional().describe("Maximum number of concept schemes to return"),
4228
+ order: z66.string().optional().describe("Order concept schemes by this field"),
4229
+ skip: z66.never().optional()
3749
4230
  }).passthrough(),
3750
4231
  // handles [key: string]: any from BasicQueryOptions
3751
- z63.object({
3752
- pageUrl: z63.string().optional()
4232
+ z66.object({
4233
+ pageUrl: z66.string().optional()
3753
4234
  })
3754
4235
  ]).optional().describe(
3755
4236
  'Query parameters for listing concept schemes, supports either pageUrl for cursor-based pagination. Offset "skip" pagination is not supported.'
@@ -3819,22 +4300,22 @@ function listConceptSchemesTool(config) {
3819
4300
  }
3820
4301
 
3821
4302
  // src/tools/taxonomies/concept-schemes/updateConceptScheme.ts
3822
- import { z as z64 } from "zod";
4303
+ import { z as z67 } from "zod";
3823
4304
  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(
4305
+ var UpdateConceptSchemeToolParams = z67.object({
4306
+ organizationId: z67.string().describe("The ID of the Contentful organization"),
4307
+ conceptSchemeId: z67.string().describe("The ID of the concept scheme to update"),
4308
+ version: z67.number().describe("The current version of the concept scheme"),
4309
+ prefLabel: z67.record(z67.string()).optional().describe("The preferred label for the concept scheme (localized)"),
4310
+ uri: z67.string().nullable().optional().describe("The URI for the concept scheme"),
4311
+ definition: z67.record(z67.string().nullable()).optional().describe("Definition of the concept scheme (localized)"),
4312
+ editorialNote: z67.record(z67.string().nullable()).optional().describe("Editorial note for the concept scheme (localized)"),
4313
+ historyNote: z67.record(z67.string().nullable()).optional().describe("History note for the concept scheme (localized)"),
4314
+ example: z67.record(z67.string().nullable()).optional().describe("Example for the concept scheme (localized)"),
4315
+ note: z67.record(z67.string().nullable()).optional().describe("General note for the concept scheme (localized)"),
4316
+ scopeNote: z67.record(z67.string().nullable()).optional().describe("Scope note for the concept scheme (localized)"),
4317
+ topConcepts: z67.array(TaxonomyConceptLinkSchema).optional().describe("Links to top-level concepts in this scheme"),
4318
+ addConcept: z67.string().optional().describe(
3838
4319
  "ID of a concept to add to this scheme (adds to both concepts and topConcepts)"
3839
4320
  )
3840
4321
  });
@@ -3909,22 +4390,47 @@ function updateConceptSchemeTool(config) {
3909
4390
  }
3910
4391
 
3911
4392
  // src/tools/taxonomies/concept-schemes/deleteConceptScheme.ts
3912
- import { z as z65 } from "zod";
4393
+ import { z as z68 } from "zod";
3913
4394
  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")
4395
+ var DeleteConceptSchemeToolParams = z68.object({
4396
+ organizationId: z68.string().describe("The ID of the Contentful organization"),
4397
+ conceptSchemeId: z68.string().describe("The ID of the concept scheme to delete"),
4398
+ confirm: z68.boolean().optional().describe(
4399
+ "Set to true on the second call to actually perform the deletion. Required together with confirmToken."
4400
+ ),
4401
+ confirmToken: z68.string().optional().describe(
4402
+ "Token returned by the preview call; must be supplied with confirm: true."
4403
+ )
3918
4404
  });
3919
4405
  function deleteConceptSchemeTool(config) {
3920
4406
  async function tool2(args) {
3921
4407
  const clientConfig = createClientConfig(config);
3922
4408
  delete clientConfig.space;
3923
4409
  const contentfulClient = createClient10(clientConfig);
4410
+ const conceptScheme = await contentfulClient.conceptScheme.get({
4411
+ organizationId: args.organizationId,
4412
+ conceptSchemeId: args.conceptSchemeId
4413
+ });
4414
+ const expectedToken = buildConfirmToken(
4415
+ "conceptScheme",
4416
+ args.conceptSchemeId,
4417
+ conceptScheme.sys.version
4418
+ );
4419
+ if (args.confirm !== true || args.confirmToken !== expectedToken) {
4420
+ return createSuccessResponse(
4421
+ `${CONFIRMATION_MESSAGE_PREFIX} concept scheme`,
4422
+ buildConfirmationPreview(
4423
+ "conceptScheme",
4424
+ args.conceptSchemeId,
4425
+ { conceptScheme },
4426
+ expectedToken
4427
+ )
4428
+ );
4429
+ }
3924
4430
  await contentfulClient.conceptScheme.delete({
3925
4431
  organizationId: args.organizationId,
3926
4432
  conceptSchemeId: args.conceptSchemeId,
3927
- version: args.version
4433
+ version: conceptScheme.sys.version
3928
4434
  });
3929
4435
  return createSuccessResponse("Concept scheme deleted successfully", {
3930
4436
  conceptSchemeId: args.conceptSchemeId
@@ -3987,12 +4493,12 @@ function createConceptSchemeTools(config) {
3987
4493
  },
3988
4494
  deleteConceptScheme: {
3989
4495
  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.",
4496
+ 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
4497
  inputParams: DeleteConceptSchemeToolParams.shape,
3992
4498
  annotations: {
3993
4499
  readOnlyHint: false,
3994
4500
  destructiveHint: true,
3995
- idempotentHint: true,
4501
+ idempotentHint: false,
3996
4502
  openWorldHint: false
3997
4503
  },
3998
4504
  tool: deleteConceptScheme
@@ -4001,26 +4507,26 @@ function createConceptSchemeTools(config) {
4001
4507
  }
4002
4508
 
4003
4509
  // src/tools/taxonomies/concepts/createConcept.ts
4004
- import { z as z66 } from "zod";
4510
+ import { z as z69 } from "zod";
4005
4511
  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(
4512
+ var CreateConceptToolParams = z69.object({
4513
+ organizationId: z69.string().describe("The ID of the Contentful organization"),
4514
+ conceptId: z69.string().optional().describe(
4009
4515
  "Optional user-defined ID for the concept. If not provided, Contentful will generate one automatically."
4010
4516
  ),
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")
4517
+ prefLabel: z69.record(z69.string()).describe("The preferred label for the concept (localized)"),
4518
+ uri: z69.string().nullable().optional().describe("The URI for the concept"),
4519
+ altLabels: z69.record(z69.array(z69.string())).optional().describe("Alternative labels for the concept (localized)"),
4520
+ hiddenLabels: z69.record(z69.array(z69.string())).optional().describe("Hidden labels for the concept (localized)"),
4521
+ definition: z69.record(z69.string().nullable()).optional().describe("Definition of the concept (localized)"),
4522
+ editorialNote: z69.record(z69.string().nullable()).optional().describe("Editorial note for the concept (localized)"),
4523
+ historyNote: z69.record(z69.string().nullable()).optional().describe("History note for the concept (localized)"),
4524
+ example: z69.record(z69.string().nullable()).optional().describe("Example for the concept (localized)"),
4525
+ note: z69.record(z69.string().nullable()).optional().describe("General note for the concept (localized)"),
4526
+ scopeNote: z69.record(z69.string().nullable()).optional().describe("Scope note for the concept (localized)"),
4527
+ notations: z69.array(z69.string()).optional().describe("Notations for the concept"),
4528
+ broader: z69.array(TaxonomyConceptLinkSchema).optional().describe("Links to broader concepts"),
4529
+ related: z69.array(TaxonomyConceptLinkSchema).optional().describe("Links to related concepts")
4024
4530
  });
4025
4531
  function createConceptTool(config) {
4026
4532
  async function tool2(args) {
@@ -4055,22 +4561,42 @@ function createConceptTool(config) {
4055
4561
  }
4056
4562
 
4057
4563
  // src/tools/taxonomies/concepts/deleteConcept.ts
4058
- import { z as z67 } from "zod";
4564
+ import { z as z70 } from "zod";
4059
4565
  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")
4566
+ var DeleteConceptToolParams = z70.object({
4567
+ organizationId: z70.string().describe("The ID of the Contentful organization"),
4568
+ conceptId: z70.string().describe("The ID of the concept to delete"),
4569
+ confirm: z70.boolean().optional().describe(
4570
+ "Set to true on the second call to actually perform the deletion. Required together with confirmToken."
4571
+ ),
4572
+ confirmToken: z70.string().optional().describe(
4573
+ "Token returned by the preview call; must be supplied with confirm: true."
4574
+ )
4064
4575
  });
4065
4576
  function deleteConceptTool(config) {
4066
4577
  async function tool2(args) {
4067
4578
  const clientConfig = createClientConfig(config);
4068
4579
  delete clientConfig.space;
4069
4580
  const contentfulClient = createClient12(clientConfig);
4581
+ const concept = await contentfulClient.concept.get({
4582
+ organizationId: args.organizationId,
4583
+ conceptId: args.conceptId
4584
+ });
4585
+ const expectedToken = buildConfirmToken(
4586
+ "concept",
4587
+ args.conceptId,
4588
+ concept.sys.version
4589
+ );
4590
+ if (args.confirm !== true || args.confirmToken !== expectedToken) {
4591
+ return createSuccessResponse(
4592
+ `${CONFIRMATION_MESSAGE_PREFIX} concept`,
4593
+ buildConfirmationPreview("concept", args.conceptId, { concept }, expectedToken)
4594
+ );
4595
+ }
4070
4596
  await contentfulClient.concept.delete({
4071
4597
  organizationId: args.organizationId,
4072
4598
  conceptId: args.conceptId,
4073
- version: args.version
4599
+ version: concept.sys.version
4074
4600
  });
4075
4601
  return createSuccessResponse("Concept deleted successfully", {
4076
4602
  conceptId: args.conceptId
@@ -4080,25 +4606,25 @@ function deleteConceptTool(config) {
4080
4606
  }
4081
4607
 
4082
4608
  // src/tools/taxonomies/concepts/updateConcept.ts
4083
- import { z as z68 } from "zod";
4609
+ import { z as z71 } from "zod";
4084
4610
  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")
4611
+ var UpdateConceptToolParams = z71.object({
4612
+ organizationId: z71.string().describe("The ID of the Contentful organization"),
4613
+ conceptId: z71.string().describe("The ID of the concept to update"),
4614
+ version: z71.number().describe("The current version of the concept"),
4615
+ prefLabel: z71.record(z71.string()).optional().describe("The preferred label for the concept (localized)"),
4616
+ uri: z71.string().nullable().optional().describe("The URI for the concept"),
4617
+ altLabels: z71.record(z71.array(z71.string())).optional().describe("Alternative labels for the concept (localized)"),
4618
+ hiddenLabels: z71.record(z71.array(z71.string())).optional().describe("Hidden labels for the concept (localized)"),
4619
+ definition: z71.record(z71.string().nullable()).optional().describe("Definition of the concept (localized)"),
4620
+ editorialNote: z71.record(z71.string().nullable()).optional().describe("Editorial note for the concept (localized)"),
4621
+ historyNote: z71.record(z71.string().nullable()).optional().describe("History note for the concept (localized)"),
4622
+ example: z71.record(z71.string().nullable()).optional().describe("Example for the concept (localized)"),
4623
+ note: z71.record(z71.string().nullable()).optional().describe("General note for the concept (localized)"),
4624
+ scopeNote: z71.record(z71.string().nullable()).optional().describe("Scope note for the concept (localized)"),
4625
+ notations: z71.array(z71.string()).optional().describe("Notations for the concept"),
4626
+ broader: z71.array(TaxonomyConceptLinkSchema).optional().describe("Links to broader concepts"),
4627
+ related: z71.array(TaxonomyConceptLinkSchema).optional().describe("Links to related concepts")
4102
4628
  });
4103
4629
  function updateConceptTool(config) {
4104
4630
  async function tool2(args) {
@@ -4140,11 +4666,11 @@ function updateConceptTool(config) {
4140
4666
  }
4141
4667
 
4142
4668
  // src/tools/taxonomies/concepts/getConcept.ts
4143
- import { z as z69 } from "zod";
4669
+ import { z as z72 } from "zod";
4144
4670
  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")
4671
+ var GetConceptToolParams = z72.object({
4672
+ organizationId: z72.string().describe("The ID of the Contentful organization"),
4673
+ conceptId: z72.string().describe("The ID of the concept to retrieve")
4148
4674
  });
4149
4675
  function getConceptTool(config) {
4150
4676
  async function tool2(args) {
@@ -4161,18 +4687,18 @@ function getConceptTool(config) {
4161
4687
  }
4162
4688
 
4163
4689
  // src/tools/taxonomies/concepts/listConcepts.ts
4164
- import { z as z70 } from "zod";
4690
+ import { z as z73 } from "zod";
4165
4691
  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")
4692
+ var ListConceptsToolParams = z73.object({
4693
+ organizationId: z73.string().describe("The ID of the Contentful organization"),
4694
+ conceptId: z73.string().optional().describe("The ID of the concept (required for descendants/ancestors)"),
4695
+ limit: z73.number().optional().describe("Maximum number of concepts to return"),
4696
+ select: z73.string().optional().describe("Comma-separated list of fields to return"),
4697
+ include: z73.number().optional().describe("Include this many levels of linked entries"),
4698
+ order: z73.string().optional().describe("Order concepts by this field"),
4699
+ getDescendants: z73.boolean().optional().describe("Get descendants of the specified concept (requires conceptId)"),
4700
+ getAncestors: z73.boolean().optional().describe("Get ancestors of the specified concept (requires conceptId)"),
4701
+ getTotalOnly: z73.boolean().optional().describe("Get only the total number of concepts without full data")
4176
4702
  });
4177
4703
  function listConceptsTool(config) {
4178
4704
  async function tool2(args) {
@@ -4324,12 +4850,12 @@ function createConceptTools(config) {
4324
4850
  },
4325
4851
  deleteConcept: {
4326
4852
  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.",
4853
+ 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
4854
  inputParams: DeleteConceptToolParams.shape,
4329
4855
  annotations: {
4330
4856
  readOnlyHint: false,
4331
4857
  destructiveHint: true,
4332
- idempotentHint: true,
4858
+ idempotentHint: false,
4333
4859
  openWorldHint: false
4334
4860
  },
4335
4861
  tool: deleteConcept
@@ -4348,61 +4874,54 @@ function createTaxonomyTools(config) {
4348
4874
  }
4349
4875
 
4350
4876
  // src/tools/jobs/space-to-space-migration/exportSpace.ts
4351
- import { z as z72 } from "zod";
4877
+ import { z as z75 } from "zod";
4352
4878
 
4353
4879
  // 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")
4880
+ import { z as z74 } from "zod";
4881
+ var EntryQuerySchema = z74.object({
4882
+ content_type: z74.string().optional().describe("Filter by content type"),
4883
+ include: z74.number().optional().describe("Include this many levels of linked entries"),
4884
+ select: z74.string().optional().describe("Comma-separated list of fields to return"),
4885
+ links_to_entry: z74.string().optional().describe("Find entries that link to the specified entry ID"),
4886
+ limit: z74.number().optional().describe("Maximum number of entries to return"),
4887
+ skip: z74.number().optional().describe("Skip this many entries"),
4888
+ order: z74.string().optional().describe("Order entries by this field")
4363
4889
  });
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")
4890
+ var AssetQuerySchema = z74.object({
4891
+ mimetype_group: z74.string().optional().describe("Filter by MIME type group"),
4892
+ select: z74.string().optional().describe("Comma-separated list of fields to return"),
4893
+ limit: z74.number().optional().describe("Maximum number of assets to return"),
4894
+ skip: z74.number().optional().describe("Skip this many assets"),
4895
+ order: z74.string().optional().describe("Order assets by this field")
4370
4896
  });
4371
4897
 
4372
4898
  // src/tools/jobs/space-to-space-migration/exportSpace.ts
4373
4899
  var ExportSpaceToolParams = BaseToolSchema.extend({
4374
- exportDir: z72.string().optional().describe(
4900
+ exportDir: z75.string().optional().describe(
4375
4901
  "Directory to save the exported space data (optional, defaults to current directory)"
4376
4902
  ),
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"),
4903
+ saveFile: z75.boolean().optional().default(true).describe("Save the exported space data to a file"),
4904
+ contentFile: z75.string().optional().describe("Custom filename for the exported space data (optional)"),
4905
+ includeDrafts: z75.boolean().optional().default(false).describe("Include draft entries in the export"),
4906
+ includeArchived: z75.boolean().optional().default(false).describe("Include archived entries in the export"),
4907
+ skipContentModel: z75.boolean().optional().default(false).describe("Skip exporting content types"),
4908
+ skipEditorInterfaces: z75.boolean().optional().default(false).describe("Skip exporting editor interfaces"),
4909
+ skipContent: z75.boolean().optional().default(false).describe("Skip exporting entries and assets"),
4910
+ skipRoles: z75.boolean().optional().default(false).describe("Skip exporting roles and permissions"),
4911
+ skipTags: z75.boolean().optional().default(false).describe("Skip exporting tags"),
4912
+ skipWebhooks: z75.boolean().optional().default(false).describe("Skip exporting webhooks"),
4913
+ stripTags: z75.boolean().optional().default(false).describe("Untag assets and entries"),
4914
+ contentOnly: z75.boolean().optional().default(false).describe("Only export assets and entries"),
4389
4915
  queryEntries: EntryQuerySchema.optional().describe(
4390
4916
  "Export only entries that match query parameters"
4391
4917
  ),
4392
4918
  queryAssets: AssetQuerySchema.optional().describe(
4393
4919
  "Export only assets that match query parameters"
4394
4920
  ),
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
- deliveryToken: z72.string().optional().describe("CDA token to export only published content (excludes tags)"),
4398
- host: z72.string().optional().describe("Management API host"),
4399
- hostDelivery: z72.string().optional().describe("Delivery API host"),
4400
- proxy: z72.string().optional().describe("HTTP/HTTPS proxy config"),
4401
- rawProxy: z72.boolean().optional().describe("Pass raw proxy config directly to Axios"),
4402
- headers: z72.record(z72.string()).optional().describe("Additional headers to include in requests"),
4403
- errorLogFile: z72.string().optional().describe("Path to error log output file"),
4404
- useVerboseRenderer: z72.boolean().optional().describe("Line-by-line logging, useful for CI"),
4405
- config: z72.string().optional().describe("Path to a JSON config file with all options")
4921
+ downloadAssets: z75.boolean().optional().default(false).describe("Download actual asset files"),
4922
+ maxAllowedLimit: z75.number().optional().default(1e3).describe("Maximum number of items per request"),
4923
+ errorLogFile: z75.string().optional().describe("Path to error log output file"),
4924
+ useVerboseRenderer: z75.boolean().optional().describe("Line-by-line logging, useful for CI")
4406
4925
  });
4407
4926
  function createExportSpaceTool(config) {
4408
4927
  async function tool2(args) {
@@ -4414,6 +4933,9 @@ function createExportSpaceTool(config) {
4414
4933
  const exportOptions = {
4415
4934
  ...args,
4416
4935
  managementToken,
4936
+ host: config.host ?? "api.contentful.com",
4937
+ ...config.deliveryToken && { deliveryToken: config.deliveryToken },
4938
+ ...config.hostDelivery && { hostDelivery: config.hostDelivery },
4417
4939
  environmentId: args.environmentId || "master",
4418
4940
  exportDir: args.exportDir || process.cwd(),
4419
4941
  contentFile: args.contentFile || `contentful-export-${args.spaceId}.json`
@@ -4449,70 +4971,70 @@ function createExportSpaceTool(config) {
4449
4971
  }
4450
4972
 
4451
4973
  // src/tools/jobs/space-to-space-migration/paramCollection.ts
4452
- import { z as z73 } from "zod";
4974
+ import { z as z76 } from "zod";
4453
4975
  var ParamCollectionToolParams = BaseToolSchema.extend({
4454
- confirmation: z73.boolean().optional().describe(
4976
+ confirmation: z76.boolean().optional().describe(
4455
4977
  "User confirmation that they are ready to proceed with the workflow"
4456
4978
  ),
4457
- export: z73.object({
4458
- spaceId: z73.string().optional().describe("ID of the space with source data"),
4459
- environmentId: z73.string().optional().describe("ID of the environment in the source space"),
4460
- deliveryToken: z73.string().optional().describe("CDA token to export only published content (excludes tags)"),
4461
- exportDir: z73.string().optional().describe("Path to export JSON output"),
4462
- saveFile: z73.boolean().optional().describe("Save the export as a JSON file"),
4463
- contentFile: z73.string().optional().describe("Filename for exported data"),
4464
- includeDrafts: z73.boolean().optional().describe("Include drafts in exported entries"),
4465
- includeArchived: z73.boolean().optional().describe("Include archived entries"),
4466
- skipContentModel: z73.boolean().optional().describe("Skip exporting content models"),
4467
- skipEditorInterfaces: z73.boolean().optional().describe("Skip exporting editor interfaces"),
4468
- skipContent: z73.boolean().optional().describe("Skip exporting entries and assets"),
4469
- skipRoles: z73.boolean().optional().describe("Skip exporting roles and permissions"),
4470
- skipTags: z73.boolean().optional().describe("Skip exporting tags"),
4471
- skipWebhooks: z73.boolean().optional().describe("Skip exporting webhooks"),
4472
- stripTags: z73.boolean().optional().describe("Remove tags from entries and assets"),
4473
- contentOnly: z73.boolean().optional().describe("Export only entries and assets"),
4979
+ export: z76.object({
4980
+ spaceId: z76.string().optional().describe("ID of the space with source data"),
4981
+ environmentId: z76.string().optional().describe("ID of the environment in the source space"),
4982
+ deliveryToken: z76.string().optional().describe("CDA token to export only published content (excludes tags)"),
4983
+ exportDir: z76.string().optional().describe("Path to export JSON output"),
4984
+ saveFile: z76.boolean().optional().describe("Save the export as a JSON file"),
4985
+ contentFile: z76.string().optional().describe("Filename for exported data"),
4986
+ includeDrafts: z76.boolean().optional().describe("Include drafts in exported entries"),
4987
+ includeArchived: z76.boolean().optional().describe("Include archived entries"),
4988
+ skipContentModel: z76.boolean().optional().describe("Skip exporting content models"),
4989
+ skipEditorInterfaces: z76.boolean().optional().describe("Skip exporting editor interfaces"),
4990
+ skipContent: z76.boolean().optional().describe("Skip exporting entries and assets"),
4991
+ skipRoles: z76.boolean().optional().describe("Skip exporting roles and permissions"),
4992
+ skipTags: z76.boolean().optional().describe("Skip exporting tags"),
4993
+ skipWebhooks: z76.boolean().optional().describe("Skip exporting webhooks"),
4994
+ stripTags: z76.boolean().optional().describe("Remove tags from entries and assets"),
4995
+ contentOnly: z76.boolean().optional().describe("Export only entries and assets"),
4474
4996
  queryEntries: EntryQuerySchema.optional().describe(
4475
4997
  "Export only entries that match query parameters"
4476
4998
  ),
4477
4999
  queryAssets: AssetQuerySchema.optional().describe(
4478
5000
  "Export only assets that match query parameters"
4479
5001
  ),
4480
- downloadAssets: z73.boolean().optional().describe("Download asset files to disk"),
4481
- host: z73.string().optional().describe("Management API host"),
4482
- hostDelivery: z73.string().optional().describe("Delivery API host"),
4483
- proxy: z73.string().optional().describe("HTTP/HTTPS proxy config"),
4484
- rawProxy: z73.boolean().optional().describe("Pass raw proxy config directly to Axios"),
4485
- maxAllowedLimit: z73.number().optional().describe("Page size for requests"),
4486
- headers: z73.record(z73.any()).optional().describe("Additional headers to include in requests"),
4487
- errorLogFile: z73.string().optional().describe("Path to error log output file"),
4488
- useVerboseRenderer: z73.boolean().optional().describe("Line-by-line logging, useful for CI"),
4489
- config: z73.string().optional().describe("Path to a JSON config file with all options")
5002
+ downloadAssets: z76.boolean().optional().describe("Download asset files to disk"),
5003
+ host: z76.string().optional().describe("Management API host"),
5004
+ hostDelivery: z76.string().optional().describe("Delivery API host"),
5005
+ proxy: z76.string().optional().describe("HTTP/HTTPS proxy config"),
5006
+ rawProxy: z76.boolean().optional().describe("Pass raw proxy config directly to Axios"),
5007
+ maxAllowedLimit: z76.number().optional().describe("Page size for requests"),
5008
+ headers: z76.record(z76.any()).optional().describe("Additional headers to include in requests"),
5009
+ errorLogFile: z76.string().optional().describe("Path to error log output file"),
5010
+ useVerboseRenderer: z76.boolean().optional().describe("Line-by-line logging, useful for CI"),
5011
+ config: z76.string().optional().describe("Path to a JSON config file with all options")
4490
5012
  }).optional(),
4491
- import: z73.object({
4492
- spaceId: z73.string().optional().describe("ID of the space to import into"),
4493
- environmentId: z73.string().optional().describe("Target environment in destination space"),
4494
- contentFile: z73.string().optional().describe("Path to JSON file containing the content to import"),
4495
- content: z73.record(z73.any()).optional().describe(
5013
+ import: z76.object({
5014
+ spaceId: z76.string().optional().describe("ID of the space to import into"),
5015
+ environmentId: z76.string().optional().describe("Target environment in destination space"),
5016
+ contentFile: z76.string().optional().describe("Path to JSON file containing the content to import"),
5017
+ content: z76.record(z76.any()).optional().describe(
4496
5018
  "JS object containing import content (must match expected structure)"
4497
5019
  ),
4498
- contentModelOnly: z73.boolean().optional().describe("Import only content types"),
4499
- skipContentModel: z73.boolean().optional().describe("Skip importing content types and locales"),
4500
- skipLocales: z73.boolean().optional().describe("Skip importing locales"),
4501
- skipContentUpdates: z73.boolean().optional().describe("Do not update existing content"),
4502
- skipContentPublishing: z73.boolean().optional().describe("Create but do not publish content"),
4503
- uploadAssets: z73.boolean().optional().describe("Upload asset files (requires assetsDirectory)"),
4504
- skipAssetUpdates: z73.boolean().optional().describe("Do not update existing assets"),
4505
- assetsDirectory: z73.string().optional().describe("Path to directory containing exported asset files"),
4506
- timeout: z73.number().optional().describe("Time between retries during asset processing (ms)"),
4507
- retryLimit: z73.number().optional().describe("Max retries for asset processing"),
4508
- host: z73.string().optional().describe("Management API host"),
4509
- proxy: z73.string().optional().describe("HTTP/HTTPS proxy string (host:port or user:pass@host:port)"),
4510
- rawProxy: z73.boolean().optional().describe("Pass proxy config directly to Axios"),
4511
- rateLimit: z73.number().optional().describe("Max requests per second to the API"),
4512
- headers: z73.record(z73.any()).optional().describe("Additional headers to attach to requests"),
4513
- errorLogFile: z73.string().optional().describe("Path to error log file"),
4514
- useVerboseRenderer: z73.boolean().optional().describe("Line-by-line progress output (good for CI)"),
4515
- config: z73.string().optional().describe("Path to config JSON file (merged with CLI args)")
5020
+ contentModelOnly: z76.boolean().optional().describe("Import only content types"),
5021
+ skipContentModel: z76.boolean().optional().describe("Skip importing content types and locales"),
5022
+ skipLocales: z76.boolean().optional().describe("Skip importing locales"),
5023
+ skipContentUpdates: z76.boolean().optional().describe("Do not update existing content"),
5024
+ skipContentPublishing: z76.boolean().optional().describe("Create but do not publish content"),
5025
+ uploadAssets: z76.boolean().optional().describe("Upload asset files (requires assetsDirectory)"),
5026
+ skipAssetUpdates: z76.boolean().optional().describe("Do not update existing assets"),
5027
+ assetsDirectory: z76.string().optional().describe("Path to directory containing exported asset files"),
5028
+ timeout: z76.number().optional().describe("Time between retries during asset processing (ms)"),
5029
+ retryLimit: z76.number().optional().describe("Max retries for asset processing"),
5030
+ host: z76.string().optional().describe("Management API host"),
5031
+ proxy: z76.string().optional().describe("HTTP/HTTPS proxy string (host:port or user:pass@host:port)"),
5032
+ rawProxy: z76.boolean().optional().describe("Pass proxy config directly to Axios"),
5033
+ rateLimit: z76.number().optional().describe("Max requests per second to the API"),
5034
+ headers: z76.record(z76.any()).optional().describe("Additional headers to attach to requests"),
5035
+ errorLogFile: z76.string().optional().describe("Path to error log file"),
5036
+ useVerboseRenderer: z76.boolean().optional().describe("Line-by-line progress output (good for CI)"),
5037
+ config: z76.string().optional().describe("Path to config JSON file (merged with CLI args)")
4516
5038
  }).optional()
4517
5039
  });
4518
5040
  var paramCollectionConfig = {
@@ -4628,33 +5150,33 @@ var createParamCollectionTool = withErrorHandling(
4628
5150
  );
4629
5151
 
4630
5152
  // src/tools/jobs/space-to-space-migration/importSpace.ts
4631
- import { z as z74 } from "zod";
5153
+ import { z as z77 } from "zod";
4632
5154
  var ImportSpaceToolParams = BaseToolSchema.extend({
4633
- contentFile: z74.string().optional().describe("Path to JSON file containing the content to import"),
4634
- content: z74.record(z74.any()).optional().describe(
5155
+ contentFile: z77.string().optional().describe("Path to JSON file containing the content to import"),
5156
+ content: z77.record(z77.any()).optional().describe(
4635
5157
  "JS object containing import content (must match expected structure)"
4636
5158
  ),
4637
- contentModelOnly: z74.boolean().optional().default(false).describe("Import only content types"),
4638
- skipContentModel: z74.boolean().optional().default(false).describe("Skip importing content types and locales"),
4639
- skipLocales: z74.boolean().optional().default(false).describe("Skip importing locales"),
4640
- skipContentUpdates: z74.boolean().optional().default(false).describe("Do not update existing content"),
4641
- skipContentPublishing: z74.boolean().optional().default(false).describe("Create but do not publish content"),
4642
- uploadAssets: z74.boolean().optional().default(false).describe("Upload asset files (requires assetsDirectory)"),
4643
- skipAssetUpdates: z74.boolean().optional().default(false).describe("Do not update existing assets"),
4644
- assetsDirectory: z74.string().optional().describe("Path to directory containing exported asset files"),
4645
- timeout: z74.number().optional().default(3e3).describe("Time between retries during asset processing (ms)"),
4646
- retryLimit: z74.number().optional().default(10).describe("Max retries for asset processing"),
4647
- host: z74.string().optional().describe("Management API host"),
4648
- proxy: z74.string().optional().describe("HTTP/HTTPS proxy string (host:port or user:pass@host:port)"),
4649
- rawProxy: z74.boolean().optional().describe("Pass proxy config directly to Axios"),
4650
- rateLimit: z74.number().optional().default(7).describe("Max requests per second to the API"),
4651
- headers: z74.record(z74.any()).optional().describe("Additional headers to attach to requests"),
4652
- errorLogFile: z74.string().optional().describe("Path to error log file"),
4653
- useVerboseRenderer: z74.boolean().optional().describe("Line-by-line progress output (good for CI)"),
4654
- config: z74.string().optional().describe("Path to config JSON file (merged with CLI args)")
5159
+ contentModelOnly: z77.boolean().optional().default(false).describe("Import only content types"),
5160
+ skipContentModel: z77.boolean().optional().default(false).describe("Skip importing content types and locales"),
5161
+ skipLocales: z77.boolean().optional().default(false).describe("Skip importing locales"),
5162
+ skipContentUpdates: z77.boolean().optional().default(false).describe("Do not update existing content"),
5163
+ skipContentPublishing: z77.boolean().optional().default(false).describe("Create but do not publish content"),
5164
+ uploadAssets: z77.boolean().optional().default(false).describe("Upload asset files (requires assetsDirectory)"),
5165
+ skipAssetUpdates: z77.boolean().optional().default(false).describe("Do not update existing assets"),
5166
+ assetsDirectory: z77.string().optional().describe("Path to directory containing exported asset files"),
5167
+ timeout: z77.number().optional().default(3e3).describe("Time between retries during asset processing (ms)"),
5168
+ retryLimit: z77.number().optional().default(10).describe("Max retries for asset processing"),
5169
+ rateLimit: z77.number().optional().default(7).describe("Max requests per second to the API"),
5170
+ errorLogFile: z77.string().optional().describe("Path to error log file"),
5171
+ useVerboseRenderer: z77.boolean().optional().describe("Line-by-line progress output (good for CI)")
4655
5172
  });
4656
5173
  function createImportSpaceTool(config) {
4657
5174
  async function tool2(args) {
5175
+ const targetEnvironmentId = args.environmentId || "master";
5176
+ assertEnvironmentNotProtected(
5177
+ targetEnvironmentId,
5178
+ config.protectedEnvironments
5179
+ );
4658
5180
  const clientConfig = createClientConfig(config);
4659
5181
  const managementToken = clientConfig.accessToken;
4660
5182
  if (!managementToken) {
@@ -4663,14 +5185,15 @@ function createImportSpaceTool(config) {
4663
5185
  const importOptions = {
4664
5186
  ...args,
4665
5187
  managementToken,
4666
- environmentId: args.environmentId || "master"
5188
+ host: config.host ?? "api.contentful.com",
5189
+ environmentId: targetEnvironmentId
4667
5190
  };
4668
5191
  try {
4669
5192
  const contentfulImport = await import("contentful-import");
4670
5193
  const result = await contentfulImport.default(importOptions);
4671
5194
  return createSuccessResponse("Space imported successfully", {
4672
5195
  spaceId: args.spaceId,
4673
- environmentId: args.environmentId || "master",
5196
+ environmentId: targetEnvironmentId,
4674
5197
  contentTypes: result.contentTypes?.length || 0,
4675
5198
  entries: result.entries?.length || 0,
4676
5199
  assets: result.assets?.length || 0,
@@ -4690,7 +5213,7 @@ function createImportSpaceTool(config) {
4690
5213
  }
4691
5214
 
4692
5215
  // src/tools/jobs/space-to-space-migration/migrationHandler.ts
4693
- import { z as z75 } from "zod";
5216
+ import { z as z78 } from "zod";
4694
5217
 
4695
5218
  // src/tools/jobs/space-to-space-migration/instructions.ts
4696
5219
  var S2S_MIGRATION_INSTRUCTIONS = `
@@ -4733,7 +5256,7 @@ The space to space migration workflow has been concluded and all related tools h
4733
5256
  The workflow is now complete. You can start a new migration workflow by calling space_to_space_migration_handler with enableWorkflow=true if needed.
4734
5257
  `;
4735
5258
  var SpaceToSpaceMigrationHandlerToolParams = BaseToolSchema.extend({
4736
- enableWorkflow: z75.boolean().describe(
5259
+ enableWorkflow: z78.boolean().describe(
4737
5260
  "Set to true to enable the workflow tools, false to disable them and conclude the workflow"
4738
5261
  )
4739
5262
  });