@kontent-ai/mcp-server 0.23.2 → 0.24.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 (34) hide show
  1. package/README.md +14 -2
  2. package/build/bin.js +1 -1
  3. package/build/schemas/assetFolderSchemas.js +44 -0
  4. package/build/schemas/assetSchemas.js +23 -0
  5. package/build/schemas/{contentTypeSchemas.js → contentTypeAndSnippetSchemas.js} +9 -10
  6. package/build/schemas/patchSchemas/baseTypeAndSnippetPatchSchemas.js +41 -0
  7. package/build/schemas/patchSchemas/contentTypePatchSchemas.js +4 -46
  8. package/build/schemas/patchSchemas/snippetPatchSchemas.js +22 -0
  9. package/build/schemas/patchSchemas/taxonomyPatchSchemas.js +67 -0
  10. package/build/schemas/spaceSchemas.js +30 -0
  11. package/build/server.js +20 -0
  12. package/build/telemetry/applicationInsights.js +1 -1
  13. package/build/tools/add-content-type-mapi.js +1 -1
  14. package/build/tools/add-content-type-snippet-mapi.js +1 -1
  15. package/build/tools/add-space-mapi.js +23 -0
  16. package/build/tools/context/patch-guide-path-based.js +53 -0
  17. package/build/tools/context/patch-guide-property-based.js +42 -0
  18. package/build/tools/context/patch-guide-reference-based.js +86 -0
  19. package/build/tools/delete-space-mapi.js +20 -0
  20. package/build/tools/delete-taxonomy-group-mapi.js +20 -0
  21. package/build/tools/delete-type-snippet-mapi.js +23 -0
  22. package/build/tools/get-patch-guide.js +31 -3
  23. package/build/tools/get-taxonomy-group-mapi.js +2 -2
  24. package/build/tools/list-asset-folders-mapi.js +15 -0
  25. package/build/tools/list-spaces-mapi.js +1 -1
  26. package/build/tools/list-taxonomy-groups-mapi.js +1 -1
  27. package/build/tools/patch-asset-folders-mapi.js +25 -0
  28. package/build/tools/patch-content-type-mapi.js +10 -6
  29. package/build/tools/patch-space-mapi.js +28 -0
  30. package/build/tools/patch-taxonomy-group-mapi.js +28 -0
  31. package/build/tools/patch-type-snippet-mapi.js +30 -0
  32. package/build/tools/update-asset-mapi.js +24 -0
  33. package/package.json +1 -1
  34. package/build/tools/context/patch-operations-guide.js +0 -58
package/README.md CHANGED
@@ -63,7 +63,7 @@ npx @kontent-ai/mcp-server@latest shttp
63
63
 
64
64
  ### Patch Operations Guide
65
65
 
66
- * **get-patch-guide** – 🚨 **REQUIRED before any patch operation**. Get JSON Patch operations guide for Kontent.ai Management API
66
+ * **get-patch-guide** – 🚨 **REQUIRED before any patch operation**. Get patch operations guide for Kontent.ai Management API by entity type
67
67
 
68
68
  ### Content Type Management
69
69
 
@@ -78,17 +78,20 @@ npx @kontent-ai/mcp-server@latest shttp
78
78
  * **get-type-snippet-mapi** – Get Kontent.ai content type snippet by internal ID from Management API
79
79
  * **list-content-type-snippets-mapi** – Get all Kontent.ai content type snippets from Management API
80
80
  * **add-content-type-snippet-mapi** – Add new Kontent.ai content type snippet via Management API
81
+ * **patch-type-snippet-mapi** – Update an existing Kontent.ai content type snippet by internal ID using patch operations (move, addInto, remove, replace)
82
+ * **delete-type-snippet-mapi** – Delete a Kontent.ai content type snippet by codename
81
83
 
82
84
  ### Taxonomy Management
83
85
 
84
86
  * **get-taxonomy-group-mapi** – Get Kontent.ai taxonomy group by internal ID from Management API
85
87
  * **list-taxonomy-groups-mapi** – Get all Kontent.ai taxonomy groups from Management API
86
88
  * **add-taxonomy-group-mapi** – Add new Kontent.ai taxonomy group via Management API
89
+ * **patch-taxonomy-group-mapi** – Update Kontent.ai taxonomy group using patch operations (addInto, move, remove, replace) via Management API
90
+ * **delete-taxonomy-group-mapi** – Delete Kontent.ai taxonomy group by internal ID
87
91
 
88
92
  ### Content Item Management
89
93
 
90
94
  * **get-item-mapi** – Get Kontent.ai item by internal ID from Management API
91
- * **get-item-dapi** – Get Kontent.ai item by codename from Delivery API
92
95
  * **get-latest-variant-mapi** – Get latest version of Kontent.ai language variant from Management API
93
96
  * **get-published-variant-mapi** – Get published version of Kontent.ai language variant from Management API
94
97
  * **list-variants-item-mapi** – List all Kontent.ai language variants of a content item from Management API
@@ -109,6 +112,12 @@ npx @kontent-ai/mcp-server@latest shttp
109
112
 
110
113
  * **get-asset-mapi** – Get a specific Kontent.ai asset by internal ID from Management API
111
114
  * **list-assets-mapi** – Get all Kontent.ai assets from Management API
115
+ * **update-asset-mapi** – Update Kontent.ai asset by internal ID
116
+
117
+ ### Asset Folder Management
118
+
119
+ * **list-asset-folders-mapi** – List all Kontent.ai asset folders
120
+ * **patch-asset-folders-mapi** – Modify Kontent.ai asset folders using patch operations (addInto to add new folders, rename to change names, remove to delete folders)
112
121
 
113
122
  ### Language Management
114
123
 
@@ -124,6 +133,9 @@ npx @kontent-ai/mcp-server@latest shttp
124
133
  ### Space Management
125
134
 
126
135
  * **list-spaces-mapi** – Get all Kontent.ai spaces from Management API
136
+ * **add-space-mapi** – Add Kontent.ai space to environment
137
+ * **patch-space-mapi** – Patch Kontent.ai space using replace operations
138
+ * **delete-space-mapi** – Delete Kontent.ai space
127
139
 
128
140
  ### Workflow Management
129
141
 
package/build/bin.js CHANGED
@@ -152,7 +152,7 @@ Available endpoints:
152
152
  async function startStdio() {
153
153
  const { server } = createServer();
154
154
  const transport = new StdioServerTransport();
155
- console.log(`Kontent.ai MCP Server v${version} (stdio) starting`);
155
+ console.error(`Kontent.ai MCP Server v${version} (stdio) starting`);
156
156
  await server.connect(transport);
157
157
  }
158
158
  async function main() {
@@ -0,0 +1,44 @@
1
+ import { z } from "zod";
2
+ import { referenceObjectSchema } from "./referenceObjectSchema.js";
3
+ const assetFolderValueSchema = z.object({
4
+ name: z.string(),
5
+ codename: z.string().optional(),
6
+ external_id: z.string().optional(),
7
+ folders: z.lazy(() => z.array(assetFolderValueSchema)).optional(),
8
+ });
9
+ const addIntoBaseSchema = {
10
+ op: z.literal("addInto"),
11
+ reference: referenceObjectSchema
12
+ .optional()
13
+ .describe("Parent folder reference. Omit to add at root level."),
14
+ value: assetFolderValueSchema,
15
+ };
16
+ const addIntoBeforeOperationSchema = z.object({
17
+ ...addIntoBaseSchema,
18
+ before: referenceObjectSchema,
19
+ });
20
+ const addIntoAfterOperationSchema = z.object({
21
+ ...addIntoBaseSchema,
22
+ after: referenceObjectSchema,
23
+ });
24
+ const addIntoDefaultOperationSchema = z.object(addIntoBaseSchema);
25
+ const renameOperationSchema = z.object({
26
+ op: z.literal("rename"),
27
+ reference: referenceObjectSchema,
28
+ value: z.string(),
29
+ });
30
+ const removeOperationSchema = z.object({
31
+ op: z.literal("remove"),
32
+ reference: referenceObjectSchema,
33
+ });
34
+ const assetFolderPatchOperationSchema = z.union([
35
+ addIntoBeforeOperationSchema,
36
+ addIntoAfterOperationSchema,
37
+ addIntoDefaultOperationSchema,
38
+ renameOperationSchema,
39
+ removeOperationSchema,
40
+ ]);
41
+ export const assetFolderPatchOperationsSchema = z
42
+ .array(assetFolderPatchOperationSchema)
43
+ .min(1)
44
+ .describe("Patch operations array. Use addInto to add new folders (with optional reference for parent, before/after for positioning), rename to change folder names, remove to delete folders.");
@@ -0,0 +1,23 @@
1
+ import { z } from "zod";
2
+ import { referenceObjectSchema } from "./referenceObjectSchema.js";
3
+ const assetDescriptionSchema = z.object({
4
+ language: referenceObjectSchema,
5
+ description: z.string(),
6
+ });
7
+ const assetTaxonomyElementSchema = z.object({
8
+ element: referenceObjectSchema,
9
+ value: z.array(referenceObjectSchema),
10
+ });
11
+ const assetCollectionReferenceSchema = z.object({
12
+ reference: referenceObjectSchema,
13
+ });
14
+ export const updateAssetDataSchema = z
15
+ .object({
16
+ title: z.string().optional(),
17
+ codename: z.string().optional(),
18
+ collection: assetCollectionReferenceSchema.optional(),
19
+ folder: referenceObjectSchema.optional(),
20
+ descriptions: z.array(assetDescriptionSchema).optional(),
21
+ elements: z.array(assetTaxonomyElementSchema).optional(),
22
+ })
23
+ .describe("Only include properties you want to update; omitted fields retain existing values.");
@@ -1,9 +1,5 @@
1
1
  import { z } from "zod";
2
- // Reference by id or codename (id preferred)
3
- export const referenceObjectSchema = z.object({
4
- id: z.string().optional(),
5
- codename: z.string().optional(),
6
- });
2
+ import { referenceObjectSchema } from "./referenceObjectSchema.js";
7
3
  // Common property schemas
8
4
  const baseElementSchema = {
9
5
  codename: z.string().optional(),
@@ -16,7 +12,10 @@ const contentGroupElementSchema = {
16
12
  const namedElementSchema = {
17
13
  ...baseElementSchema,
18
14
  name: z.string(),
19
- guidelines: z.string().optional(),
15
+ guidelines: z
16
+ .string()
17
+ .optional()
18
+ .describe("Plain text guidelines shown to editors"),
20
19
  is_required: z.boolean().optional(),
21
20
  is_non_localizable: z.boolean().optional(),
22
21
  };
@@ -93,7 +92,7 @@ const assetElementSchema = {
93
92
  const customElementSchema = {
94
93
  type: z.literal("custom"),
95
94
  ...namedElementSchema,
96
- source_url: z.string(),
95
+ source_url: z.url(),
97
96
  json_parameters: z.string().optional(),
98
97
  allowed_elements: z.array(referenceObjectSchema).optional(),
99
98
  };
@@ -105,7 +104,9 @@ const dateTimeElementSchema = {
105
104
  const guidelinesElementSchema = {
106
105
  type: z.literal("guidelines"),
107
106
  ...baseElementSchema,
108
- guidelines: z.string(),
107
+ guidelines: z
108
+ .string()
109
+ .describe("HTML content for guidelines element. Must be valid HTML."),
109
110
  };
110
111
  const modularContentElementSchema = {
111
112
  type: z.literal("modular_content"),
@@ -292,14 +293,12 @@ export const contentGroupSchema = z.object({
292
293
  external_id: z.string().optional(),
293
294
  codename: z.string().optional(),
294
295
  });
295
- // Define a union type for snippet elements (excluding url_slug and snippet elements)
296
296
  export const snippetElementSchema = z.discriminatedUnion("type", [
297
297
  z.object(assetElementSchema),
298
298
  z.object(customElementSchema),
299
299
  z.object(dateTimeElementSchema),
300
300
  z.object(guidelinesElementSchema),
301
301
  z.object(modularContentElementSchema),
302
- z.object(subpagesElementSchema),
303
302
  z.object(multipleChoiceElementSchema),
304
303
  z.object(numberElementSchema),
305
304
  z.object(richTextElementSchema),
@@ -0,0 +1,41 @@
1
+ import { z } from "zod";
2
+ import { allowedBlockSchema, allowedFormattingSchema, allowedTableBlockSchema, allowedTableFormattingSchema, allowedTableTextBlockSchema, allowedTextBlockSchema, arrayDefaultSchema, countLimitSchema, numberDefaultSchema, optionSchema, regexValidationSchema, stringDefaultSchema, textLengthLimitSchema, } from "../contentTypeAndSnippetSchemas.js";
3
+ import { referenceObjectSchema } from "../referenceObjectSchema.js";
4
+ export const moveOperationSchema = z.object({
5
+ op: z.literal("move"),
6
+ path: z.string().describe("Path to object (format: id:{uuid})"),
7
+ before: referenceObjectSchema.optional(),
8
+ after: referenceObjectSchema.optional(),
9
+ });
10
+ export const removeOperationSchema = z.object({
11
+ op: z.literal("remove"),
12
+ path: z.string().describe("Path to item to remove (format: id:{uuid})"),
13
+ });
14
+ export const sharedAddIntoValueSchemas = [
15
+ optionSchema,
16
+ referenceObjectSchema,
17
+ allowedBlockSchema,
18
+ allowedFormattingSchema,
19
+ allowedTextBlockSchema,
20
+ allowedTableBlockSchema,
21
+ allowedTableFormattingSchema,
22
+ allowedTableTextBlockSchema,
23
+ z.string(),
24
+ z.number(),
25
+ z.boolean(),
26
+ z.null(),
27
+ z.any(),
28
+ ];
29
+ export const sharedReplaceValueSchemas = [
30
+ regexValidationSchema,
31
+ textLengthLimitSchema,
32
+ countLimitSchema,
33
+ arrayDefaultSchema,
34
+ stringDefaultSchema,
35
+ numberDefaultSchema,
36
+ z.string(),
37
+ z.number(),
38
+ z.boolean(),
39
+ z.null(),
40
+ z.any(),
41
+ ];
@@ -1,66 +1,24 @@
1
- // Patch operation schemas for content type modifications
2
- // Based on: https://kontent.ai/learn/docs/apis/openapi/management-api-v2/#operation/modify-a-content-type
3
1
  import { z } from "zod";
4
- import { allowedBlockSchema, allowedFormattingSchema, allowedTableBlockSchema, allowedTableFormattingSchema, allowedTableTextBlockSchema, allowedTextBlockSchema, arrayDefaultSchema, contentGroupSchema, countLimitSchema, dependsOnSchema, elementSchema, numberDefaultSchema, optionSchema, referenceObjectSchema, regexValidationSchema, stringDefaultSchema, textLengthLimitSchema, } from "../contentTypeSchemas.js";
5
- // Move operation - Move elements within content type
6
- const moveOperationSchema = z.object({
7
- op: z.literal("move"),
8
- path: z.string().describe("Path to object (format: id:{uuid})"),
9
- before: referenceObjectSchema.optional(),
10
- after: referenceObjectSchema.optional(),
11
- });
12
- // AddInto operation - Add new elements to content type
2
+ import { contentGroupSchema, dependsOnSchema, elementSchema, } from "../contentTypeAndSnippetSchemas.js";
3
+ import { moveOperationSchema, removeOperationSchema, sharedAddIntoValueSchemas, sharedReplaceValueSchemas, } from "./baseTypeAndSnippetPatchSchemas.js";
13
4
  const addIntoOperationSchema = z.object({
14
5
  op: z.literal("addInto"),
15
6
  path: z.string().describe("Path where to add item (format: id:{uuid})"),
16
7
  value: z.union([
17
8
  elementSchema,
18
- optionSchema,
19
9
  contentGroupSchema,
20
- referenceObjectSchema,
21
- allowedBlockSchema,
22
- allowedFormattingSchema,
23
- allowedTextBlockSchema,
24
- allowedTableBlockSchema,
25
- allowedTableFormattingSchema,
26
- allowedTableTextBlockSchema,
27
- z.string(),
28
- z.number(),
29
- z.boolean(),
30
- z.null(),
31
- z.any(),
10
+ ...sharedAddIntoValueSchemas,
32
11
  ]),
33
12
  });
34
- // Remove operation - Remove elements from content type
35
- const removeOperationSchema = z.object({
36
- op: z.literal("remove"),
37
- path: z.string().describe("Path to item to remove (format: id:{uuid})"),
38
- });
39
- // Replace operation - Replace/update existing elements in content type
40
13
  const replaceOperationSchema = z.object({
41
14
  op: z.literal("replace"),
42
15
  path: z.string().describe("Path to property to replace (format: id:{uuid})"),
43
- value: z.union([
44
- dependsOnSchema,
45
- regexValidationSchema,
46
- textLengthLimitSchema,
47
- countLimitSchema,
48
- arrayDefaultSchema,
49
- stringDefaultSchema,
50
- numberDefaultSchema,
51
- z.string(),
52
- z.number(),
53
- z.boolean(),
54
- z.null(),
55
- z.any(),
56
- ]),
16
+ value: z.union([dependsOnSchema, ...sharedReplaceValueSchemas]),
57
17
  });
58
- // Union type for all patch operations
59
18
  export const patchOperationSchema = z.discriminatedUnion("op", [
60
19
  moveOperationSchema,
61
20
  addIntoOperationSchema,
62
21
  removeOperationSchema,
63
22
  replaceOperationSchema,
64
23
  ]);
65
- // Schema for array of patch operations
66
24
  export const patchOperationsSchema = z.array(patchOperationSchema).min(1);
@@ -0,0 +1,22 @@
1
+ import { z } from "zod";
2
+ import { snippetElementSchema } from "../contentTypeAndSnippetSchemas.js";
3
+ import { moveOperationSchema, removeOperationSchema, sharedAddIntoValueSchemas, sharedReplaceValueSchemas, } from "./baseTypeAndSnippetPatchSchemas.js";
4
+ const addIntoOperationSchema = z.object({
5
+ op: z.literal("addInto"),
6
+ path: z.string().describe("Path where to add item (format: id:{uuid})"),
7
+ value: z.union([snippetElementSchema, ...sharedAddIntoValueSchemas]),
8
+ });
9
+ const replaceOperationSchema = z.object({
10
+ op: z.literal("replace"),
11
+ path: z.string().describe("Path to property to replace (format: id:{uuid})"),
12
+ value: z.union(sharedReplaceValueSchemas),
13
+ });
14
+ export const snippetPatchOperationSchema = z.discriminatedUnion("op", [
15
+ moveOperationSchema,
16
+ addIntoOperationSchema,
17
+ removeOperationSchema,
18
+ replaceOperationSchema,
19
+ ]);
20
+ export const snippetPatchOperationsSchema = z
21
+ .array(snippetPatchOperationSchema)
22
+ .min(1);
@@ -0,0 +1,67 @@
1
+ import { z } from "zod";
2
+ import { referenceObjectSchema } from "../referenceObjectSchema.js";
3
+ const taxonomyTermValueSchema = z.object({
4
+ name: z.string(),
5
+ codename: z.string().optional(),
6
+ external_id: z.string().optional(),
7
+ terms: z.lazy(() => z.array(taxonomyTermValueSchema)).optional(),
8
+ });
9
+ const addIntoBaseSchema = {
10
+ op: z.literal("addInto"),
11
+ reference: referenceObjectSchema
12
+ .optional()
13
+ .describe("Parent term reference. Omit to add at root level of taxonomy group."),
14
+ value: taxonomyTermValueSchema,
15
+ };
16
+ const addIntoBeforeOperationSchema = z.object({
17
+ ...addIntoBaseSchema,
18
+ before: referenceObjectSchema,
19
+ });
20
+ const addIntoAfterOperationSchema = z.object({
21
+ ...addIntoBaseSchema,
22
+ after: referenceObjectSchema,
23
+ });
24
+ const addIntoDefaultOperationSchema = z.object(addIntoBaseSchema);
25
+ const moveBaseSchema = {
26
+ op: z.literal("move"),
27
+ reference: referenceObjectSchema,
28
+ };
29
+ const moveBeforeOperationSchema = z.object({
30
+ ...moveBaseSchema,
31
+ before: referenceObjectSchema,
32
+ });
33
+ const moveAfterOperationSchema = z.object({
34
+ ...moveBaseSchema,
35
+ after: referenceObjectSchema,
36
+ });
37
+ const moveUnderOperationSchema = z.object({
38
+ ...moveBaseSchema,
39
+ under: referenceObjectSchema.describe("Move as child of this term (tree nesting)"),
40
+ });
41
+ const removeOperationSchema = z.object({
42
+ op: z.literal("remove"),
43
+ reference: referenceObjectSchema,
44
+ });
45
+ const replaceOperationSchema = z.object({
46
+ op: z.literal("replace"),
47
+ reference: referenceObjectSchema
48
+ .optional()
49
+ .describe("Term reference. Omit when modifying group-level properties (name, codename). Required when modifying specific term."),
50
+ property_name: z.enum(["name", "codename", "terms"]),
51
+ value: z
52
+ .union([z.string(), z.array(taxonomyTermValueSchema)])
53
+ .describe("New value. String for name/codename, array for terms."),
54
+ });
55
+ export const taxonomyPatchOperationSchema = z.union([
56
+ addIntoBeforeOperationSchema,
57
+ addIntoAfterOperationSchema,
58
+ addIntoDefaultOperationSchema,
59
+ moveBeforeOperationSchema,
60
+ moveAfterOperationSchema,
61
+ moveUnderOperationSchema,
62
+ removeOperationSchema,
63
+ replaceOperationSchema,
64
+ ]);
65
+ export const taxonomyPatchOperationsSchema = z
66
+ .array(taxonomyPatchOperationSchema)
67
+ .min(1);
@@ -0,0 +1,30 @@
1
+ import { z } from "zod";
2
+ import { referenceObjectSchema } from "./referenceObjectSchema.js";
3
+ const nameReplaceOperationSchema = z.object({
4
+ op: z.literal("replace"),
5
+ property_name: z.literal("name"),
6
+ value: z.string(),
7
+ });
8
+ const codenameReplaceOperationSchema = z.object({
9
+ op: z.literal("replace"),
10
+ property_name: z.literal("codename"),
11
+ value: z.string(),
12
+ });
13
+ const collectionsReplaceOperationSchema = z.object({
14
+ op: z.literal("replace"),
15
+ property_name: z.literal("collections"),
16
+ value: z.array(referenceObjectSchema),
17
+ });
18
+ export const spacePatchOperationSchema = z.discriminatedUnion("property_name", [
19
+ nameReplaceOperationSchema,
20
+ codenameReplaceOperationSchema,
21
+ collectionsReplaceOperationSchema,
22
+ ]);
23
+ export const spacePatchOperationsSchema = z
24
+ .array(spacePatchOperationSchema)
25
+ .min(1);
26
+ export const addSpaceSchema = z.object({
27
+ name: z.string(),
28
+ codename: z.string().optional(),
29
+ collections: z.array(referenceObjectSchema).optional(),
30
+ });
package/build/server.js CHANGED
@@ -4,12 +4,16 @@ import { registerTool as registerAddContentItemMapi } from "./tools/add-content-
4
4
  import { registerTool as registerAddContentTypeMapi } from "./tools/add-content-type-mapi.js";
5
5
  import { registerTool as registerAddContentTypeSnippetMapi } from "./tools/add-content-type-snippet-mapi.js";
6
6
  import { registerTool as registerAddLanguageMapi } from "./tools/add-language-mapi.js";
7
+ import { registerTool as registerAddSpaceMapi } from "./tools/add-space-mapi.js";
7
8
  import { registerTool as registerAddTaxonomyGroupMapi } from "./tools/add-taxonomy-group-mapi.js";
8
9
  import { registerTool as registerChangeVariantWorkflowStepMapi } from "./tools/change-variant-workflow-step-mapi.js";
9
10
  import { registerTool as registerCreateVariantVersionMapi } from "./tools/create-variant-version-mapi.js";
10
11
  import { registerTool as registerDeleteContentItemMapi } from "./tools/delete-content-item-mapi.js";
11
12
  import { registerTool as registerDeleteContentTypeMapi } from "./tools/delete-content-type-mapi.js";
12
13
  import { registerTool as registerDeleteLanguageVariantMapi } from "./tools/delete-language-variant-mapi.js";
14
+ import { registerTool as registerDeleteSpaceMapi } from "./tools/delete-space-mapi.js";
15
+ import { registerTool as registerDeleteTaxonomyGroupMapi } from "./tools/delete-taxonomy-group-mapi.js";
16
+ import { registerTool as registerDeleteTypeSnippetMapi } from "./tools/delete-type-snippet-mapi.js";
13
17
  import { registerTool as registerFilterVariantsMapi } from "./tools/filter-variants-mapi.js";
14
18
  import { registerTool as registerGetAssetMapi } from "./tools/get-asset-mapi.js";
15
19
  import { registerTool as registerGetItemMapi } from "./tools/get-item-mapi.js";
@@ -19,6 +23,7 @@ import { registerTool as registerGetPublishedVariantMapi } from "./tools/get-pub
19
23
  import { registerTool as registerGetTaxonomyGroupMapi } from "./tools/get-taxonomy-group-mapi.js";
20
24
  import { registerTool as registerGetTypeMapi } from "./tools/get-type-mapi.js";
21
25
  import { registerTool as registerGetTypeSnippetMapi } from "./tools/get-type-snippet-mapi.js";
26
+ import { registerTool as registerListAssetFoldersMapi } from "./tools/list-asset-folders-mapi.js";
22
27
  import { registerTool as registerListAssetsMapi } from "./tools/list-assets-mapi.js";
23
28
  import { registerTool as registerListCollectionsMapi } from "./tools/list-collections-mapi.js";
24
29
  import { registerTool as registerListContentTypeSnippetsMapi } from "./tools/list-content-type-snippets-mapi.js";
@@ -32,12 +37,17 @@ import { registerTool as registerListVariantsItemMapi } from "./tools/list-varia
32
37
  import { registerTool as registerListVariantsSpaceMapi } from "./tools/list-variants-space-mapi.js";
33
38
  import { registerTool as registerListVariantsTypeMapi } from "./tools/list-variants-type-mapi.js";
34
39
  import { registerTool as registerListWorkflowsMapi } from "./tools/list-workflows-mapi.js";
40
+ import { registerTool as registerPatchAssetFoldersMapi } from "./tools/patch-asset-folders-mapi.js";
35
41
  import { registerTool as registerPatchCollectionsMapi } from "./tools/patch-collections-mapi.js";
36
42
  import { registerTool as registerPatchContentTypeMapi } from "./tools/patch-content-type-mapi.js";
37
43
  import { registerTool as registerPatchLanguageMapi } from "./tools/patch-language-mapi.js";
44
+ import { registerTool as registerPatchSpaceMapi } from "./tools/patch-space-mapi.js";
45
+ import { registerTool as registerPatchTaxonomyGroupMapi } from "./tools/patch-taxonomy-group-mapi.js";
46
+ import { registerTool as registerPatchTypeSnippetMapi } from "./tools/patch-type-snippet-mapi.js";
38
47
  import { registerTool as registerPublishVariantMapi } from "./tools/publish-variant-mapi.js";
39
48
  import { registerTool as registerSearchVariantsMapi } from "./tools/search-variants-mapi.js";
40
49
  import { registerTool as registerUnpublishVariantMapi } from "./tools/unpublish-variant-mapi.js";
50
+ import { registerTool as registerUpdateAssetMapi } from "./tools/update-asset-mapi.js";
41
51
  import { registerTool as registerUpdateContentItemMapi } from "./tools/update-content-item-mapi.js";
42
52
  import { registerTool as registerUpsertLanguageVariantMapi } from "./tools/upsert-language-variant-mapi.js";
43
53
  // Create server instance
@@ -65,16 +75,26 @@ export const createServer = () => {
65
75
  registerListCollectionsMapi(server);
66
76
  registerPatchCollectionsMapi(server);
67
77
  registerListSpacesMapi(server);
78
+ registerAddSpaceMapi(server);
79
+ registerPatchSpaceMapi(server);
80
+ registerDeleteSpaceMapi(server);
68
81
  registerGetAssetMapi(server);
69
82
  registerListAssetsMapi(server);
83
+ registerUpdateAssetMapi(server);
84
+ registerListAssetFoldersMapi(server);
85
+ registerPatchAssetFoldersMapi(server);
70
86
  registerAddContentTypeMapi(server);
71
87
  registerPatchContentTypeMapi(server);
72
88
  registerAddContentTypeSnippetMapi(server);
73
89
  registerGetTypeSnippetMapi(server);
74
90
  registerListContentTypeSnippetsMapi(server);
91
+ registerPatchTypeSnippetMapi(server);
92
+ registerDeleteTypeSnippetMapi(server);
75
93
  registerAddTaxonomyGroupMapi(server);
76
94
  registerListTaxonomyGroupsMapi(server);
77
95
  registerGetTaxonomyGroupMapi(server);
96
+ registerPatchTaxonomyGroupMapi(server);
97
+ registerDeleteTaxonomyGroupMapi(server);
78
98
  registerAddContentItemMapi(server);
79
99
  registerUpdateContentItemMapi(server);
80
100
  registerDeleteContentItemMapi(server);
@@ -156,6 +156,6 @@ export function initializeApplicationInsights() {
156
156
  appInsights.defaultClient.addTelemetryProcessor(createTelemetryProcessor());
157
157
  }
158
158
  catch (error) {
159
- console.log("Failed to initialize Application Insights:", error);
159
+ console.error("Failed to initialize Application Insights:", error);
160
160
  }
161
161
  }
@@ -1,6 +1,6 @@
1
1
  import { z } from "zod";
2
2
  import { createMapiClient } from "../clients/kontentClients.js";
3
- import { contentGroupSchema, elementSchema, } from "../schemas/contentTypeSchemas.js";
3
+ import { contentGroupSchema, elementSchema, } from "../schemas/contentTypeAndSnippetSchemas.js";
4
4
  import { handleMcpToolError } from "../utils/errorHandler.js";
5
5
  import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
6
6
  export const registerTool = (server) => {
@@ -1,6 +1,6 @@
1
1
  import { z } from "zod";
2
2
  import { createMapiClient } from "../clients/kontentClients.js";
3
- import { snippetElementSchema } from "../schemas/contentTypeSchemas.js";
3
+ import { snippetElementSchema } from "../schemas/contentTypeAndSnippetSchemas.js";
4
4
  import { handleMcpToolError } from "../utils/errorHandler.js";
5
5
  import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
6
6
  export const registerTool = (server) => {
@@ -0,0 +1,23 @@
1
+ import { createMapiClient } from "../clients/kontentClients.js";
2
+ import { addSpaceSchema } from "../schemas/spaceSchemas.js";
3
+ import { handleMcpToolError } from "../utils/errorHandler.js";
4
+ import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
5
+ export const registerTool = (server) => {
6
+ server.tool("add-space-mapi", "Add Kontent.ai space", addSpaceSchema.shape, async ({ name, codename, collections }, { authInfo: { token, clientId } = {} }) => {
7
+ const client = createMapiClient(clientId, token);
8
+ try {
9
+ const response = await client
10
+ .addSpace()
11
+ .withData({
12
+ name,
13
+ codename,
14
+ collections,
15
+ })
16
+ .toPromise();
17
+ return createMcpToolSuccessResponse(response.rawData);
18
+ }
19
+ catch (error) {
20
+ return handleMcpToolError(error, "Space Creation");
21
+ }
22
+ });
23
+ };
@@ -0,0 +1,53 @@
1
+ export const pathBasedPatchGuide = `
2
+ # Patch Guide: Content Types & Snippets
3
+
4
+ ## Addressing
5
+ Use JSON Pointer 'path' property with id:{uuid} format.
6
+
7
+ ## Path Formats
8
+ - Element: /elements/id:{uuid}
9
+ - Element property: /elements/id:{uuid}/name
10
+ - Option: /elements/id:{uuid}/options/id:{uuid}
11
+ - Content group: /content_groups/id:{uuid}
12
+ - Array item: /elements/id:{uuid}/allowed_content_types/id:{uuid}
13
+
14
+ ## Operations
15
+
16
+ **move** - Reorder elements/options/groups
17
+ \`\`\`json
18
+ { "op": "move", "path": "/elements/id:{uuid}", "before": { "id": "{uuid}" } }
19
+ { "op": "move", "path": "/elements/id:{uuid}", "after": { "id": "{uuid}" } }
20
+ \`\`\`
21
+
22
+ **addInto** - Add to arrays (elements, options, allowed_blocks, etc.)
23
+ \`\`\`json
24
+ { "op": "addInto", "path": "/elements", "value": { "name": "Title", "type": "text", ... } }
25
+ { "op": "addInto", "path": "/elements/id:{uuid}/allowed_content_types", "value": { "id": "{uuid}" } }
26
+ \`\`\`
27
+
28
+ **remove** - Delete items
29
+ \`\`\`json
30
+ { "op": "remove", "path": "/elements/id:{uuid}" }
31
+ { "op": "remove", "path": "/elements/id:{uuid}/allowed_content_types/id:{uuid}" }
32
+ \`\`\`
33
+
34
+ **replace** - Update primitives/objects
35
+ \`\`\`json
36
+ { "op": "replace", "path": "/elements/id:{uuid}/name", "value": "New Name" }
37
+ { "op": "replace", "path": "/elements/id:{uuid}/maximum_text_length", "value": { "value": 100, "applies_to": "characters" } }
38
+ \`\`\`
39
+
40
+ ## Rules
41
+ - Use addInto/remove for arrays, replace for primitives/objects
42
+ - external_id and type cannot be modified after creation
43
+ - Empty arrays enable all options (allowed_blocks, allowed_formatting, etc.)
44
+ - 'unstyled' must be first when adding allowed_formatting
45
+
46
+ ## Content Type Specifics
47
+ - Only one url_slug element allowed per content type
48
+ - To remove content groups: set ALL elements' content_group to null AND remove ALL groups in one request
49
+ - URL slug with snippet: add snippet element first, then url_slug with depends_on reference
50
+
51
+ ## Snippet Specifics
52
+ - Cannot contain: content_groups, snippet, or url_slug elements
53
+ `;
@@ -0,0 +1,42 @@
1
+ export const propertyBasedPatchGuide = `
2
+ # Patch Guide: Spaces & Languages
3
+
4
+ ## Addressing
5
+ Use 'property_name' to specify which property to update. Only 'replace' operation is supported.
6
+
7
+ ## Space Operations
8
+
9
+ **replace** - Update space properties
10
+ \`\`\`json
11
+ { "op": "replace", "property_name": "name", "value": "New Space Name" }
12
+ { "op": "replace", "property_name": "codename", "value": "new_codename" }
13
+ { "op": "replace", "property_name": "collections", "value": [{ "id": "{uuid}" }, { "codename": "collection" }] }
14
+ \`\`\`
15
+
16
+ Available properties: name, codename, collections
17
+
18
+ ## Language Operations
19
+
20
+ **replace** - Update language properties
21
+ \`\`\`json
22
+ { "op": "replace", "property_name": "name", "value": "New Language Name" }
23
+ { "op": "replace", "property_name": "codename", "value": "new_codename" }
24
+ { "op": "replace", "property_name": "is_active", "value": true }
25
+ { "op": "replace", "property_name": "fallback_language", "value": { "codename": "en-US" } }
26
+ \`\`\`
27
+
28
+ Available properties: name, codename, is_active, fallback_language
29
+
30
+ ## Critical Rule for Languages
31
+ If a language is deactivated, you must activate it first before making other changes:
32
+ \`\`\`json
33
+ [
34
+ { "op": "replace", "property_name": "is_active", "value": true },
35
+ { "op": "replace", "property_name": "name", "value": "New Name" }
36
+ ]
37
+ \`\`\`
38
+
39
+ ## General Rules
40
+ - external_id cannot be modified after creation
41
+ - Operations are applied in order
42
+ `;
@@ -0,0 +1,86 @@
1
+ export const referenceBasedPatchGuide = `
2
+ # Patch Guide: Taxonomy, Collections & Asset Folders
3
+
4
+ ## Addressing
5
+ Use 'reference' objects: { id: "{uuid}" } or { codename: "codename" }
6
+
7
+ ## Taxonomy Group Operations
8
+
9
+ **addInto** - Add terms
10
+ \`\`\`json
11
+ { "op": "addInto", "value": { "name": "Term" } }
12
+ { "op": "addInto", "reference": { "id": "{parent-uuid}" }, "value": { "name": "Child Term" } }
13
+ { "op": "addInto", "value": { "name": "Term" }, "before": { "id": "{uuid}" } }
14
+ { "op": "addInto", "value": { "name": "Term" }, "after": { "id": "{uuid}" } }
15
+ \`\`\`
16
+
17
+ **move** - Reorder or nest terms (before/after/under are mutually exclusive)
18
+ \`\`\`json
19
+ { "op": "move", "reference": { "id": "{uuid}" }, "before": { "id": "{uuid}" } }
20
+ { "op": "move", "reference": { "id": "{uuid}" }, "after": { "id": "{uuid}" } }
21
+ { "op": "move", "reference": { "id": "{uuid}" }, "under": { "id": "{parent-uuid}" } }
22
+ \`\`\`
23
+
24
+ **remove** - Delete terms
25
+ \`\`\`json
26
+ { "op": "remove", "reference": { "id": "{uuid}" } }
27
+ \`\`\`
28
+
29
+ **replace** - Update properties
30
+ \`\`\`json
31
+ { "op": "replace", "property_name": "name", "value": "New Group Name" }
32
+ { "op": "replace", "reference": { "id": "{uuid}" }, "property_name": "name", "value": "New Term Name" }
33
+ { "op": "replace", "reference": { "id": "{uuid}" }, "property_name": "terms", "value": [] }
34
+ \`\`\`
35
+
36
+ ## Collection Operations
37
+
38
+ **addInto** - Add collections
39
+ \`\`\`json
40
+ { "op": "addInto", "value": { "name": "Collection", "codename": "collection" } }
41
+ { "op": "addInto", "value": { "name": "Collection" }, "before": { "id": "{uuid}" } }
42
+ { "op": "addInto", "value": { "name": "Collection" }, "after": { "id": "{uuid}" } }
43
+ \`\`\`
44
+
45
+ **move** - Reorder collections
46
+ \`\`\`json
47
+ { "op": "move", "reference": { "id": "{uuid}" }, "before": { "id": "{uuid}" } }
48
+ { "op": "move", "reference": { "id": "{uuid}" }, "after": { "id": "{uuid}" } }
49
+ \`\`\`
50
+
51
+ **remove** - Delete empty collections only
52
+ \`\`\`json
53
+ { "op": "remove", "reference": { "id": "{uuid}" } }
54
+ \`\`\`
55
+
56
+ **replace** - Rename collections
57
+ \`\`\`json
58
+ { "op": "replace", "reference": { "id": "{uuid}" }, "property_name": "name", "value": "New Name" }
59
+ \`\`\`
60
+
61
+ ## Asset Folder Operations
62
+
63
+ **addInto** - Add folders
64
+ \`\`\`json
65
+ { "op": "addInto", "value": { "name": "Folder" } }
66
+ { "op": "addInto", "reference": { "id": "{parent-uuid}" }, "value": { "name": "Subfolder" } }
67
+ { "op": "addInto", "value": { "name": "Folder" }, "before": { "id": "{uuid}" } }
68
+ \`\`\`
69
+
70
+ **rename** - Rename folders (not 'replace')
71
+ \`\`\`json
72
+ { "op": "rename", "reference": { "id": "{uuid}" }, "value": "New Folder Name" }
73
+ \`\`\`
74
+
75
+ **remove** - Delete folders
76
+ \`\`\`json
77
+ { "op": "remove", "reference": { "id": "{uuid}" } }
78
+ \`\`\`
79
+
80
+ Note: Asset folders do not support 'move' operation.
81
+
82
+ ## General Rules
83
+ - Always fetch the entity first to get current IDs
84
+ - external_id cannot be modified after creation
85
+ - Operations are applied in order
86
+ `;
@@ -0,0 +1,20 @@
1
+ import { z } from "zod";
2
+ import { createMapiClient } from "../clients/kontentClients.js";
3
+ import { handleMcpToolError } from "../utils/errorHandler.js";
4
+ import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
5
+ export const registerTool = (server) => {
6
+ server.tool("delete-space-mapi", "Delete Kontent.ai space by ID", {
7
+ id: z.guid(),
8
+ }, async ({ id }, { authInfo: { token, clientId } = {} }) => {
9
+ const client = createMapiClient(clientId, token);
10
+ try {
11
+ await client.deleteSpace().bySpaceId(id).toPromise();
12
+ return createMcpToolSuccessResponse({
13
+ message: `Space '${id}' deleted successfully`,
14
+ });
15
+ }
16
+ catch (error) {
17
+ return handleMcpToolError(error, "Space Deletion");
18
+ }
19
+ });
20
+ };
@@ -0,0 +1,20 @@
1
+ import { z } from "zod";
2
+ import { createMapiClient } from "../clients/kontentClients.js";
3
+ import { handleMcpToolError } from "../utils/errorHandler.js";
4
+ import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
5
+ export const registerTool = (server) => {
6
+ server.tool("delete-taxonomy-group-mapi", "Delete Kontent.ai taxonomy group by ID", {
7
+ id: z.guid(),
8
+ }, async ({ id }, { authInfo: { token, clientId } = {} }) => {
9
+ const client = createMapiClient(clientId, token);
10
+ try {
11
+ await client.deleteTaxonomy().byTaxonomyId(id).toPromise();
12
+ return createMcpToolSuccessResponse({
13
+ message: `Taxonomy group '${id}' deleted successfully`,
14
+ });
15
+ }
16
+ catch (error) {
17
+ return handleMcpToolError(error, "Taxonomy Group Deletion");
18
+ }
19
+ });
20
+ };
@@ -0,0 +1,23 @@
1
+ import { z } from "zod";
2
+ import { createMapiClient } from "../clients/kontentClients.js";
3
+ import { handleMcpToolError } from "../utils/errorHandler.js";
4
+ import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
5
+ export const registerTool = (server) => {
6
+ server.tool("delete-type-snippet-mapi", "Delete Kontent.ai content type snippet by codename", {
7
+ codename: z.string(),
8
+ }, async ({ codename }, { authInfo: { token, clientId } = {} }) => {
9
+ const client = createMapiClient(clientId, token);
10
+ try {
11
+ await client
12
+ .deleteContentTypeSnippet()
13
+ .byTypeCodename(codename)
14
+ .toPromise();
15
+ return createMcpToolSuccessResponse({
16
+ message: `Content type snippet '${codename}' deleted successfully`,
17
+ });
18
+ }
19
+ catch (error) {
20
+ return handleMcpToolError(error, "Content Type Snippet Deletion");
21
+ }
22
+ });
23
+ };
@@ -1,9 +1,37 @@
1
+ import { z } from "zod";
1
2
  import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
2
- import { patchOperationsGuide } from "./context/patch-operations-guide.js";
3
+ import { pathBasedPatchGuide } from "./context/patch-guide-path-based.js";
4
+ import { propertyBasedPatchGuide } from "./context/patch-guide-property-based.js";
5
+ import { referenceBasedPatchGuide } from "./context/patch-guide-reference-based.js";
6
+ const entityTypeSchema = z.enum([
7
+ "content-type",
8
+ "snippet",
9
+ "taxonomy",
10
+ "collection",
11
+ "asset-folder",
12
+ "space",
13
+ "language",
14
+ ]);
15
+ const getGuideForEntity = (entityType) => {
16
+ switch (entityType) {
17
+ case "content-type":
18
+ case "snippet":
19
+ return pathBasedPatchGuide;
20
+ case "taxonomy":
21
+ case "collection":
22
+ case "asset-folder":
23
+ return referenceBasedPatchGuide;
24
+ case "space":
25
+ case "language":
26
+ return propertyBasedPatchGuide;
27
+ }
28
+ };
3
29
  export const registerTool = (server) => {
4
- server.tool("get-patch-guide", "REQUIRED before any patch operation. Get JSON Patch operations guide for Kontent.ai Management API.", {}, async () => {
30
+ server.tool("get-patch-guide", "REQUIRED before any patch operation. Get patch operations guide for Kontent.ai Management API.", {
31
+ entityType: entityTypeSchema.describe("Entity type to get patch guide for: content-type, snippet, taxonomy, collection, asset-folder, space, language"),
32
+ }, async ({ entityType }) => {
5
33
  try {
6
- return createMcpToolSuccessResponse(patchOperationsGuide);
34
+ return createMcpToolSuccessResponse(getGuideForEntity(entityType));
7
35
  }
8
36
  catch (error) {
9
37
  throw new Error(`Failed to read patch guide: ${error instanceof Error ? error.message : "Unknown error"}`);
@@ -3,8 +3,8 @@ import { createMapiClient } from "../clients/kontentClients.js";
3
3
  import { handleMcpToolError } from "../utils/errorHandler.js";
4
4
  import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
5
5
  export const registerTool = (server) => {
6
- server.tool("get-taxonomy-group-mapi", "Get Kontent.ai taxonomy group. Taxonomies provide hierarchical categorization for organizing and tagging content.", {
7
- id: z.string().describe("Taxonomy group ID"),
6
+ server.tool("get-taxonomy-group-mapi", "Get Kontent.ai taxonomy group. Taxonomy groups are hierarchical with tree-structured terms that can be nested to any depth for flexible content categorization.", {
7
+ id: z.guid(),
8
8
  }, async ({ id }, { authInfo: { token, clientId } = {} }) => {
9
9
  const client = createMapiClient(clientId, token);
10
10
  try {
@@ -0,0 +1,15 @@
1
+ import { createMapiClient } from "../clients/kontentClients.js";
2
+ import { handleMcpToolError } from "../utils/errorHandler.js";
3
+ import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
4
+ export const registerTool = (server) => {
5
+ server.tool("list-asset-folders-mapi", "List all Kontent.ai asset folders", {}, async (_params, { authInfo: { token, clientId } = {} }) => {
6
+ const client = createMapiClient(clientId, token);
7
+ try {
8
+ const response = await client.listAssetFolders().toPromise();
9
+ return createMcpToolSuccessResponse(response.rawData);
10
+ }
11
+ catch (error) {
12
+ return handleMcpToolError(error, "Asset Folders Listing");
13
+ }
14
+ });
15
+ };
@@ -2,7 +2,7 @@ import { createMapiClient } from "../clients/kontentClients.js";
2
2
  import { handleMcpToolError } from "../utils/errorHandler.js";
3
3
  import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
4
4
  export const registerTool = (server) => {
5
- server.tool("list-spaces-mapi", "Get all Kontent.ai spaces from Management API", {}, async (_, { authInfo: { token, clientId } = {} }) => {
5
+ server.tool("list-spaces-mapi", "List all Kontent.ai spaces. Spaces provide channel-specific context for managing multiple websites/channels. Each space has its own domain and preview URLs; collections connect to spaces to organize content per channel.", {}, async (_, { authInfo: { token, clientId } = {} }) => {
6
6
  const client = createMapiClient(clientId, token);
7
7
  try {
8
8
  const response = await client.listSpaces().toPromise();
@@ -3,7 +3,7 @@ import { listTaxonomyGroupsSchema } from "../schemas/listSchemas.js";
3
3
  import { handleMcpToolError } from "../utils/errorHandler.js";
4
4
  import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
5
5
  export const registerTool = (server) => {
6
- server.tool("list-taxonomy-groups-mapi", "Get all Kontent.ai taxonomy groups (paginated). Taxonomies provide hierarchical categorization for organizing and tagging content.", listTaxonomyGroupsSchema.shape, async ({ continuation_token }, { authInfo: { token, clientId } = {} }) => {
6
+ server.tool("list-taxonomy-groups-mapi", "List all Kontent.ai taxonomy groups (paginated). Taxonomy groups are hierarchical with tree-structured terms that can be nested to any depth for flexible content categorization.", listTaxonomyGroupsSchema.shape, async ({ continuation_token }, { authInfo: { token, clientId } = {} }) => {
7
7
  const client = createMapiClient(clientId, token);
8
8
  try {
9
9
  const query = client.listTaxonomies();
@@ -0,0 +1,25 @@
1
+ import { createMapiClient } from "../clients/kontentClients.js";
2
+ import { assetFolderPatchOperationsSchema } from "../schemas/assetFolderSchemas.js";
3
+ import { handleMcpToolError } from "../utils/errorHandler.js";
4
+ import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
5
+ export const registerTool = (server) => {
6
+ server.tool("patch-asset-folders-mapi", "Modify Kontent.ai asset folders using patch operations (addInto, rename, remove). Call get-patch-guide first for operations reference.", {
7
+ operations: assetFolderPatchOperationsSchema,
8
+ }, async ({ operations }, { authInfo: { token, clientId } = {} }) => {
9
+ const client = createMapiClient(clientId, token);
10
+ try {
11
+ const response = await client
12
+ .modifyAssetFolders()
13
+ .withData(operations)
14
+ .toPromise();
15
+ return createMcpToolSuccessResponse({
16
+ message: `Asset folders modified with ${operations.length} operation(s)`,
17
+ folders: response.rawData,
18
+ appliedOperations: operations,
19
+ });
20
+ }
21
+ catch (error) {
22
+ return handleMcpToolError(error, "Asset Folders Modification");
23
+ }
24
+ });
25
+ };
@@ -4,20 +4,24 @@ import { patchOperationsSchema } from "../schemas/patchSchemas/contentTypePatchS
4
4
  import { handleMcpToolError } from "../utils/errorHandler.js";
5
5
  import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
6
6
  export const registerTool = (server) => {
7
- server.tool("patch-content-type-mapi", "Update Kontent.ai content type using JSON Patch. Call get-patch-guide first for operations reference.", {
8
- codename: z.string().describe("Content type codename"),
9
- operations: patchOperationsSchema.describe("Patch operations array. CRITICAL: Always call get-type-mapi first. Use addInto/remove for arrays, replace for primitives/objects. See context for details."),
10
- }, async ({ codename, operations }, { authInfo: { token, clientId } = {} }) => {
7
+ server.tool("patch-content-type-mapi", "Update Kontent.ai content type using patch operations. Call get-patch-guide first for operations reference.", {
8
+ id: z.guid(),
9
+ operations: patchOperationsSchema.describe(`Patch operations array. CRITICAL: Always call get-type-mapi first.
10
+ - Use addInto/remove for arrays, replace for primitives/objects
11
+ - Only one url_slug element allowed per content type
12
+ - To remove content groups: set ALL elements' content_group to null AND remove ALL groups in one request
13
+ - URL slug with snippet: add snippet element first, then url_slug with depends_on reference`),
14
+ }, async ({ id, operations }, { authInfo: { token, clientId } = {} }) => {
11
15
  const client = createMapiClient(clientId, token);
12
16
  try {
13
17
  // Apply patch operations using the modifyContentType method
14
18
  const response = await client
15
19
  .modifyContentType()
16
- .byTypeCodename(codename)
20
+ .byTypeId(id)
17
21
  .withData(operations)
18
22
  .toPromise();
19
23
  return createMcpToolSuccessResponse({
20
- message: `Content type '${codename}' updated successfully with ${operations.length} operation(s)`,
24
+ message: `Content type updated successfully with ${operations.length} operation(s)`,
21
25
  contentType: response.rawData,
22
26
  appliedOperations: operations,
23
27
  });
@@ -0,0 +1,28 @@
1
+ import { z } from "zod";
2
+ import { createMapiClient } from "../clients/kontentClients.js";
3
+ import { spacePatchOperationsSchema } from "../schemas/spaceSchemas.js";
4
+ import { handleMcpToolError } from "../utils/errorHandler.js";
5
+ import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
6
+ export const registerTool = (server) => {
7
+ server.tool("patch-space-mapi", "Patch Kontent.ai space using replace operations. Call get-patch-guide first for operations reference.", {
8
+ id: z.guid(),
9
+ operations: spacePatchOperationsSchema,
10
+ }, async ({ id, operations }, { authInfo: { token, clientId } = {} }) => {
11
+ const client = createMapiClient(clientId, token);
12
+ try {
13
+ const response = await client
14
+ .modifySpace()
15
+ .bySpaceId(id)
16
+ .withData(operations)
17
+ .toPromise();
18
+ return createMcpToolSuccessResponse({
19
+ message: `Space updated successfully with ${operations.length} operation(s)`,
20
+ space: response.rawData,
21
+ appliedOperations: operations,
22
+ });
23
+ }
24
+ catch (error) {
25
+ return handleMcpToolError(error, "Space Modification");
26
+ }
27
+ });
28
+ };
@@ -0,0 +1,28 @@
1
+ import { z } from "zod";
2
+ import { createMapiClient } from "../clients/kontentClients.js";
3
+ import { taxonomyPatchOperationsSchema } from "../schemas/patchSchemas/taxonomyPatchSchemas.js";
4
+ import { handleMcpToolError } from "../utils/errorHandler.js";
5
+ import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
6
+ export const registerTool = (server) => {
7
+ server.tool("patch-taxonomy-group-mapi", "Update Kontent.ai taxonomy group using patch operations (addInto, move, remove, replace). Call get-patch-guide first for operations reference.", {
8
+ id: z.guid(),
9
+ operations: taxonomyPatchOperationsSchema.describe("Patch operations array. Call get-taxonomy-group-mapi first. Use addInto to add terms (with optional reference for parent), move to reorder/nest terms (before/after/under - mutually exclusive), remove to delete terms, replace for name/codename/terms."),
10
+ }, async ({ id, operations }, { authInfo: { token, clientId } = {} }) => {
11
+ const client = createMapiClient(clientId, token);
12
+ try {
13
+ const response = await client
14
+ .modifyTaxonomy()
15
+ .byTaxonomyId(id)
16
+ .withData(operations)
17
+ .toPromise();
18
+ return createMcpToolSuccessResponse({
19
+ message: `Taxonomy group updated with ${operations.length} operation(s)`,
20
+ taxonomyGroup: response.rawData,
21
+ appliedOperations: operations,
22
+ });
23
+ }
24
+ catch (error) {
25
+ return handleMcpToolError(error, "Taxonomy Group Patch");
26
+ }
27
+ });
28
+ };
@@ -0,0 +1,30 @@
1
+ import { z } from "zod";
2
+ import { createMapiClient } from "../clients/kontentClients.js";
3
+ import { snippetPatchOperationsSchema } from "../schemas/patchSchemas/snippetPatchSchemas.js";
4
+ import { handleMcpToolError } from "../utils/errorHandler.js";
5
+ import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
6
+ export const registerTool = (server) => {
7
+ server.tool("patch-type-snippet-mapi", "Update Kontent.ai content type snippet using patch operations (move, addInto, remove, replace). Call get-patch-guide first for operations reference.", {
8
+ id: z.guid(),
9
+ operations: snippetPatchOperationsSchema.describe(`Patch operations array. CRITICAL: Always call get-type-snippet-mapi first.
10
+ - Use addInto/remove for arrays, replace for primitives/objects
11
+ - Snippets cannot contain: content_groups, snippet, or url_slug elements`),
12
+ }, async ({ id, operations }, { authInfo: { token, clientId } = {} }) => {
13
+ const client = createMapiClient(clientId, token);
14
+ try {
15
+ const response = await client
16
+ .modifyContentTypeSnippet()
17
+ .byTypeId(id)
18
+ .withData(operations)
19
+ .toPromise();
20
+ return createMcpToolSuccessResponse({
21
+ message: `Content type snippet updated successfully with ${operations.length} operation(s)`,
22
+ snippet: response.rawData,
23
+ appliedOperations: operations,
24
+ });
25
+ }
26
+ catch (error) {
27
+ return handleMcpToolError(error, "Content Type Snippet Patch");
28
+ }
29
+ });
30
+ };
@@ -0,0 +1,24 @@
1
+ import { z } from "zod";
2
+ import { createMapiClient } from "../clients/kontentClients.js";
3
+ import { updateAssetDataSchema } from "../schemas/assetSchemas.js";
4
+ import { handleMcpToolError } from "../utils/errorHandler.js";
5
+ import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
6
+ export const registerTool = (server) => {
7
+ server.tool("update-asset-mapi", "Update Kontent.ai asset by ID", {
8
+ id: z.guid(),
9
+ data: updateAssetDataSchema,
10
+ }, async ({ id, data }, { authInfo: { token, clientId } = {} }) => {
11
+ const client = createMapiClient(clientId, token);
12
+ try {
13
+ const response = await client
14
+ .upsertAsset()
15
+ .byAssetId(id)
16
+ .withData(() => data)
17
+ .toPromise();
18
+ return createMcpToolSuccessResponse(response.rawData);
19
+ }
20
+ catch (error) {
21
+ return handleMcpToolError(error, "Asset Update");
22
+ }
23
+ });
24
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kontent-ai/mcp-server",
3
- "version": "0.23.2",
3
+ "version": "0.24.0",
4
4
  "type": "module",
5
5
  "mcpName": "io.github.kontent-ai/mcp-server",
6
6
  "repository": {
@@ -1,58 +0,0 @@
1
- export const patchOperationsGuide = `
2
- # Content Type Patch Operations Guide
3
-
4
- ## Overview
5
- Modify content types using RFC 6902 JSON Patch operations: move, addInto, remove, replace.
6
-
7
- ## Critical Requirements
8
- - **Always call get-type-mapi first** to get current schema
9
- - **Use addInto/remove for arrays** (elements, allowed_content_types, allowed_blocks, etc.)
10
- - **Never use replace for array properties** - use addInto/remove instead
11
- - **Use replace for primitives/objects** (name, maximum_text_length, validation_regex)
12
- - **external_id and type cannot be modified** after creation
13
- - **When adding allowed_formatting/allowed_table_formatting**, 'unstyled' must be first
14
-
15
- ## Operation Types
16
-
17
- ### move
18
- Reorganize elements, options, or content groups using 'before' or 'after' reference.
19
-
20
- ### addInto
21
- Add new items to arrays. Use for all array operations (elements, options, allowed_blocks, etc.).
22
-
23
- ### remove
24
- Delete items from arrays or remove elements/groups.
25
-
26
- ### replace
27
- Update primitives and objects. Cannot modify external_id, id, or type.
28
-
29
- ## Path Formats
30
- Use JSON Pointer with id:{uuid} format:
31
- - Element: /elements/id:{uuid}
32
- - Element property: /elements/id:{uuid}/name
33
- - Option: /elements/id:{uuid}/options/id:{uuid}
34
- - Content group: /content_groups/id:{uuid}
35
- - Array item: /elements/id:{uuid}/allowed_content_types/id:{uuid}
36
-
37
- ## Rich Text Properties
38
- - **allowed_content_types**: Content types for components/linked items (empty=all)
39
- - **allowed_item_link_types**: Content types for text links (empty=all)
40
- - **allowed_blocks**: "images", "text", "tables", "components-and-items" (empty=all)
41
- - **allowed_image_types**: "adjustable" or "any"
42
- - **allowed_text_blocks**: "paragraph", "heading-one" through "heading-six", "ordered-list", "unordered-list" (empty=all)
43
- - **allowed_formatting**: "unstyled", "bold", "italic", "code", "link", "subscript", "superscript" (empty=all, unstyled must be first)
44
- - **allowed_table_blocks**: "images", "text" (empty=both)
45
- - **allowed_table_text_blocks**: Same as allowed_text_blocks (empty=all)
46
- - **allowed_table_formatting**: Same as allowed_formatting (empty=all, unstyled must be first)
47
-
48
- ## Special Techniques
49
- - **Remove content groups**: Set ALL elements' content_group to null AND remove ALL groups in one request
50
- - **URL Slug with snippet**: Add snippet element first, then URL slug with depends_on reference
51
-
52
- ## Best Practices
53
- - Use descriptive codenames
54
- - Group related operations in single request
55
- - Use id:{uuid} format in paths
56
- - Validate dependencies before adding URL slugs
57
- - Consider element ordering for move operations
58
- `;