@kontent-ai/mcp-server 0.4.2 → 0.6.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 (31) hide show
  1. package/README.md +127 -32
  2. package/build/bin.js +11 -7
  3. package/build/clients/kontentClients.js +12 -8
  4. package/build/schemas/contentItemSchemas.js +205 -0
  5. package/build/schemas/contentTypeSchemas.js +250 -127
  6. package/build/schemas/taxonomySchemas.js +11 -3
  7. package/build/server.js +22 -11
  8. package/build/tools/add-content-item-mapi.js +54 -0
  9. package/build/tools/add-content-type-mapi.js +35 -28
  10. package/build/tools/add-content-type-snippet-mapi.js +31 -29
  11. package/build/tools/add-taxonomy-group-mapi.js +14 -14
  12. package/build/tools/delete-content-item-mapi.js +24 -0
  13. package/build/tools/delete-language-variant-mapi.js +28 -0
  14. package/build/tools/get-asset-mapi.js +14 -14
  15. package/build/tools/get-item-dapi.js +13 -13
  16. package/build/tools/get-item-mapi.js +14 -14
  17. package/build/tools/get-taxonomy-group-mapi.js +14 -14
  18. package/build/tools/get-type-mapi.js +14 -14
  19. package/build/tools/get-type-snippet-mapi.js +16 -14
  20. package/build/tools/get-variant-mapi.js +17 -15
  21. package/build/tools/list-assets-mapi.js +10 -12
  22. package/build/tools/list-content-type-snippets-mapi.js +10 -12
  23. package/build/tools/list-content-types-mapi.js +10 -12
  24. package/build/tools/list-languages-mapi.js +10 -12
  25. package/build/tools/list-taxonomy-groups-mapi.js +11 -13
  26. package/build/tools/update-content-item-mapi.js +74 -0
  27. package/build/tools/upsert-language-variant-mapi.js +46 -0
  28. package/build/utils/errorHandler.js +87 -0
  29. package/build/utils/responseHelper.js +18 -0
  30. package/build/utils/throwError.js +3 -0
  31. package/package.json +13 -5
@@ -1,13 +1,18 @@
1
1
  import { z } from "zod";
2
2
  // Define a reusable reference object schema
3
- const referenceObjectSchema = z.object({
3
+ const referenceObjectSchema = z
4
+ .object({
4
5
  id: z.string().optional(),
5
6
  codename: z.string().optional(),
6
- });
7
+ })
8
+ .describe("An object with an id or codename property referencing another item. Using codename is preferred for better readability.");
7
9
  // Common property schemas
8
10
  const baseElementSchema = {
9
11
  codename: z.string().optional(),
10
12
  external_id: z.string().optional(),
13
+ };
14
+ // Content group schema for content type elements only
15
+ const contentGroupElementSchema = {
11
16
  content_group: referenceObjectSchema
12
17
  .describe("An object with an id or codename property referencing a content group.")
13
18
  .optional(),
@@ -20,174 +25,292 @@ const namedElementSchema = {
20
25
  is_non_localizable: z.boolean().optional(),
21
26
  };
22
27
  // Limit schemas
23
- const conditionEnum = z.enum(['at_most', 'exactly', 'at_least']);
24
- const countLimitSchema = z.object({
28
+ const conditionEnum = z.enum(["at_most", "exactly", "at_least"]);
29
+ const countLimitSchema = z
30
+ .object({
25
31
  value: z.number(),
26
- condition: conditionEnum
27
- }).optional();
32
+ condition: conditionEnum,
33
+ })
34
+ .optional();
28
35
  const imageLimitSchema = {
29
- image_width_limit: z.object({
36
+ image_width_limit: z
37
+ .object({
30
38
  value: z.number(),
31
- condition: conditionEnum
32
- }).optional(),
33
- image_height_limit: z.object({
39
+ condition: conditionEnum,
40
+ })
41
+ .optional(),
42
+ image_height_limit: z
43
+ .object({
34
44
  value: z.number(),
35
- condition: conditionEnum
36
- }).optional(),
45
+ condition: conditionEnum,
46
+ })
47
+ .optional(),
37
48
  };
38
49
  // Default value schemas
39
- const arrayDefaultSchema = (schema = referenceObjectSchema) => z.object({
50
+ const arrayDefaultSchema = z
51
+ .object({
40
52
  global: z.object({
41
- value: z.array(schema)
42
- })
43
- }).optional();
44
- const stringDefaultSchema = z.object({
53
+ value: z.array(referenceObjectSchema),
54
+ }),
55
+ })
56
+ .optional();
57
+ const stringDefaultSchema = z
58
+ .object({
45
59
  global: z.object({
46
- value: z.string()
47
- })
48
- }).optional();
49
- const numberDefaultSchema = z.object({
60
+ value: z.string(),
61
+ }),
62
+ })
63
+ .optional();
64
+ const numberDefaultSchema = z
65
+ .object({
50
66
  global: z.object({
51
- value: z.number()
52
- })
53
- }).optional();
67
+ value: z.number(),
68
+ }),
69
+ })
70
+ .optional();
54
71
  // Regex validation schema
55
- const regexValidationSchema = z.object({
72
+ const regexValidationSchema = z
73
+ .object({
56
74
  is_active: z.boolean(),
57
75
  regex: z.string(),
58
76
  flags: z.string().optional(),
59
- validation_message: z.string().optional()
60
- }).optional();
77
+ validation_message: z.string().optional(),
78
+ })
79
+ .optional();
61
80
  // Text length limit schema
62
- const textLengthLimitSchema = z.object({
81
+ const textLengthLimitSchema = z
82
+ .object({
63
83
  value: z.number(),
64
- applies_to: z.enum(['words', 'characters'])
65
- }).optional();
84
+ applies_to: z.enum(["words", "characters"]),
85
+ })
86
+ .optional();
66
87
  // Individual element type schemas
67
- const assetElementSchema = z.object({
68
- type: z.literal('asset'),
88
+ const assetElementSchema = {
89
+ type: z.literal("asset"),
69
90
  ...namedElementSchema,
70
91
  asset_count_limit: countLimitSchema,
71
92
  maximum_file_size: z.number().optional(),
72
- allowed_file_types: z.enum(['adjustable', 'any']).optional(),
93
+ allowed_file_types: z.enum(["adjustable", "any"]).optional(),
73
94
  ...imageLimitSchema,
74
- default: arrayDefaultSchema(),
75
- });
76
- const customElementSchema = z.object({
77
- type: z.literal('custom'),
95
+ default: arrayDefaultSchema.describe("Default value of the asset element. Reference an existing asset by its id or codename."),
96
+ };
97
+ const customElementSchema = {
98
+ type: z.literal("custom"),
78
99
  ...namedElementSchema,
79
100
  source_url: z.string(),
80
101
  json_parameters: z.string().optional(),
81
- allowed_elements: z.array(referenceObjectSchema
82
- .describe("An object with an id or codename property referencing an element.")).optional(),
83
- });
84
- const dateTimeElementSchema = z.object({
85
- type: z.literal('date_time'),
102
+ allowed_elements: z
103
+ .array(referenceObjectSchema.describe("An object with an id or codename property referencing an element."))
104
+ .optional()
105
+ .describe("Specifies which elements from the content type can be used within this custom element."),
106
+ };
107
+ const dateTimeElementSchema = {
108
+ type: z.literal("date_time"),
86
109
  ...namedElementSchema,
87
110
  default: stringDefaultSchema,
88
- });
89
- const guidelinesElementSchema = z.object({
90
- type: z.literal('guidelines'),
91
- guidelines: z.string(),
111
+ };
112
+ const guidelinesElementSchema = {
113
+ type: z.literal("guidelines"),
92
114
  ...baseElementSchema,
93
- });
94
- const modularContentElementSchema = z.object({
95
- type: z.literal('modular_content'),
115
+ guidelines: z
116
+ .string()
117
+ .describe("Value of the guidelines element. This is rich text and can include HTML formatting. Check the documentation here https://kontent.ai/learn/docs/apis/openapi/management-api-v2/#section/HTML5-elements-allowed-in-rich-text for the supported format, but keep in mind that content items and components are not supported in guidelines. Use empty `<p>` tag for empty guidelines."),
118
+ };
119
+ const modularContentElementSchema = {
120
+ type: z.literal("modular_content"),
96
121
  ...namedElementSchema,
97
- allowed_content_types: z.array(referenceObjectSchema
98
- .describe("An object with an id or codename property referencing a content type.")).optional(),
122
+ allowed_content_types: z
123
+ .array(referenceObjectSchema.describe("An object with an id or codename property referencing a content type. Use an empty array to allow all content types."))
124
+ .optional(),
99
125
  item_count_limit: countLimitSchema,
100
- default: arrayDefaultSchema(),
101
- });
102
- const subpagesElementSchema = z.object({
103
- type: z.literal('subpages'),
126
+ default: arrayDefaultSchema.describe("Default value of the modular content element. Reference an existing content item by its id or codename."),
127
+ };
128
+ const subpagesElementSchema = {
129
+ type: z.literal("subpages"),
104
130
  ...namedElementSchema,
105
- allowed_content_types: z.array(referenceObjectSchema
106
- .describe("An object with an id or codename property referencing a content type.")).optional(),
131
+ allowed_content_types: z
132
+ .array(referenceObjectSchema.describe("An object with an id or codename property referencing a content type. Use an empty array to allow all content types."))
133
+ .optional(),
107
134
  item_count_limit: countLimitSchema,
108
- });
109
- const multipleChoiceElementSchema = z.object({
110
- type: z.literal('multiple_choice'),
135
+ };
136
+ const multipleChoiceElementSchema = {
137
+ type: z.literal("multiple_choice"),
111
138
  ...namedElementSchema,
112
- mode: z.enum(['single', 'multiple']),
139
+ mode: z.enum(["single", "multiple"]),
113
140
  options: z.array(z.object({
114
141
  name: z.string(),
115
142
  codename: z.string().optional(),
116
143
  external_id: z.string().optional(),
117
144
  })),
118
- default: arrayDefaultSchema(),
119
- });
120
- const numberElementSchema = z.object({
121
- type: z.literal('number'),
145
+ default: arrayDefaultSchema.describe("Default value of the multiple choice element. Reference one of the options by its codename."),
146
+ };
147
+ const numberElementSchema = {
148
+ type: z.literal("number"),
122
149
  ...namedElementSchema,
123
150
  default: numberDefaultSchema,
124
- });
125
- const richTextElementSchema = z.object({
126
- type: z.literal('rich_text'),
151
+ };
152
+ const richTextElementSchema = {
153
+ type: z.literal("rich_text"),
127
154
  ...namedElementSchema,
128
- allowed_blocks: z.array(z.enum(['images', 'text', 'tables', 'components-and-items'])).optional(),
129
- allowed_formatting: z.array(z.enum(['unstyled', 'bold', 'italic', 'code', 'link', 'subscript', 'superscript'])).optional(),
130
- allowed_text_blocks: z.array(z.enum(['paragraph', 'heading-one', 'heading-two', 'heading-three', 'heading-four', 'heading-five', 'heading-six', 'ordered-list', 'unordered-list'])).optional(),
131
- allowed_table_blocks: z.array(z.enum(['images', 'text'])).optional(),
132
- allowed_table_formatting: z.array(z.enum(['unstyled', 'bold', 'italic', 'code', 'link', 'subscript', 'superscript'])).optional(),
133
- allowed_table_text_blocks: z.array(z.enum(['paragraph', 'heading-one', 'heading-two', 'heading-three', 'heading-four', 'heading-five', 'heading-six', 'ordered-list', 'unordered-list'])).optional(),
134
- allowed_content_types: z.array(referenceObjectSchema
135
- .describe("An object with an id or codename property referencing a content type.")).optional(),
136
- allowed_item_link_types: z.array(referenceObjectSchema
137
- .describe("An object with an id or codename property referencing a content type.")).optional(),
155
+ allowed_blocks: z
156
+ .array(z.enum(["images", "text", "tables", "components-and-items"]))
157
+ .optional()
158
+ .describe("Specifies allowed blocks. Use an empty array to allow all options."),
159
+ allowed_formatting: z
160
+ .array(z.enum([
161
+ "unstyled",
162
+ "bold",
163
+ "italic",
164
+ "code",
165
+ "link",
166
+ "subscript",
167
+ "superscript",
168
+ ]))
169
+ .optional()
170
+ .describe("Specifies allowed formatting options. Use an empty array to allow all options."),
171
+ allowed_text_blocks: z
172
+ .array(z.enum([
173
+ "paragraph",
174
+ "heading-one",
175
+ "heading-two",
176
+ "heading-three",
177
+ "heading-four",
178
+ "heading-five",
179
+ "heading-six",
180
+ "ordered-list",
181
+ "unordered-list",
182
+ ]))
183
+ .optional()
184
+ .describe("Specifies allowed text blocks. Use an empty array to allow all options."),
185
+ allowed_table_blocks: z
186
+ .array(z.enum(["images", "text"]))
187
+ .optional()
188
+ .describe("Specifies allowed table blocks. Use an empty array to allow all options."),
189
+ allowed_table_formatting: z
190
+ .array(z.enum([
191
+ "unstyled",
192
+ "bold",
193
+ "italic",
194
+ "code",
195
+ "link",
196
+ "subscript",
197
+ "superscript",
198
+ ]))
199
+ .optional()
200
+ .describe("Specifies allowed table formatting options. Use an empty array to allow all options."),
201
+ allowed_table_text_blocks: z
202
+ .array(z.enum([
203
+ "paragraph",
204
+ "heading-one",
205
+ "heading-two",
206
+ "heading-three",
207
+ "heading-four",
208
+ "heading-five",
209
+ "heading-six",
210
+ "ordered-list",
211
+ "unordered-list",
212
+ ]))
213
+ .optional()
214
+ .describe("Specifies allowed table text blocks. Use an empty array to allow all options."),
215
+ allowed_content_types: z
216
+ .array(referenceObjectSchema.describe("An object with an id or codename property referencing a content type."))
217
+ .optional()
218
+ .describe("Specifies allowed content types. Use an empty array to allow all content types."),
219
+ allowed_item_link_types: z
220
+ .array(referenceObjectSchema.describe("An object with an id or codename property referencing a content type."))
221
+ .optional()
222
+ .describe("Specifies allowed item link types. Use an empty array to allow all link types."),
138
223
  ...imageLimitSchema,
139
- allowed_image_types: z.enum(['adjustable', 'any']).optional(),
224
+ allowed_image_types: z.enum(["adjustable", "any"]).optional(),
140
225
  maximum_image_size: z.number().optional(),
141
226
  maximum_text_length: textLengthLimitSchema,
142
- });
143
- const snippetElement = z.object({
144
- type: z.literal('snippet'),
145
- snippet: referenceObjectSchema
146
- .describe("An object with an id or codename property referencing a snippet."),
227
+ };
228
+ const snippetElement = {
229
+ type: z.literal("snippet"),
230
+ snippet: referenceObjectSchema.describe("An object with an id or codename property referencing a snippet."),
147
231
  ...baseElementSchema,
148
- });
149
- const taxonomyElementSchema = z.object({
150
- type: z.literal('taxonomy'),
151
- taxonomy_group: referenceObjectSchema
152
- .describe("An object with an id or codename property referencing a taxonomy group."),
232
+ };
233
+ const taxonomyElementSchema = {
234
+ type: z.literal("taxonomy"),
235
+ taxonomy_group: referenceObjectSchema.describe("An object with an id or codename property referencing a taxonomy group."),
153
236
  ...namedElementSchema,
154
237
  term_count_limit: countLimitSchema,
155
- default: arrayDefaultSchema(),
156
- });
157
- const textElementSchema = z.object({
158
- type: z.literal('text'),
238
+ default: arrayDefaultSchema.describe("Default value of the taxonomy element. Reference one of the terms from the specified taxonomy group by its codename."),
239
+ };
240
+ const textElementSchema = {
241
+ type: z.literal("text"),
159
242
  ...namedElementSchema,
160
243
  maximum_text_length: textLengthLimitSchema,
161
244
  validation_regex: regexValidationSchema,
162
245
  default: stringDefaultSchema,
163
- });
164
- const urlSlugElementSchema = z.object({
165
- type: z.literal('url_slug'),
246
+ };
247
+ const urlSlugElementSchema = {
248
+ type: z.literal("url_slug"),
166
249
  ...namedElementSchema,
167
- depends_on: z.object({
168
- element: referenceObjectSchema
169
- .describe("An object with an id or codename property referencing an element."),
250
+ depends_on: z
251
+ .object({
252
+ element: referenceObjectSchema.describe("An object with an id or codename property referencing an element."),
170
253
  snippet: referenceObjectSchema
171
254
  .describe("An object with an id or codename property referencing a content type snippet.")
172
255
  .optional(),
173
- }),
256
+ })
257
+ .describe("The element the URL slug depends on. If this element is within a snippet, the snippet must also be specified."),
174
258
  validation_regex: regexValidationSchema,
175
- });
259
+ };
176
260
  // Define a union type of all possible element types for content types
177
- export const elementSchema = z.discriminatedUnion('type', [
178
- assetElementSchema,
179
- customElementSchema,
180
- dateTimeElementSchema,
181
- guidelinesElementSchema,
182
- modularContentElementSchema,
183
- subpagesElementSchema,
184
- multipleChoiceElementSchema,
185
- numberElementSchema,
186
- richTextElementSchema,
187
- snippetElement,
188
- taxonomyElementSchema,
189
- textElementSchema,
190
- urlSlugElementSchema,
261
+ export const elementSchema = z.discriminatedUnion("type", [
262
+ z.object({
263
+ ...assetElementSchema,
264
+ ...contentGroupElementSchema,
265
+ }),
266
+ z.object({
267
+ ...customElementSchema,
268
+ ...contentGroupElementSchema,
269
+ }),
270
+ z.object({
271
+ ...dateTimeElementSchema,
272
+ ...contentGroupElementSchema,
273
+ }),
274
+ z.object({
275
+ ...guidelinesElementSchema,
276
+ ...contentGroupElementSchema,
277
+ }),
278
+ z.object({
279
+ ...modularContentElementSchema,
280
+ ...contentGroupElementSchema,
281
+ }),
282
+ z.object({
283
+ ...subpagesElementSchema,
284
+ ...contentGroupElementSchema,
285
+ }),
286
+ z.object({
287
+ ...multipleChoiceElementSchema,
288
+ ...contentGroupElementSchema,
289
+ }),
290
+ z.object({
291
+ ...numberElementSchema,
292
+ ...contentGroupElementSchema,
293
+ }),
294
+ z.object({
295
+ ...richTextElementSchema,
296
+ ...contentGroupElementSchema,
297
+ }),
298
+ z.object({
299
+ ...snippetElement,
300
+ ...contentGroupElementSchema,
301
+ }),
302
+ z.object({
303
+ ...taxonomyElementSchema,
304
+ ...contentGroupElementSchema,
305
+ }),
306
+ z.object({
307
+ ...textElementSchema,
308
+ ...contentGroupElementSchema,
309
+ }),
310
+ z.object({
311
+ ...urlSlugElementSchema,
312
+ ...contentGroupElementSchema,
313
+ }),
191
314
  ]);
192
315
  // Define schema for content groups
193
316
  export const contentGroupSchema = z.object({
@@ -196,16 +319,16 @@ export const contentGroupSchema = z.object({
196
319
  codename: z.string().optional(),
197
320
  });
198
321
  // Define a union type for snippet elements (excluding url_slug and snippet elements)
199
- export const snippetElementSchema = z.discriminatedUnion('type', [
200
- assetElementSchema,
201
- customElementSchema,
202
- dateTimeElementSchema,
203
- guidelinesElementSchema,
204
- modularContentElementSchema,
205
- subpagesElementSchema,
206
- multipleChoiceElementSchema,
207
- numberElementSchema,
208
- richTextElementSchema,
209
- taxonomyElementSchema,
210
- textElementSchema,
322
+ export const snippetElementSchema = z.discriminatedUnion("type", [
323
+ z.object(assetElementSchema),
324
+ z.object(customElementSchema),
325
+ z.object(dateTimeElementSchema),
326
+ z.object(guidelinesElementSchema),
327
+ z.object(modularContentElementSchema),
328
+ z.object(subpagesElementSchema),
329
+ z.object(multipleChoiceElementSchema),
330
+ z.object(numberElementSchema),
331
+ z.object(richTextElementSchema),
332
+ z.object(taxonomyElementSchema),
333
+ z.object(textElementSchema),
211
334
  ]);
@@ -9,7 +9,15 @@ const taxonomyTermSchema = z.object({
9
9
  // Schema for a taxonomy group
10
10
  export const taxonomyGroupSchemas = {
11
11
  name: z.string().describe("Display name of the taxonomy group"),
12
- codename: z.string().optional().describe("Codename of the taxonomy group (optional, will be generated if not provided)"),
13
- external_id: z.string().optional().describe("External ID of the taxonomy group (optional)"),
14
- terms: z.array(taxonomyTermSchema).describe("Hierarchical structure of taxonomy terms"),
12
+ codename: z
13
+ .string()
14
+ .optional()
15
+ .describe("Codename of the taxonomy group (optional, will be generated if not provided)"),
16
+ external_id: z
17
+ .string()
18
+ .optional()
19
+ .describe("External ID of the taxonomy group (optional)"),
20
+ terms: z
21
+ .array(taxonomyTermSchema)
22
+ .describe("Hierarchical structure of taxonomy terms"),
15
23
  };
package/build/server.js CHANGED
@@ -1,24 +1,30 @@
1
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
- import { registerTool as registerGetItemMapi } from "./tools/get-item-mapi.js";
3
- import { registerTool as registerGetItemDapi } from "./tools/get-item-dapi.js";
4
- import { registerTool as registerGetVariantMapi } from "./tools/get-variant-mapi.js";
5
- import { registerTool as registerGetTypeMapi } from "./tools/get-type-mapi.js";
6
- import { registerTool as registerListContentTypesMapi } from "./tools/list-content-types-mapi.js";
7
- import { registerTool as registerListLanguagesMapi } from "./tools/list-languages-mapi.js";
8
- import { registerTool as registerGetAssetMapi } from "./tools/get-asset-mapi.js";
9
- import { registerTool as registerListAssetsMapi } from "./tools/list-assets-mapi.js";
2
+ import packageJson from "../package.json" with { type: "json" };
3
+ import { registerTool as registerAddContentItemMapi } from "./tools/add-content-item-mapi.js";
10
4
  import { registerTool as registerAddContentTypeMapi } from "./tools/add-content-type-mapi.js";
11
5
  import { registerTool as registerAddContentTypeSnippetMapi } from "./tools/add-content-type-snippet-mapi.js";
6
+ import { registerTool as registerAddTaxonomyGroupMapi } from "./tools/add-taxonomy-group-mapi.js";
7
+ import { registerTool as registerDeleteContentItemMapi } from "./tools/delete-content-item-mapi.js";
8
+ import { registerTool as registerDeleteLanguageVariantMapi } from "./tools/delete-language-variant-mapi.js";
9
+ import { registerTool as registerGetAssetMapi } from "./tools/get-asset-mapi.js";
10
+ import { registerTool as registerGetItemDapi } from "./tools/get-item-dapi.js";
11
+ import { registerTool as registerGetItemMapi } from "./tools/get-item-mapi.js";
12
+ import { registerTool as registerGetTaxonomyGroupMapi } from "./tools/get-taxonomy-group-mapi.js";
13
+ import { registerTool as registerGetTypeMapi } from "./tools/get-type-mapi.js";
12
14
  import { registerTool as registerGetTypeSnippetMapi } from "./tools/get-type-snippet-mapi.js";
15
+ import { registerTool as registerGetVariantMapi } from "./tools/get-variant-mapi.js";
16
+ import { registerTool as registerListAssetsMapi } from "./tools/list-assets-mapi.js";
13
17
  import { registerTool as registerListContentTypeSnippetsMapi } from "./tools/list-content-type-snippets-mapi.js";
14
- import { registerTool as registerAddTaxonomyGroupMapi } from "./tools/add-taxonomy-group-mapi.js";
18
+ import { registerTool as registerListContentTypesMapi } from "./tools/list-content-types-mapi.js";
19
+ import { registerTool as registerListLanguagesMapi } from "./tools/list-languages-mapi.js";
15
20
  import { registerTool as registerListTaxonomyGroupsMapi } from "./tools/list-taxonomy-groups-mapi.js";
16
- import { registerTool as registerGetTaxonomyGroupMapi } from "./tools/get-taxonomy-group-mapi.js";
21
+ import { registerTool as registerUpdateContentItemMapi } from "./tools/update-content-item-mapi.js";
22
+ import { registerTool as registerUpsertLanguageVariantMapi } from "./tools/upsert-language-variant-mapi.js";
17
23
  // Create server instance
18
24
  export const createServer = () => {
19
25
  const server = new McpServer({
20
26
  name: "kontent-ai",
21
- version: "1.0.0",
27
+ version: packageJson.version,
22
28
  capabilities: {
23
29
  resources: {},
24
30
  tools: {},
@@ -40,5 +46,10 @@ export const createServer = () => {
40
46
  registerAddTaxonomyGroupMapi(server);
41
47
  registerListTaxonomyGroupsMapi(server);
42
48
  registerGetTaxonomyGroupMapi(server);
49
+ registerAddContentItemMapi(server);
50
+ registerUpdateContentItemMapi(server);
51
+ registerDeleteContentItemMapi(server);
52
+ registerUpsertLanguageVariantMapi(server);
53
+ registerDeleteLanguageVariantMapi(server);
43
54
  return { server };
44
55
  };
@@ -0,0 +1,54 @@
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("add-content-item-mapi", "Add a new content item via Management API. This creates the content item structure but does not add content to language variants. Use upsert-language-variant-mapi to add content to the item.", {
7
+ name: z
8
+ .string()
9
+ .min(1)
10
+ .max(200)
11
+ .describe("Display name of the content item (1-200 characters)"),
12
+ type: z
13
+ .object({
14
+ id: z.string().optional(),
15
+ codename: z.string().optional(),
16
+ external_id: z.string().optional(),
17
+ })
18
+ .describe("Reference to the content type by id, codename, or external_id. At least one property must be specified."),
19
+ codename: z
20
+ .string()
21
+ .optional()
22
+ .describe("Codename of the content item (optional, will be generated from name if not provided)"),
23
+ external_id: z
24
+ .string()
25
+ .optional()
26
+ .describe("External ID for the content item (optional, useful for external system integration)"),
27
+ collection: z
28
+ .object({
29
+ id: z.string().optional(),
30
+ codename: z.string().optional(),
31
+ external_id: z.string().optional(),
32
+ })
33
+ .optional()
34
+ .describe("Reference to a collection by id, codename, or external_id (optional)"),
35
+ }, async ({ name, type, codename, external_id, collection }) => {
36
+ const client = createMapiClient();
37
+ try {
38
+ const response = await client
39
+ .addContentItem()
40
+ .withData({
41
+ name,
42
+ type,
43
+ codename,
44
+ external_id,
45
+ collection,
46
+ })
47
+ .toPromise();
48
+ return createMcpToolSuccessResponse(response.rawData);
49
+ }
50
+ catch (error) {
51
+ return handleMcpToolError(error, "Content Item Creation");
52
+ }
53
+ });
54
+ };
@@ -1,36 +1,43 @@
1
1
  import { z } from "zod";
2
- import { createMapiClient } from '../clients/kontentClients.js';
3
- import { elementSchema, contentGroupSchema } from '../schemas/contentTypeSchemas.js';
2
+ import { createMapiClient } from "../clients/kontentClients.js";
3
+ import { contentGroupSchema, elementSchema, } from "../schemas/contentTypeSchemas.js";
4
+ import { handleMcpToolError } from "../utils/errorHandler.js";
5
+ import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
4
6
  export const registerTool = (server) => {
5
7
  server.tool("add-content-type-mapi", "Add a new content type via Management API", {
6
8
  name: z.string().describe("Display name of the content type"),
7
- codename: z.string().optional().describe("Codename of the content type (optional, will be generated if not provided)"),
8
- external_id: z.string().optional().describe("External ID of the content type (optional)"),
9
- elements: z.array(elementSchema).describe("Array of elements that define the structure of the content type"),
10
- content_groups: z.array(contentGroupSchema).optional().describe("Array of content groups (optional)"),
9
+ codename: z
10
+ .string()
11
+ .optional()
12
+ .describe("Codename of the content type (optional, will be generated if not provided)"),
13
+ external_id: z
14
+ .string()
15
+ .optional()
16
+ .describe("External ID of the content type (optional)"),
17
+ elements: z
18
+ .array(elementSchema)
19
+ .describe("Array of elements that define the structure of the content type"),
20
+ content_groups: z
21
+ .array(contentGroupSchema)
22
+ .optional()
23
+ .describe("Array of content groups (optional)"),
11
24
  }, async ({ name, codename, external_id, elements, content_groups }) => {
12
25
  const client = createMapiClient();
13
- const response = await client
14
- .addContentType()
15
- .withData(() => ({
16
- name,
17
- codename,
18
- external_id,
19
- elements,
20
- content_groups: content_groups?.map(group => ({
21
- name: group.name,
22
- external_id: group.external_id,
23
- codename: group.codename
24
- })),
25
- }))
26
- .toPromise();
27
- return {
28
- content: [
29
- {
30
- type: "text",
31
- text: JSON.stringify(response.rawData),
32
- },
33
- ],
34
- };
26
+ try {
27
+ const response = await client
28
+ .addContentType()
29
+ .withData(() => ({
30
+ name,
31
+ codename,
32
+ external_id,
33
+ elements,
34
+ content_groups,
35
+ }))
36
+ .toPromise();
37
+ return createMcpToolSuccessResponse(response.rawData);
38
+ }
39
+ catch (error) {
40
+ return handleMcpToolError(error, "Content Type Creation");
41
+ }
35
42
  });
36
43
  };