@kontent-ai/mcp-server 0.23.3 → 0.25.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 (41) hide show
  1. package/README.md +21 -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/searchOperationSchemas.js +5 -5
  11. package/build/schemas/spaceSchemas.js +30 -0
  12. package/build/schemas/workflowSchemas.js +74 -76
  13. package/build/server.js +28 -0
  14. package/build/telemetry/applicationInsights.js +1 -1
  15. package/build/tools/add-content-type-mapi.js +1 -1
  16. package/build/tools/add-content-type-snippet-mapi.js +1 -1
  17. package/build/tools/add-space-mapi.js +23 -0
  18. package/build/tools/add-workflow-mapi.js +24 -0
  19. package/build/tools/change-variant-workflow-step-mapi.js +4 -6
  20. package/build/tools/context/patch-guide-path-based.js +53 -0
  21. package/build/tools/context/patch-guide-property-based.js +42 -0
  22. package/build/tools/context/patch-guide-reference-based.js +86 -0
  23. package/build/tools/delete-space-mapi.js +20 -0
  24. package/build/tools/delete-taxonomy-group-mapi.js +20 -0
  25. package/build/tools/delete-type-snippet-mapi.js +23 -0
  26. package/build/tools/delete-workflow-mapi.js +20 -0
  27. package/build/tools/get-patch-guide.js +31 -3
  28. package/build/tools/get-taxonomy-group-mapi.js +2 -2
  29. package/build/tools/list-asset-folders-mapi.js +15 -0
  30. package/build/tools/list-roles-mapi.js +15 -0
  31. package/build/tools/list-spaces-mapi.js +1 -1
  32. package/build/tools/list-taxonomy-groups-mapi.js +1 -1
  33. package/build/tools/patch-asset-folders-mapi.js +25 -0
  34. package/build/tools/patch-content-type-mapi.js +10 -6
  35. package/build/tools/patch-space-mapi.js +28 -0
  36. package/build/tools/patch-taxonomy-group-mapi.js +28 -0
  37. package/build/tools/patch-type-snippet-mapi.js +30 -0
  38. package/build/tools/update-asset-mapi.js +24 -0
  39. package/build/tools/update-workflow-mapi.js +32 -0
  40. package/package.json +1 -1
  41. package/build/tools/context/patch-operations-guide.js +0 -58
package/build/server.js CHANGED
@@ -4,12 +4,18 @@ 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";
9
+ import { registerTool as registerAddWorkflowMapi } from "./tools/add-workflow-mapi.js";
8
10
  import { registerTool as registerChangeVariantWorkflowStepMapi } from "./tools/change-variant-workflow-step-mapi.js";
9
11
  import { registerTool as registerCreateVariantVersionMapi } from "./tools/create-variant-version-mapi.js";
10
12
  import { registerTool as registerDeleteContentItemMapi } from "./tools/delete-content-item-mapi.js";
11
13
  import { registerTool as registerDeleteContentTypeMapi } from "./tools/delete-content-type-mapi.js";
12
14
  import { registerTool as registerDeleteLanguageVariantMapi } from "./tools/delete-language-variant-mapi.js";
15
+ import { registerTool as registerDeleteSpaceMapi } from "./tools/delete-space-mapi.js";
16
+ import { registerTool as registerDeleteTaxonomyGroupMapi } from "./tools/delete-taxonomy-group-mapi.js";
17
+ import { registerTool as registerDeleteTypeSnippetMapi } from "./tools/delete-type-snippet-mapi.js";
18
+ import { registerTool as registerDeleteWorkflowMapi } from "./tools/delete-workflow-mapi.js";
13
19
  import { registerTool as registerFilterVariantsMapi } from "./tools/filter-variants-mapi.js";
14
20
  import { registerTool as registerGetAssetMapi } from "./tools/get-asset-mapi.js";
15
21
  import { registerTool as registerGetItemMapi } from "./tools/get-item-mapi.js";
@@ -19,11 +25,13 @@ import { registerTool as registerGetPublishedVariantMapi } from "./tools/get-pub
19
25
  import { registerTool as registerGetTaxonomyGroupMapi } from "./tools/get-taxonomy-group-mapi.js";
20
26
  import { registerTool as registerGetTypeMapi } from "./tools/get-type-mapi.js";
21
27
  import { registerTool as registerGetTypeSnippetMapi } from "./tools/get-type-snippet-mapi.js";
28
+ import { registerTool as registerListAssetFoldersMapi } from "./tools/list-asset-folders-mapi.js";
22
29
  import { registerTool as registerListAssetsMapi } from "./tools/list-assets-mapi.js";
23
30
  import { registerTool as registerListCollectionsMapi } from "./tools/list-collections-mapi.js";
24
31
  import { registerTool as registerListContentTypeSnippetsMapi } from "./tools/list-content-type-snippets-mapi.js";
25
32
  import { registerTool as registerListContentTypesMapi } from "./tools/list-content-types-mapi.js";
26
33
  import { registerTool as registerListLanguagesMapi } from "./tools/list-languages-mapi.js";
34
+ import { registerTool as registerListRolesMapi } from "./tools/list-roles-mapi.js";
27
35
  import { registerTool as registerListSpacesMapi } from "./tools/list-spaces-mapi.js";
28
36
  import { registerTool as registerListTaxonomyGroupsMapi } from "./tools/list-taxonomy-groups-mapi.js";
29
37
  import { registerTool as registerListVariantsCollectionMapi } from "./tools/list-variants-collection-mapi.js";
@@ -32,13 +40,19 @@ import { registerTool as registerListVariantsItemMapi } from "./tools/list-varia
32
40
  import { registerTool as registerListVariantsSpaceMapi } from "./tools/list-variants-space-mapi.js";
33
41
  import { registerTool as registerListVariantsTypeMapi } from "./tools/list-variants-type-mapi.js";
34
42
  import { registerTool as registerListWorkflowsMapi } from "./tools/list-workflows-mapi.js";
43
+ import { registerTool as registerPatchAssetFoldersMapi } from "./tools/patch-asset-folders-mapi.js";
35
44
  import { registerTool as registerPatchCollectionsMapi } from "./tools/patch-collections-mapi.js";
36
45
  import { registerTool as registerPatchContentTypeMapi } from "./tools/patch-content-type-mapi.js";
37
46
  import { registerTool as registerPatchLanguageMapi } from "./tools/patch-language-mapi.js";
47
+ import { registerTool as registerPatchSpaceMapi } from "./tools/patch-space-mapi.js";
48
+ import { registerTool as registerPatchTaxonomyGroupMapi } from "./tools/patch-taxonomy-group-mapi.js";
49
+ import { registerTool as registerPatchTypeSnippetMapi } from "./tools/patch-type-snippet-mapi.js";
38
50
  import { registerTool as registerPublishVariantMapi } from "./tools/publish-variant-mapi.js";
39
51
  import { registerTool as registerSearchVariantsMapi } from "./tools/search-variants-mapi.js";
40
52
  import { registerTool as registerUnpublishVariantMapi } from "./tools/unpublish-variant-mapi.js";
53
+ import { registerTool as registerUpdateAssetMapi } from "./tools/update-asset-mapi.js";
41
54
  import { registerTool as registerUpdateContentItemMapi } from "./tools/update-content-item-mapi.js";
55
+ import { registerTool as registerUpdateWorkflowMapi } from "./tools/update-workflow-mapi.js";
42
56
  import { registerTool as registerUpsertLanguageVariantMapi } from "./tools/upsert-language-variant-mapi.js";
43
57
  // Create server instance
44
58
  export const createServer = () => {
@@ -65,16 +79,27 @@ export const createServer = () => {
65
79
  registerListCollectionsMapi(server);
66
80
  registerPatchCollectionsMapi(server);
67
81
  registerListSpacesMapi(server);
82
+ registerAddSpaceMapi(server);
83
+ registerPatchSpaceMapi(server);
84
+ registerDeleteSpaceMapi(server);
85
+ registerListRolesMapi(server);
68
86
  registerGetAssetMapi(server);
69
87
  registerListAssetsMapi(server);
88
+ registerUpdateAssetMapi(server);
89
+ registerListAssetFoldersMapi(server);
90
+ registerPatchAssetFoldersMapi(server);
70
91
  registerAddContentTypeMapi(server);
71
92
  registerPatchContentTypeMapi(server);
72
93
  registerAddContentTypeSnippetMapi(server);
73
94
  registerGetTypeSnippetMapi(server);
74
95
  registerListContentTypeSnippetsMapi(server);
96
+ registerPatchTypeSnippetMapi(server);
97
+ registerDeleteTypeSnippetMapi(server);
75
98
  registerAddTaxonomyGroupMapi(server);
76
99
  registerListTaxonomyGroupsMapi(server);
77
100
  registerGetTaxonomyGroupMapi(server);
101
+ registerPatchTaxonomyGroupMapi(server);
102
+ registerDeleteTaxonomyGroupMapi(server);
78
103
  registerAddContentItemMapi(server);
79
104
  registerUpdateContentItemMapi(server);
80
105
  registerDeleteContentItemMapi(server);
@@ -82,6 +107,9 @@ export const createServer = () => {
82
107
  registerCreateVariantVersionMapi(server);
83
108
  registerDeleteLanguageVariantMapi(server);
84
109
  registerListWorkflowsMapi(server);
110
+ registerAddWorkflowMapi(server);
111
+ registerUpdateWorkflowMapi(server);
112
+ registerDeleteWorkflowMapi(server);
85
113
  registerChangeVariantWorkflowStepMapi(server);
86
114
  registerFilterVariantsMapi(server);
87
115
  registerSearchVariantsMapi(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,24 @@
1
+ import { createMapiClient } from "../clients/kontentClients.js";
2
+ import { workflowInputSchema } from "../schemas/workflowSchemas.js";
3
+ import { handleMcpToolError } from "../utils/errorHandler.js";
4
+ import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
5
+ export const registerTool = (server) => {
6
+ server.tool("add-workflow-mapi", "Add new Kontent.ai workflow", workflowInputSchema.shape, async ({ name, codename, scopes, steps, published_step, archived_step }, { authInfo: { token, clientId } = {} }) => {
7
+ const client = createMapiClient(clientId, token);
8
+ const data = {
9
+ name,
10
+ codename,
11
+ scopes,
12
+ steps,
13
+ published_step,
14
+ archived_step,
15
+ };
16
+ try {
17
+ const response = await client.addWorkflow().withData(data).toPromise();
18
+ return createMcpToolSuccessResponse(response.rawData);
19
+ }
20
+ catch (error) {
21
+ return handleMcpToolError(error, "Workflow Creation");
22
+ }
23
+ });
24
+ };
@@ -4,12 +4,10 @@ import { handleMcpToolError } from "../utils/errorHandler.js";
4
4
  import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
5
5
  export const registerTool = (server) => {
6
6
  server.tool("change-variant-workflow-step-mapi", "Change Kontent.ai variant workflow step", {
7
- itemId: z.guid().describe("Content item UUID"),
8
- languageId: z
9
- .guid()
10
- .describe("Language variant UUID (default: 00000000-0000-0000-0000-000000000000)"),
11
- workflowId: z.guid().describe("Workflow UUID"),
12
- workflowStepId: z.guid().describe("Target workflow step UUID"),
7
+ itemId: z.guid().describe("Content item ID"),
8
+ languageId: z.guid().describe("Language variant ID"),
9
+ workflowId: z.guid().describe("Workflow ID"),
10
+ workflowStepId: z.guid().describe("Target workflow step ID"),
13
11
  }, async ({ itemId, languageId, workflowId, workflowStepId }, { authInfo: { token, clientId } = {} }) => {
14
12
  const client = createMapiClient(clientId, token);
15
13
  try {
@@ -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
+ };
@@ -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-workflow-mapi", {
7
+ id: z.guid().describe("Workflow ID"),
8
+ }, async ({ id }, { authInfo: { token, clientId } = {} }) => {
9
+ const client = createMapiClient(clientId, token);
10
+ try {
11
+ await client.deleteWorkflow().byWorkflowId(id).toPromise();
12
+ return createMcpToolSuccessResponse({
13
+ message: `Workflow '${id}' deleted successfully`,
14
+ });
15
+ }
16
+ catch (error) {
17
+ return handleMcpToolError(error, "Workflow Deletion");
18
+ }
19
+ });
20
+ };
@@ -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
+ };
@@ -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-roles-mapi", "Get all Kontent.ai roles", {}, async (_, { authInfo: { token, clientId } = {} }) => {
6
+ const client = createMapiClient(clientId, token);
7
+ try {
8
+ const response = await client.listRoles().toPromise();
9
+ return createMcpToolSuccessResponse(response.rawData.roles);
10
+ }
11
+ catch (error) {
12
+ return handleMcpToolError(error, "Roles 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
  });