@kontent-ai/mcp-server 0.21.9 → 0.21.11

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 (42) hide show
  1. package/README.md +30 -1
  2. package/build/bin.js +7 -0
  3. package/build/schemas/contentTypeSchemas.js +24 -61
  4. package/build/schemas/filterVariantSchemas.js +2 -0
  5. package/build/schemas/listSchemas.js +26 -0
  6. package/build/schemas/patchSchemas/contentTypePatchSchemas.js +12 -64
  7. package/build/schemas/referenceObjectSchema.js +3 -5
  8. package/build/schemas/taxonomySchemas.js +4 -9
  9. package/build/test/utils/responseHelper.spec.js +450 -0
  10. package/build/tools/add-content-item-mapi.js +6 -13
  11. package/build/tools/add-content-type-mapi.js +6 -11
  12. package/build/tools/add-content-type-snippet-mapi.js +5 -8
  13. package/build/tools/add-taxonomy-group-mapi.js +1 -1
  14. package/build/tools/change-variant-workflow-step-mapi.js +5 -14
  15. package/build/tools/context/initial-context.js +40 -1
  16. package/build/tools/context/patch-operations-guide.js +58 -0
  17. package/build/tools/create-variant-version-mapi.js +3 -6
  18. package/build/tools/delete-content-item-mapi.js +2 -2
  19. package/build/tools/delete-content-type-mapi.js +2 -2
  20. package/build/tools/delete-language-variant-mapi.js +3 -5
  21. package/build/tools/filter-variants-mapi.js +13 -20
  22. package/build/tools/get-asset-mapi.js +2 -2
  23. package/build/tools/get-initial-context.js +2 -1
  24. package/build/tools/get-item-mapi.js +2 -2
  25. package/build/tools/get-taxonomy-group-mapi.js +2 -2
  26. package/build/tools/get-type-mapi.js +2 -2
  27. package/build/tools/get-type-snippet-mapi.js +2 -2
  28. package/build/tools/get-variant-mapi.js +5 -7
  29. package/build/tools/list-assets-mapi.js +12 -4
  30. package/build/tools/list-content-type-snippets-mapi.js +12 -4
  31. package/build/tools/list-content-types-mapi.js +12 -4
  32. package/build/tools/list-languages-mapi.js +12 -4
  33. package/build/tools/list-taxonomy-groups-mapi.js +12 -4
  34. package/build/tools/list-workflows-mapi.js +1 -1
  35. package/build/tools/patch-content-type-mapi.js +3 -50
  36. package/build/tools/publish-variant-mapi.js +5 -8
  37. package/build/tools/search-variants-mapi.js +3 -29
  38. package/build/tools/unpublish-variant-mapi.js +5 -8
  39. package/build/tools/update-content-item-mapi.js +4 -4
  40. package/build/tools/upsert-language-variant-mapi.js +7 -10
  41. package/build/utils/responseHelper.js +90 -6
  42. package/package.json +4 -1
@@ -3,14 +3,14 @@ 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("update-content-item-mapi", "Update existing Kontent.ai content item by internal ID via Management API. The content item must already exist - this tool will not create new items.", {
7
- id: z.string().describe("Internal ID of the content item to update"),
6
+ server.tool("update-content-item-mapi", "Update Kontent.ai content item", {
7
+ id: z.string().describe("Content item ID"),
8
8
  name: z
9
9
  .string()
10
10
  .min(1)
11
11
  .max(200)
12
12
  .optional()
13
- .describe("New display name of the content item (1-200 characters, optional)"),
13
+ .describe("New name (1-200 chars)"),
14
14
  collection: z
15
15
  .object({
16
16
  id: z.string().optional(),
@@ -18,7 +18,7 @@ export const registerTool = (server) => {
18
18
  external_id: z.string().optional(),
19
19
  })
20
20
  .optional()
21
- .describe("Reference to a collection by id, codename, or external_id (optional)"),
21
+ .describe("Collection reference"),
22
22
  }, async ({ id, name, collection }, { authInfo: { token, clientId } = {} }) => {
23
23
  const client = createMapiClient(clientId, token);
24
24
  try {
@@ -2,20 +2,17 @@ import { z } from "zod";
2
2
  import { createMapiClient } from "../clients/kontentClients.js";
3
3
  import { languageVariantElementSchema } from "../schemas/contentItemSchemas.js";
4
4
  import { handleMcpToolError } from "../utils/errorHandler.js";
5
- import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
5
+ import { createVariantMcpToolSuccessResponse } from "../utils/responseHelper.js";
6
6
  export const registerTool = (server) => {
7
- server.tool("upsert-language-variant-mapi", "Create or update Kontent.ai language variant of a content item via Management API. This adds actual content to the content item elements. When updating an existing variant, only the provided elements will be modified.", {
8
- itemId: z.string().describe("Internal ID of the content item"),
7
+ server.tool("upsert-language-variant-mapi", "Create or update Kontent.ai variant", {
8
+ itemId: z.string().describe("Content item ID"),
9
9
  languageId: z
10
10
  .string()
11
- .describe("Internal ID of the language variant (e.g., '00000000-0000-0000-0000-000000000000' for default language)"),
11
+ .describe("Language variant ID (default: 00000000-0000-0000-0000-000000000000)"),
12
12
  elements: z
13
13
  .array(languageVariantElementSchema)
14
- .describe("Array of content elements, each with 'element' (reference object with id/codename/external_id) and 'value' properties. Additional properties may be required depending on element type (e.g., 'mode' for URL slugs)."),
15
- workflow_step_id: z
16
- .string()
17
- .optional()
18
- .describe("Internal ID of the workflow step (optional)"),
14
+ .describe("Content elements array"),
15
+ workflow_step_id: z.string().optional().describe("Workflow step ID"),
19
16
  }, async ({ itemId, languageId, elements, workflow_step_id }, { authInfo: { token, clientId } = {} }) => {
20
17
  const client = createMapiClient(clientId, token);
21
18
  const data = {
@@ -31,7 +28,7 @@ export const registerTool = (server) => {
31
28
  .byLanguageId(languageId)
32
29
  .withData(() => data)
33
30
  .toPromise();
34
- return createMcpToolSuccessResponse(response.rawData);
31
+ return createVariantMcpToolSuccessResponse(response.rawData);
35
32
  }
36
33
  catch (error) {
37
34
  return handleMcpToolError(error, "Language Variant Upsert");
@@ -1,17 +1,101 @@
1
1
  /**
2
2
  * Utility for creating standardized MCP tool success responses
3
3
  */
4
- /**
5
- * Creates a standardized MCP tool success response
6
- * @param data The data to include in the response
7
- * @returns Standardized MCP tool success response
8
- */
4
+ export function isEmptyOrDefault(value) {
5
+ if (value === null || value === undefined) {
6
+ return true;
7
+ }
8
+ if (typeof value === "string" && value === "") {
9
+ return true;
10
+ }
11
+ if (typeof value === "string" && value === "<p><br/></p>") {
12
+ return true;
13
+ }
14
+ if (Array.isArray(value) && value.length === 0) {
15
+ return true;
16
+ }
17
+ if (typeof value === "object" &&
18
+ !Array.isArray(value) &&
19
+ !(value instanceof Date) &&
20
+ !(value instanceof Function) &&
21
+ Object.keys(value).length === 0) {
22
+ return true;
23
+ }
24
+ return false;
25
+ }
26
+ export function removeEmptyElementsFromVariant(obj) {
27
+ if (obj === null || obj === undefined || typeof obj !== "object") {
28
+ return obj;
29
+ }
30
+ if (Array.isArray(obj)) {
31
+ return obj.map((item) => removeEmptyElementsFromVariant(item));
32
+ }
33
+ const result = {};
34
+ for (const [key, value] of Object.entries(obj)) {
35
+ if (key === "elements" && Array.isArray(value)) {
36
+ const filteredElements = value
37
+ .filter((element) => {
38
+ if (typeof element !== "object" || element === null) {
39
+ return true;
40
+ }
41
+ const keys = Object.keys(element);
42
+ return !(keys.length === 1 && keys[0] === "element");
43
+ })
44
+ .map((element) => removeEmptyElementsFromVariant(element));
45
+ if (filteredElements.length > 0) {
46
+ result[key] = filteredElements;
47
+ }
48
+ }
49
+ else {
50
+ const processedValue = removeEmptyElementsFromVariant(value);
51
+ if (processedValue !== undefined) {
52
+ result[key] = processedValue;
53
+ }
54
+ }
55
+ }
56
+ return result;
57
+ }
58
+ export function removeEmptyValues(obj) {
59
+ if (obj === null || obj === undefined) {
60
+ return undefined;
61
+ }
62
+ if (typeof obj !== "object") {
63
+ return isEmptyOrDefault(obj) ? undefined : obj;
64
+ }
65
+ if (Array.isArray(obj)) {
66
+ const cleaned = obj
67
+ .map((item) => removeEmptyValues(item))
68
+ .filter((item) => item !== undefined);
69
+ return cleaned.length === 0 ? undefined : cleaned;
70
+ }
71
+ const cleaned = {};
72
+ for (const [key, value] of Object.entries(obj)) {
73
+ const cleanedValue = removeEmptyValues(value);
74
+ if (cleanedValue !== undefined) {
75
+ cleaned[key] = cleanedValue;
76
+ }
77
+ }
78
+ const keys = Object.keys(cleaned);
79
+ return keys.length === 0 ? undefined : cleaned;
80
+ }
9
81
  export const createMcpToolSuccessResponse = (data) => {
10
82
  return {
11
83
  content: [
12
84
  {
13
85
  type: "text",
14
- text: JSON.stringify(data),
86
+ text: JSON.stringify(removeEmptyValues(data)),
87
+ },
88
+ ],
89
+ };
90
+ };
91
+ export const createVariantMcpToolSuccessResponse = (data) => {
92
+ const cleaned = removeEmptyValues(data);
93
+ const optimized = removeEmptyElementsFromVariant(cleaned);
94
+ return {
95
+ content: [
96
+ {
97
+ type: "text",
98
+ text: JSON.stringify(optimized),
15
99
  },
16
100
  ],
17
101
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kontent-ai/mcp-server",
3
- "version": "0.21.9",
3
+ "version": "0.21.11",
4
4
  "type": "module",
5
5
  "mcpName": "io.github.kontent-ai/mcp-server",
6
6
  "scripts": {
@@ -11,6 +11,7 @@
11
11
  "dev:shttp": "tsx watch src/bin.ts shttp",
12
12
  "format": "cross-env biome ci",
13
13
  "format:fix": "cross-env biome check --fix --unsafe",
14
+ "test": "npm run build && mocha --timeout 10s -- \"build/test/**/*.spec.js\"",
14
15
  "sync-version": "node --experimental-strip-types scripts/syncVersion.ts",
15
16
  "version": "npm run sync-version sync && npm run format:fix -- server.json && git add server.json"
16
17
  },
@@ -35,8 +36,10 @@
35
36
  "devDependencies": {
36
37
  "@biomejs/biome": "^2.0.5",
37
38
  "@types/express": "^5.0.2",
39
+ "@types/mocha": "^10.0.10",
38
40
  "@types/node": "^22.15.19",
39
41
  "cross-env": "^7.0.3",
42
+ "mocha": "^11.7.5",
40
43
  "rimraf": "^6.0.1",
41
44
  "tsx": "^4.20.3",
42
45
  "typescript": "^5.8.3"