@contentful/mcp-tools 0.12.12 → 0.12.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -392,7 +392,8 @@ var RESOURCE_DISPLAY_NAME = {
392
392
  experienceFragment: "experience fragment",
393
393
  experienceTemplate: "experience template",
394
394
  dataAssembly: "data assembly",
395
- designToken: "design token"
395
+ designToken: "design token",
396
+ release: "release"
396
397
  };
397
398
  function buildConfirmationPreview(resource, id, details, confirmToken) {
398
399
  const displayName = RESOURCE_DISPLAY_NAME[resource];
@@ -6498,6 +6499,14 @@ var ExperienceSlotNodeSchema = z87.lazy(
6498
6499
  () => z87.union([ExperienceFragmentNodeSchema, InlineExperienceFragmentNodeSchema])
6499
6500
  );
6500
6501
 
6502
+ // src/types/cmaViewportCompatibility.ts
6503
+ function asViewportOptionalCmaPayload(payload) {
6504
+ return payload;
6505
+ }
6506
+ function asViewportOptionalCmaPayloadWithFlattenedDesignProperties(payload) {
6507
+ return payload;
6508
+ }
6509
+
6501
6510
  // src/tools/exo/components/createComponent.ts
6502
6511
  var CreateComponentToolParams = BaseToolSchema.extend({
6503
6512
  componentId: z88.string().optional().describe(
@@ -6505,7 +6514,9 @@ var CreateComponentToolParams = BaseToolSchema.extend({
6505
6514
  ),
6506
6515
  name: z88.string().describe("The name of the component"),
6507
6516
  description: z88.string().describe("Description of the component"),
6508
- viewports: z88.array(ViewportSchema).describe("Viewport definitions for the component (may be empty)"),
6517
+ viewports: z88.array(ViewportSchema).optional().describe(
6518
+ "Optional viewport definitions for the component. Omit for viewport-free components."
6519
+ ),
6509
6520
  contentProperties: z88.array(ContentPropertySchema).describe("Content property definitions (may be empty)"),
6510
6521
  designProperties: z88.array(DesignPropertySchema).describe("Design property definitions (may be empty)"),
6511
6522
  componentTree: z88.array(TreeNodeSchema).optional().describe("Optional component tree node definitions"),
@@ -6524,7 +6535,7 @@ function createComponentTool(config) {
6524
6535
  const componentData = {
6525
6536
  name: args.name,
6526
6537
  description: args.description,
6527
- viewports: args.viewports,
6538
+ ...args.viewports !== void 0 && { viewports: args.viewports },
6528
6539
  contentProperties: args.contentProperties,
6529
6540
  designProperties: args.designProperties,
6530
6541
  ...args.componentTree && { componentTree: args.componentTree },
@@ -6537,13 +6548,13 @@ function createComponentTool(config) {
6537
6548
  environmentId: args.environmentId,
6538
6549
  componentId: args.componentId
6539
6550
  },
6540
- {
6551
+ asViewportOptionalCmaPayload({
6541
6552
  sys: { id: args.componentId, type: "Component" },
6542
6553
  ...componentData
6543
- }
6554
+ })
6544
6555
  ) : await contentfulClient.component.create(
6545
6556
  { spaceId: args.spaceId, environmentId: args.environmentId },
6546
- componentData
6557
+ asViewportOptionalCmaPayload(componentData)
6547
6558
  );
6548
6559
  return createSuccessResponse("Component created successfully", {
6549
6560
  component
@@ -6588,7 +6599,8 @@ function upsertComponentTool(config) {
6588
6599
  `Version conflict: the component has changed since you read it (your version: ${args.version}, current version: ${current.sys.version}). Re-fetch the component with get_component and retry the update with the latest sys.version.`
6589
6600
  );
6590
6601
  }
6591
- const component = await contentfulClient.component.upsert(params, {
6602
+ const viewports = args.viewports ?? current.viewports;
6603
+ const componentData = {
6592
6604
  sys: {
6593
6605
  id: current.sys.id,
6594
6606
  type: "Component",
@@ -6596,14 +6608,18 @@ function upsertComponentTool(config) {
6596
6608
  },
6597
6609
  name: args.name ?? current.name,
6598
6610
  description: args.description ?? current.description,
6599
- viewports: args.viewports ?? current.viewports,
6611
+ ...viewports !== void 0 && { viewports },
6600
6612
  contentProperties: args.contentProperties ?? current.contentProperties,
6601
6613
  designProperties: args.designProperties ?? current.designProperties,
6602
6614
  ...args.componentTree ?? current.componentTree ? { componentTree: args.componentTree ?? current.componentTree } : {},
6603
6615
  ...args.slots ?? current.slots ? { slots: args.slots ?? current.slots } : {},
6604
6616
  ...args.metadata ?? current.metadata ? { metadata: args.metadata ?? current.metadata } : {},
6605
6617
  ...current.dataAssemblies ? { dataAssemblies: current.dataAssemblies } : {}
6606
- });
6618
+ };
6619
+ const component = await contentfulClient.component.upsert(
6620
+ params,
6621
+ asViewportOptionalCmaPayload(componentData)
6622
+ );
6607
6623
  return createSuccessResponse("Component updated successfully", {
6608
6624
  component
6609
6625
  });
@@ -6891,8 +6907,16 @@ var CreateExperienceFragmentToolParams = BaseToolSchema.extend({
6891
6907
  component: ComponentResourceLinkSchema.describe(
6892
6908
  "Resource link to the component this experience fragment is based on"
6893
6909
  ),
6894
- viewports: z95.array(ViewportSchema).describe("Viewport definitions (may be empty)"),
6895
- designProperties: z95.record(z95.string(), DimensionedDesignPropertyValueSchema).describe(
6910
+ viewports: z95.array(ViewportSchema).optional().describe(
6911
+ "Optional viewport definitions for the experience fragment. Omit for viewport-free experience fragments."
6912
+ ),
6913
+ designProperties: z95.record(
6914
+ z95.string(),
6915
+ z95.union([
6916
+ DesignPropertyValueSchema,
6917
+ DimensionedDesignPropertyValueSchema
6918
+ ])
6919
+ ).describe(
6896
6920
  "Design property values keyed by property ID (may be empty object)"
6897
6921
  ),
6898
6922
  contentBindings: ExperienceContentBindingsSchema.optional().describe(
@@ -6910,18 +6934,21 @@ function createExperienceFragmentTool(config) {
6910
6934
  config.protectedEnvironments
6911
6935
  );
6912
6936
  const contentfulClient = createExoToolClient(config, args);
6937
+ const experienceFragmentData = {
6938
+ name: args.name,
6939
+ description: args.description,
6940
+ component: args.component,
6941
+ ...args.viewports !== void 0 && { viewports: args.viewports },
6942
+ designProperties: args.designProperties,
6943
+ ...args.contentBindings && { contentBindings: args.contentBindings },
6944
+ ...args.slots && { slots: args.slots },
6945
+ ...args.metadata && { metadata: args.metadata }
6946
+ };
6913
6947
  const experienceFragment = await contentfulClient.experienceFragment.create(
6914
6948
  { spaceId: args.spaceId, environmentId: args.environmentId },
6915
- {
6916
- name: args.name,
6917
- description: args.description,
6918
- component: args.component,
6919
- viewports: args.viewports,
6920
- designProperties: args.designProperties,
6921
- ...args.contentBindings && { contentBindings: args.contentBindings },
6922
- ...args.slots && { slots: args.slots },
6923
- ...args.metadata && { metadata: args.metadata }
6924
- }
6949
+ asViewportOptionalCmaPayloadWithFlattenedDesignProperties(
6950
+ experienceFragmentData
6951
+ )
6925
6952
  );
6926
6953
  return createSuccessResponse("Experience fragment created successfully", {
6927
6954
  experienceFragment
@@ -6940,7 +6967,13 @@ var UpdateExperienceFragmentToolParams = BaseToolSchema.extend({
6940
6967
  name: z96.string().optional().describe("The name of the experience fragment"),
6941
6968
  description: z96.string().optional().describe("Description of the experience fragment"),
6942
6969
  viewports: z96.array(ViewportSchema).optional().describe("Viewport definitions; replaces existing viewports if provided"),
6943
- designProperties: z96.record(z96.string(), DimensionedDesignPropertyValueSchema).optional().describe("Design property values; replaces existing if provided"),
6970
+ designProperties: z96.record(
6971
+ z96.string(),
6972
+ z96.union([
6973
+ DesignPropertyValueSchema,
6974
+ DimensionedDesignPropertyValueSchema
6975
+ ])
6976
+ ).optional().describe("Design property values; replaces existing if provided"),
6944
6977
  contentBindings: ExperienceContentBindingsSchema.optional().describe(
6945
6978
  "Content bindings; replaces existing if provided"
6946
6979
  ),
@@ -6967,22 +7000,26 @@ function updateExperienceFragmentTool(config) {
6967
7000
  `Version conflict: the experience fragment has changed since you read it (your version: ${args.version}, current version: ${current.sys.version}). Re-fetch the experience fragment with get_experience_fragment and retry the update with the latest sys.version.`
6968
7001
  );
6969
7002
  }
7003
+ const viewports = args.viewports ?? current.viewports;
7004
+ const experienceFragmentData = {
7005
+ sys: {
7006
+ id: current.sys.id,
7007
+ type: "ExperienceFragment",
7008
+ version: current.sys.version
7009
+ },
7010
+ name: args.name ?? current.name,
7011
+ description: args.description ?? current.description,
7012
+ ...viewports !== void 0 && { viewports },
7013
+ designProperties: args.designProperties ?? current.designProperties,
7014
+ ...args.contentBindings ?? current.contentBindings ? { contentBindings: args.contentBindings ?? current.contentBindings } : {},
7015
+ ...args.slots ?? current.slots ? { slots: args.slots ?? current.slots } : {},
7016
+ ...args.metadata ?? current.metadata ? { metadata: args.metadata ?? current.metadata } : {}
7017
+ };
6970
7018
  const experienceFragment = await contentfulClient.experienceFragment.upsert(
6971
7019
  params,
6972
- {
6973
- sys: {
6974
- id: current.sys.id,
6975
- type: "ExperienceFragment",
6976
- version: current.sys.version
6977
- },
6978
- name: args.name ?? current.name,
6979
- description: args.description ?? current.description,
6980
- viewports: args.viewports ?? current.viewports,
6981
- designProperties: args.designProperties ?? current.designProperties,
6982
- ...args.contentBindings ?? current.contentBindings ? { contentBindings: args.contentBindings ?? current.contentBindings } : {},
6983
- ...args.slots ?? current.slots ? { slots: args.slots ?? current.slots } : {},
6984
- ...args.metadata ?? current.metadata ? { metadata: args.metadata ?? current.metadata } : {}
6985
- }
7020
+ asViewportOptionalCmaPayloadWithFlattenedDesignProperties(
7021
+ experienceFragmentData
7022
+ )
6986
7023
  );
6987
7024
  return createSuccessResponse("Experience fragment updated successfully", {
6988
7025
  experienceFragment
@@ -7271,8 +7308,8 @@ import { z as z102 } from "zod";
7271
7308
  var CreateExperienceTemplateToolParams = BaseToolSchema.extend({
7272
7309
  name: z102.string().describe("The name of the experience template"),
7273
7310
  description: z102.string().describe("Description of the experience template"),
7274
- viewports: z102.array(ViewportSchema).describe(
7275
- "Viewport definitions for the experience template (may be empty)"
7311
+ viewports: z102.array(ViewportSchema).optional().describe(
7312
+ "Optional viewport definitions for the experience template. Omit for viewport-free experience templates."
7276
7313
  ),
7277
7314
  contentProperties: z102.array(ContentPropertySchema).describe("Content property definitions (may be empty)"),
7278
7315
  designProperties: z102.array(DesignPropertySchema).describe("Design property definitions (may be empty)"),
@@ -7289,18 +7326,19 @@ function createExperienceTemplateTool(config) {
7289
7326
  config.protectedEnvironments
7290
7327
  );
7291
7328
  const contentfulClient = createExoToolClient(config, args);
7329
+ const experienceTemplateData = {
7330
+ name: args.name,
7331
+ description: args.description,
7332
+ ...args.viewports !== void 0 && { viewports: args.viewports },
7333
+ contentProperties: args.contentProperties,
7334
+ designProperties: args.designProperties,
7335
+ ...args.componentTree && { componentTree: args.componentTree },
7336
+ ...args.slots && { slots: args.slots },
7337
+ ...args.metadata && { metadata: args.metadata }
7338
+ };
7292
7339
  const experienceTemplate = await contentfulClient.experienceTemplate.create(
7293
7340
  { spaceId: args.spaceId, environmentId: args.environmentId },
7294
- {
7295
- name: args.name,
7296
- description: args.description,
7297
- viewports: args.viewports,
7298
- contentProperties: args.contentProperties,
7299
- designProperties: args.designProperties,
7300
- ...args.componentTree && { componentTree: args.componentTree },
7301
- ...args.slots && { slots: args.slots },
7302
- ...args.metadata && { metadata: args.metadata }
7303
- }
7341
+ asViewportOptionalCmaPayload(experienceTemplateData)
7304
7342
  );
7305
7343
  return createSuccessResponse("Experience template created successfully", {
7306
7344
  experienceTemplate
@@ -7345,24 +7383,26 @@ function upsertExperienceTemplateTool(config) {
7345
7383
  `Version conflict: the experience template has changed since you read it (your version: ${args.version}, current version: ${current.sys.version}). Re-fetch the experience template with get_experience_template and retry the update with the latest sys.version.`
7346
7384
  );
7347
7385
  }
7386
+ const viewports = args.viewports ?? current.viewports;
7387
+ const experienceTemplateData = {
7388
+ sys: {
7389
+ id: current.sys.id,
7390
+ type: "ExperienceTemplate",
7391
+ version: current.sys.version
7392
+ },
7393
+ name: args.name ?? current.name,
7394
+ description: args.description ?? current.description,
7395
+ ...viewports !== void 0 && { viewports },
7396
+ contentProperties: args.contentProperties ?? current.contentProperties,
7397
+ designProperties: args.designProperties ?? current.designProperties,
7398
+ ...args.componentTree ?? current.componentTree ? { componentTree: args.componentTree ?? current.componentTree } : {},
7399
+ ...args.slots ?? current.slots ? { slots: args.slots ?? current.slots } : {},
7400
+ ...args.metadata ?? current.metadata ? { metadata: args.metadata ?? current.metadata } : {},
7401
+ ...current.dataAssemblies ? { dataAssemblies: current.dataAssemblies } : {}
7402
+ };
7348
7403
  const experienceTemplate = await contentfulClient.experienceTemplate.upsert(
7349
7404
  params,
7350
- {
7351
- sys: {
7352
- id: current.sys.id,
7353
- type: "ExperienceTemplate",
7354
- version: current.sys.version
7355
- },
7356
- name: args.name ?? current.name,
7357
- description: args.description ?? current.description,
7358
- viewports: args.viewports ?? current.viewports,
7359
- contentProperties: args.contentProperties ?? current.contentProperties,
7360
- designProperties: args.designProperties ?? current.designProperties,
7361
- ...args.componentTree ?? current.componentTree ? { componentTree: args.componentTree ?? current.componentTree } : {},
7362
- ...args.slots ?? current.slots ? { slots: args.slots ?? current.slots } : {},
7363
- ...args.metadata ?? current.metadata ? { metadata: args.metadata ?? current.metadata } : {},
7364
- ...current.dataAssemblies ? { dataAssemblies: current.dataAssemblies } : {}
7365
- }
7405
+ asViewportOptionalCmaPayload(experienceTemplateData)
7366
7406
  );
7367
7407
  return createSuccessResponse("Experience template updated successfully", {
7368
7408
  experienceTemplate
@@ -7654,9 +7694,17 @@ var CreateExperienceToolParams = BaseToolSchema.extend({
7654
7694
  experienceTemplate: ExperienceTemplateResourceLinkSchema.describe(
7655
7695
  "Resource link to the ExperienceTemplate this experience is backed by"
7656
7696
  ),
7657
- viewports: z109.array(ViewportSchema).describe("Viewport definitions for the experience (may be empty)"),
7658
- designProperties: z109.record(z109.string(), DimensionedDesignPropertyValueSchema).describe(
7659
- "Design property values keyed by property ID. Each value is a dimensioned map (viewport ID \u2192 design value). May be an empty object."
7697
+ viewports: z109.array(ViewportSchema).optional().describe(
7698
+ "Optional viewport definitions for the experience. Omit for viewport-free experiences."
7699
+ ),
7700
+ designProperties: z109.record(
7701
+ z109.string(),
7702
+ z109.union([
7703
+ DesignPropertyValueSchema,
7704
+ DimensionedDesignPropertyValueSchema
7705
+ ])
7706
+ ).describe(
7707
+ "Design property values keyed by property ID. When viewports are provided, each value is a dimensioned map (viewport ID \u2192 design value); without viewports, use a direct design value. May be an empty object."
7660
7708
  ),
7661
7709
  contentBindings: ExperienceContentBindingsSchema.optional().describe(
7662
7710
  "Optional content bindings linking this experience to a data assembly"
@@ -7675,18 +7723,19 @@ function createExperienceTool(config) {
7675
7723
  config.protectedEnvironments
7676
7724
  );
7677
7725
  const contentfulClient = createExoToolClient(config, args);
7726
+ const experienceData = {
7727
+ name: args.name,
7728
+ description: args.description,
7729
+ experienceTemplate: args.experienceTemplate,
7730
+ ...args.viewports !== void 0 && { viewports: args.viewports },
7731
+ designProperties: args.designProperties,
7732
+ ...args.contentBindings && { contentBindings: args.contentBindings },
7733
+ ...args.slots && { slots: args.slots },
7734
+ ...args.metadata && { metadata: args.metadata }
7735
+ };
7678
7736
  const experience = await contentfulClient.experience.create(
7679
7737
  { spaceId: args.spaceId, environmentId: args.environmentId },
7680
- {
7681
- name: args.name,
7682
- description: args.description,
7683
- experienceTemplate: args.experienceTemplate,
7684
- viewports: args.viewports,
7685
- designProperties: args.designProperties,
7686
- ...args.contentBindings && { contentBindings: args.contentBindings },
7687
- ...args.slots && { slots: args.slots },
7688
- ...args.metadata && { metadata: args.metadata }
7689
- }
7738
+ asViewportOptionalCmaPayloadWithFlattenedDesignProperties(experienceData)
7690
7739
  );
7691
7740
  return createSuccessResponse("Experience created successfully", {
7692
7741
  experience
@@ -7705,7 +7754,13 @@ var UpsertExperienceToolParams = BaseToolSchema.extend({
7705
7754
  name: z110.string().optional().describe("The name of the experience"),
7706
7755
  description: z110.string().optional().describe("Description of the experience"),
7707
7756
  viewports: z110.array(ViewportSchema).optional().describe("Viewport definitions; replaces existing viewports if provided"),
7708
- designProperties: z110.record(z110.string(), DimensionedDesignPropertyValueSchema).optional().describe(
7757
+ designProperties: z110.record(
7758
+ z110.string(),
7759
+ z110.union([
7760
+ DesignPropertyValueSchema,
7761
+ DimensionedDesignPropertyValueSchema
7762
+ ])
7763
+ ).optional().describe(
7709
7764
  "Design property values keyed by property ID; replaces existing if provided"
7710
7765
  ),
7711
7766
  contentBindings: ExperienceContentBindingsSchema.optional().describe(
@@ -7734,7 +7789,8 @@ function upsertExperienceTool(config) {
7734
7789
  `Version conflict: the experience has changed since you read it (your version: ${args.version}, current version: ${current.sys.version}). Re-fetch the experience with get_experience and retry the update with the latest sys.version.`
7735
7790
  );
7736
7791
  }
7737
- const experience = await contentfulClient.experience.upsert(params, {
7792
+ const viewports = args.viewports ?? current.viewports;
7793
+ const experienceData = {
7738
7794
  sys: {
7739
7795
  id: current.sys.id,
7740
7796
  type: "Experience",
@@ -7742,12 +7798,16 @@ function upsertExperienceTool(config) {
7742
7798
  },
7743
7799
  name: args.name ?? current.name,
7744
7800
  description: args.description ?? current.description,
7745
- viewports: args.viewports ?? current.viewports,
7801
+ ...viewports !== void 0 && { viewports },
7746
7802
  designProperties: args.designProperties ?? current.designProperties,
7747
7803
  ...args.contentBindings ?? current.contentBindings ? { contentBindings: args.contentBindings ?? current.contentBindings } : {},
7748
7804
  ...args.slots ?? current.slots ? { slots: args.slots ?? current.slots } : {},
7749
7805
  ...args.metadata ?? current.metadata ? { metadata: args.metadata ?? current.metadata } : {}
7750
- });
7806
+ };
7807
+ const experience = await contentfulClient.experience.upsert(
7808
+ params,
7809
+ asViewportOptionalCmaPayloadWithFlattenedDesignProperties(experienceData)
7810
+ );
7751
7811
  return createSuccessResponse("Experience updated successfully", {
7752
7812
  experience
7753
7813
  });
@@ -8769,6 +8829,501 @@ function createDesignTokenTools(config) {
8769
8829
  };
8770
8830
  }
8771
8831
 
8832
+ // src/tools/releases/listReleases.ts
8833
+ import { z as z128 } from "zod";
8834
+ var MAX_ITEMS = 10;
8835
+ var ListReleasesToolParams = BaseToolSchema.extend({
8836
+ limit: z128.number().optional().describe("Maximum number of releases to return (max 10)"),
8837
+ pageNext: z128.string().optional().describe("Cursor token to fetch the next page of results"),
8838
+ pagePrev: z128.string().optional().describe("Cursor token to fetch the previous page of results"),
8839
+ statusIn: z128.string().optional().describe("Comma-separated list of statuses to include (active, archived)"),
8840
+ statusNin: z128.string().optional().describe("Comma-separated list of statuses to exclude (active, archived)"),
8841
+ titleMatch: z128.string().optional().describe("Full text phrase/term match on release title"),
8842
+ entitiesLinkType: z128.enum(["Entry", "Asset"]).optional().describe("Filter releases by the linked entity type (Entry or Asset)"),
8843
+ entitiesSysIdIn: z128.string().optional().describe(
8844
+ "Comma-separated list of entity IDs the release must contain. Requires entitiesLinkType."
8845
+ )
8846
+ });
8847
+ function listReleasesTool(config) {
8848
+ async function tool2(args) {
8849
+ if (args.entitiesSysIdIn && !args.entitiesLinkType) {
8850
+ throw new Error(
8851
+ "entitiesLinkType is required when entitiesSysIdIn is provided"
8852
+ );
8853
+ }
8854
+ const contentfulClient = createToolClient(config, args);
8855
+ const releases = await contentfulClient.release.query({
8856
+ spaceId: args.spaceId,
8857
+ environmentId: args.environmentId,
8858
+ query: {
8859
+ limit: Math.max(1, Math.min(args.limit ?? MAX_ITEMS, MAX_ITEMS)),
8860
+ ...args.pageNext && { pageNext: args.pageNext },
8861
+ ...args.pagePrev && { pagePrev: args.pagePrev },
8862
+ ...args.statusIn && { "sys.status[in]": args.statusIn },
8863
+ ...args.statusNin && { "sys.status[nin]": args.statusNin },
8864
+ ...args.titleMatch && { "title[match]": args.titleMatch },
8865
+ ...args.entitiesLinkType && {
8866
+ "entities.sys.linkType": args.entitiesLinkType
8867
+ },
8868
+ ...args.entitiesSysIdIn && {
8869
+ "entities.sys.id[in]": args.entitiesSysIdIn
8870
+ }
8871
+ }
8872
+ });
8873
+ const summarized = summarizeData(releases, {
8874
+ maxItems: MAX_ITEMS,
8875
+ remainingMessage: "To see more releases, ask me to retrieve the next page using the pageNext cursor."
8876
+ });
8877
+ return createSuccessResponse("Releases retrieved successfully", {
8878
+ releases: summarized,
8879
+ pages: releases.pages
8880
+ });
8881
+ }
8882
+ return withErrorHandling(tool2, "Error listing releases");
8883
+ }
8884
+
8885
+ // src/tools/releases/getRelease.ts
8886
+ import { z as z129 } from "zod";
8887
+ var GetReleaseToolParams = BaseToolSchema.extend({
8888
+ releaseId: z129.string().describe("The ID of the release to retrieve")
8889
+ });
8890
+ function getReleaseTool(config) {
8891
+ async function tool2(args) {
8892
+ const params = {
8893
+ spaceId: args.spaceId,
8894
+ environmentId: args.environmentId,
8895
+ releaseId: args.releaseId
8896
+ };
8897
+ const contentfulClient = createToolClient(config, args);
8898
+ const release = await contentfulClient.release.get(params);
8899
+ return createSuccessResponse("Release retrieved successfully", {
8900
+ release
8901
+ });
8902
+ }
8903
+ return withErrorHandling(tool2, "Error retrieving release");
8904
+ }
8905
+
8906
+ // src/tools/releases/createRelease.ts
8907
+ import { z as z131 } from "zod";
8908
+
8909
+ // src/tools/releases/releaseEntities.ts
8910
+ import { z as z130 } from "zod";
8911
+ var ReleaseEntityLinkSchema = z130.object({
8912
+ id: z130.string().describe("The ID of the Entry or Asset"),
8913
+ linkType: z130.enum(["Entry", "Asset"]).describe("The type of entity being linked")
8914
+ });
8915
+ function createReleaseEntities(entities) {
8916
+ return {
8917
+ sys: { type: "Array" },
8918
+ items: entities.map((entity) => ({
8919
+ sys: {
8920
+ type: "Link",
8921
+ linkType: entity.linkType,
8922
+ id: entity.id
8923
+ }
8924
+ }))
8925
+ };
8926
+ }
8927
+
8928
+ // src/tools/releases/createRelease.ts
8929
+ var CreateReleaseToolParams = BaseToolSchema.extend({
8930
+ title: z131.string().describe("The title of the release"),
8931
+ entities: z131.array(ReleaseEntityLinkSchema).describe("The Entries and/or Assets to include in the release")
8932
+ });
8933
+ function createReleaseTool(config) {
8934
+ async function tool2(args) {
8935
+ assertEnvironmentNotProtected(
8936
+ args.environmentId,
8937
+ config.protectedEnvironments
8938
+ );
8939
+ const contentfulClient = createToolClient(config, args);
8940
+ const release = await contentfulClient.release.create(
8941
+ {
8942
+ spaceId: args.spaceId,
8943
+ environmentId: args.environmentId
8944
+ },
8945
+ {
8946
+ title: args.title,
8947
+ entities: createReleaseEntities(args.entities)
8948
+ }
8949
+ );
8950
+ return createSuccessResponse("Release created successfully", { release });
8951
+ }
8952
+ return withErrorHandling(tool2, "Error creating release");
8953
+ }
8954
+
8955
+ // src/tools/releases/updateRelease.ts
8956
+ import { z as z132 } from "zod";
8957
+ var UpdateReleaseToolParams = BaseToolSchema.extend({
8958
+ releaseId: z132.string().describe("The ID of the release to update"),
8959
+ title: z132.string().optional().describe("The new title of the release. Omit to keep the existing title."),
8960
+ entities: z132.array(ReleaseEntityLinkSchema).optional().describe(
8961
+ "The full replacement list of Entries/Assets for the release. Omit to keep the existing entities."
8962
+ )
8963
+ });
8964
+ function updateReleaseTool(config) {
8965
+ async function tool2(args) {
8966
+ assertEnvironmentNotProtected(
8967
+ args.environmentId,
8968
+ config.protectedEnvironments
8969
+ );
8970
+ const params = {
8971
+ spaceId: args.spaceId,
8972
+ environmentId: args.environmentId,
8973
+ releaseId: args.releaseId
8974
+ };
8975
+ const contentfulClient = createToolClient(config, args);
8976
+ const existingRelease = await contentfulClient.release.get(params);
8977
+ const entities = args.entities ? createReleaseEntities(args.entities) : existingRelease.entities;
8978
+ const updatedRelease = await contentfulClient.release.update(
8979
+ { ...params, version: existingRelease.sys.version },
8980
+ {
8981
+ title: args.title ?? existingRelease.title,
8982
+ entities
8983
+ }
8984
+ );
8985
+ return createSuccessResponse("Release updated successfully", {
8986
+ release: updatedRelease
8987
+ });
8988
+ }
8989
+ return withErrorHandling(tool2, "Error updating release");
8990
+ }
8991
+
8992
+ // src/tools/releases/deleteRelease.ts
8993
+ import { z as z133 } from "zod";
8994
+ var DeleteReleaseToolParams = BaseToolSchema.extend({
8995
+ releaseId: z133.string().describe("The ID of the release to delete"),
8996
+ confirm: z133.boolean().optional().describe(
8997
+ "Set to true on the second call to actually perform the deletion. Required together with confirmToken."
8998
+ ),
8999
+ confirmToken: z133.string().optional().describe(
9000
+ "Token returned by the preview call; must be supplied with confirm: true."
9001
+ )
9002
+ });
9003
+ function deleteReleaseTool(config) {
9004
+ async function tool2(args) {
9005
+ assertEnvironmentNotProtected(
9006
+ args.environmentId,
9007
+ config.protectedEnvironments
9008
+ );
9009
+ const params = {
9010
+ spaceId: args.spaceId,
9011
+ environmentId: args.environmentId,
9012
+ releaseId: args.releaseId
9013
+ };
9014
+ const contentfulClient = createToolClient(config, args);
9015
+ const release = await contentfulClient.release.get(params);
9016
+ const expectedToken = buildConfirmToken(
9017
+ "release",
9018
+ args.releaseId,
9019
+ release.sys.version
9020
+ );
9021
+ if (args.confirm !== true || args.confirmToken !== expectedToken) {
9022
+ const preview = buildConfirmationPreview(
9023
+ "release",
9024
+ args.releaseId,
9025
+ { release },
9026
+ expectedToken
9027
+ );
9028
+ return createSuccessResponse(`${CONFIRMATION_MESSAGE_PREFIX} release`, {
9029
+ ...preview,
9030
+ instructions: `${preview.instructions} Deleting a release also permanently deletes all ReleaseActions linked to it.`
9031
+ });
9032
+ }
9033
+ await contentfulClient.release.delete(params);
9034
+ return createSuccessResponse("Release deleted successfully", { release });
9035
+ }
9036
+ return withErrorHandling(tool2, "Error deleting release");
9037
+ }
9038
+
9039
+ // src/tools/releases/publishRelease.ts
9040
+ import { z as z134 } from "zod";
9041
+ var PublishReleaseToolParams = BaseToolSchema.extend({
9042
+ releaseId: z134.string().describe("The ID of the release to publish")
9043
+ });
9044
+ function publishReleaseTool(config) {
9045
+ async function tool2(args) {
9046
+ assertEnvironmentNotProtected(
9047
+ args.environmentId,
9048
+ config.protectedEnvironments
9049
+ );
9050
+ const params = {
9051
+ spaceId: args.spaceId,
9052
+ environmentId: args.environmentId,
9053
+ releaseId: args.releaseId
9054
+ };
9055
+ const contentfulClient = createToolClient(config, args);
9056
+ const release = await contentfulClient.release.get(params);
9057
+ const releaseAction = await contentfulClient.release.publish({
9058
+ ...params,
9059
+ version: release.sys.version
9060
+ });
9061
+ return createSuccessResponse("Release publish queued", {
9062
+ actionId: releaseAction.sys.id,
9063
+ status: releaseAction.sys.status,
9064
+ releaseId: args.releaseId,
9065
+ note: "Use get_release_action with this actionId to check whether the publish succeeded."
9066
+ });
9067
+ }
9068
+ return withErrorHandling(tool2, "Error publishing release");
9069
+ }
9070
+
9071
+ // src/tools/releases/unpublishRelease.ts
9072
+ import { z as z135 } from "zod";
9073
+ var UnpublishReleaseToolParams = BaseToolSchema.extend({
9074
+ releaseId: z135.string().describe("The ID of the release to unpublish")
9075
+ });
9076
+ function unpublishReleaseTool(config) {
9077
+ async function tool2(args) {
9078
+ assertEnvironmentNotProtected(
9079
+ args.environmentId,
9080
+ config.protectedEnvironments
9081
+ );
9082
+ const params = {
9083
+ spaceId: args.spaceId,
9084
+ environmentId: args.environmentId,
9085
+ releaseId: args.releaseId
9086
+ };
9087
+ const contentfulClient = createToolClient(config, args);
9088
+ const release = await contentfulClient.release.get(params);
9089
+ const releaseAction = await contentfulClient.release.unpublish({
9090
+ ...params,
9091
+ version: release.sys.version
9092
+ });
9093
+ return createSuccessResponse("Release unpublish queued", {
9094
+ actionId: releaseAction.sys.id,
9095
+ status: releaseAction.sys.status,
9096
+ releaseId: args.releaseId,
9097
+ note: "Use get_release_action with this actionId to check whether the unpublish succeeded."
9098
+ });
9099
+ }
9100
+ return withErrorHandling(tool2, "Error unpublishing release");
9101
+ }
9102
+
9103
+ // src/tools/releases/validateRelease.ts
9104
+ import { z as z136 } from "zod";
9105
+ var ValidateReleaseToolParams = BaseToolSchema.extend({
9106
+ releaseId: z136.string().describe("The ID of the release to validate"),
9107
+ action: z136.enum(["publish", "unpublish"]).optional().describe(
9108
+ "The downstream action to validate the release against. Omit to run a general validation."
9109
+ )
9110
+ });
9111
+ function validateReleaseTool(config) {
9112
+ async function tool2(args) {
9113
+ const params = {
9114
+ spaceId: args.spaceId,
9115
+ environmentId: args.environmentId,
9116
+ releaseId: args.releaseId
9117
+ };
9118
+ const contentfulClient = createToolClient(config, args);
9119
+ const releaseAction = await contentfulClient.release.validate(
9120
+ params,
9121
+ args.action ? { action: args.action } : void 0
9122
+ );
9123
+ return createSuccessResponse("Release validation queued", {
9124
+ actionId: releaseAction.sys.id,
9125
+ status: releaseAction.sys.status,
9126
+ releaseId: args.releaseId,
9127
+ note: "Use get_release_action with this actionId to check whether validation succeeded."
9128
+ });
9129
+ }
9130
+ return withErrorHandling(tool2, "Error validating release");
9131
+ }
9132
+
9133
+ // src/tools/releases/getReleaseAction.ts
9134
+ import { z as z137 } from "zod";
9135
+ var GetReleaseActionToolParams = BaseToolSchema.extend({
9136
+ releaseId: z137.string().describe("The ID of the release the action belongs to"),
9137
+ actionId: z137.string().describe("The ID of the release action to retrieve")
9138
+ });
9139
+ function getReleaseActionTool(config) {
9140
+ async function tool2(args) {
9141
+ const params = {
9142
+ spaceId: args.spaceId,
9143
+ environmentId: args.environmentId,
9144
+ releaseId: args.releaseId,
9145
+ actionId: args.actionId
9146
+ };
9147
+ const contentfulClient = createToolClient(config, args);
9148
+ const releaseAction = await contentfulClient.releaseAction.get(params);
9149
+ return createSuccessResponse("Release action retrieved successfully", {
9150
+ releaseAction
9151
+ });
9152
+ }
9153
+ return withErrorHandling(tool2, "Error retrieving release action");
9154
+ }
9155
+
9156
+ // src/tools/releases/listReleaseActions.ts
9157
+ import { z as z138 } from "zod";
9158
+ var MAX_ITEMS2 = 10;
9159
+ var ListReleaseActionsToolParams = BaseToolSchema.extend({
9160
+ releaseId: z138.string().optional().describe("Comma-separated list of release IDs to filter actions by"),
9161
+ action: z138.enum(["publish", "unpublish", "validate"]).optional().describe("Filter by release action type"),
9162
+ statusIn: z138.string().optional().describe(
9163
+ "Comma-separated list of statuses to include (created, inProgress, succeeded, failed)"
9164
+ ),
9165
+ statusNin: z138.string().optional().describe(
9166
+ "Comma-separated list of statuses to exclude (created, inProgress, succeeded, failed)"
9167
+ ),
9168
+ limit: z138.number().optional().describe("Maximum number of release actions to return")
9169
+ });
9170
+ function listReleaseActionsTool(config) {
9171
+ async function tool2(args) {
9172
+ const contentfulClient = createToolClient(config, args);
9173
+ const releaseActions = await contentfulClient.releaseAction.getMany({
9174
+ spaceId: args.spaceId,
9175
+ environmentId: args.environmentId,
9176
+ query: {
9177
+ limit: Math.max(1, Math.min(args.limit ?? MAX_ITEMS2, MAX_ITEMS2)),
9178
+ ...args.releaseId && { "sys.release.sys.id[in]": args.releaseId },
9179
+ ...args.action && { action: args.action },
9180
+ ...args.statusIn && { "sys.status[in]": args.statusIn },
9181
+ ...args.statusNin && { "sys.status[nin]": args.statusNin }
9182
+ }
9183
+ });
9184
+ const summarized = summarizeData(releaseActions, {
9185
+ maxItems: MAX_ITEMS2,
9186
+ remainingMessage: "To see more release actions, narrow your filters or ask for a smaller limit."
9187
+ });
9188
+ return createSuccessResponse("Release actions retrieved successfully", {
9189
+ releaseActions: summarized
9190
+ });
9191
+ }
9192
+ return withErrorHandling(tool2, "Error listing release actions");
9193
+ }
9194
+
9195
+ // src/tools/releases/register.ts
9196
+ function createReleaseTools(config) {
9197
+ const listReleases = listReleasesTool(config);
9198
+ const getRelease = getReleaseTool(config);
9199
+ const createRelease = createReleaseTool(config);
9200
+ const updateRelease = updateReleaseTool(config);
9201
+ const deleteRelease = deleteReleaseTool(config);
9202
+ const publishRelease = publishReleaseTool(config);
9203
+ const unpublishRelease = unpublishReleaseTool(config);
9204
+ const validateRelease = validateReleaseTool(config);
9205
+ const getReleaseAction = getReleaseActionTool(config);
9206
+ const listReleaseActions = listReleaseActionsTool(config);
9207
+ return {
9208
+ listReleases: {
9209
+ title: "list_releases",
9210
+ description: "List releases in a space/environment. Returns a maximum of 10 items per request. Use pageNext/pagePrev cursors to paginate through results.",
9211
+ inputParams: ListReleasesToolParams.shape,
9212
+ annotations: {
9213
+ readOnlyHint: true,
9214
+ destructiveHint: false,
9215
+ openWorldHint: false
9216
+ },
9217
+ tool: listReleases
9218
+ },
9219
+ getRelease: {
9220
+ title: "get_release",
9221
+ description: "Retrieve a release",
9222
+ inputParams: GetReleaseToolParams.shape,
9223
+ annotations: {
9224
+ readOnlyHint: true,
9225
+ destructiveHint: false,
9226
+ openWorldHint: false
9227
+ },
9228
+ tool: getRelease
9229
+ },
9230
+ createRelease: {
9231
+ title: "create_release",
9232
+ description: "Create a release with a title and a set of Entries/Assets to include in it.",
9233
+ inputParams: CreateReleaseToolParams.shape,
9234
+ annotations: {
9235
+ readOnlyHint: false,
9236
+ destructiveHint: false,
9237
+ idempotentHint: false,
9238
+ openWorldHint: false
9239
+ },
9240
+ tool: createRelease
9241
+ },
9242
+ updateRelease: {
9243
+ title: "update_release",
9244
+ description: "Update a release's title and/or the Entries/Assets it contains. Omitted fields keep their current value.",
9245
+ inputParams: UpdateReleaseToolParams.shape,
9246
+ annotations: {
9247
+ readOnlyHint: false,
9248
+ destructiveHint: false,
9249
+ idempotentHint: false,
9250
+ openWorldHint: false
9251
+ },
9252
+ tool: updateRelease
9253
+ },
9254
+ deleteRelease: {
9255
+ title: "delete_release",
9256
+ description: "Delete a release. This is a two-phase operation: the first call (without confirm/confirmToken) returns a preview of the release and a confirmToken. To complete the deletion, call this tool again with the same releaseId, confirm: true, and the confirmToken from the preview response. Deleting a release also permanently deletes all ReleaseActions linked to it.",
9257
+ inputParams: DeleteReleaseToolParams.shape,
9258
+ annotations: {
9259
+ readOnlyHint: false,
9260
+ destructiveHint: true,
9261
+ idempotentHint: false,
9262
+ openWorldHint: false
9263
+ },
9264
+ tool: deleteRelease
9265
+ },
9266
+ publishRelease: {
9267
+ title: "publish_release",
9268
+ description: "Publish a release. Publishing is asynchronous: this tool returns as soon as the publish is queued (status created/inProgress), not once it completes. Use get_release_action with the returned actionId to check the outcome.",
9269
+ inputParams: PublishReleaseToolParams.shape,
9270
+ annotations: {
9271
+ readOnlyHint: false,
9272
+ destructiveHint: true,
9273
+ idempotentHint: true,
9274
+ openWorldHint: false
9275
+ },
9276
+ tool: publishRelease
9277
+ },
9278
+ unpublishRelease: {
9279
+ title: "unpublish_release",
9280
+ description: "Unpublish a release. Unpublishing is asynchronous: this tool returns as soon as the unpublish is queued (status created/inProgress), not once it completes. Use get_release_action with the returned actionId to check the outcome.",
9281
+ inputParams: UnpublishReleaseToolParams.shape,
9282
+ annotations: {
9283
+ readOnlyHint: false,
9284
+ destructiveHint: true,
9285
+ idempotentHint: true,
9286
+ openWorldHint: false
9287
+ },
9288
+ tool: unpublishRelease
9289
+ },
9290
+ validateRelease: {
9291
+ title: "validate_release",
9292
+ description: "Validate a release, optionally against a specific downstream action (publish or unpublish). Validation is asynchronous: this tool returns as soon as validation is queued (status created/inProgress), not once it completes. Use get_release_action with the returned actionId to check the outcome.",
9293
+ inputParams: ValidateReleaseToolParams.shape,
9294
+ annotations: {
9295
+ readOnlyHint: false,
9296
+ destructiveHint: false,
9297
+ idempotentHint: true,
9298
+ openWorldHint: false
9299
+ },
9300
+ tool: validateRelease
9301
+ },
9302
+ getReleaseAction: {
9303
+ title: "get_release_action",
9304
+ description: "Retrieve a release action by ID to check the status (created, inProgress, succeeded, failed) of a previously queued publish, unpublish, or validate operation.",
9305
+ inputParams: GetReleaseActionToolParams.shape,
9306
+ annotations: {
9307
+ readOnlyHint: true,
9308
+ destructiveHint: false,
9309
+ openWorldHint: false
9310
+ },
9311
+ tool: getReleaseAction
9312
+ },
9313
+ listReleaseActions: {
9314
+ title: "list_release_actions",
9315
+ description: "List release actions in a space/environment. Returns a maximum of 10 items per request. Optionally filter by release ID, action type (publish/unpublish/validate), or status.",
9316
+ inputParams: ListReleaseActionsToolParams.shape,
9317
+ annotations: {
9318
+ readOnlyHint: true,
9319
+ destructiveHint: false,
9320
+ openWorldHint: false
9321
+ },
9322
+ tool: listReleaseActions
9323
+ }
9324
+ };
9325
+ }
9326
+
8772
9327
  // src/ContentfulMcpTools.ts
8773
9328
  var ContentfulMcpTools = class {
8774
9329
  config;
@@ -8871,6 +9426,12 @@ var ContentfulMcpTools = class {
8871
9426
  getSpaceTools() {
8872
9427
  return createSpaceTools(this.config);
8873
9428
  }
9429
+ /**
9430
+ * Get release tools
9431
+ */
9432
+ getReleaseTools() {
9433
+ return createReleaseTools(this.config);
9434
+ }
8874
9435
  /**
8875
9436
  * Get tag tools
8876
9437
  */