@kontent-ai/mcp-server 0.13.0 → 0.15.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.
- package/README.md +2 -0
- package/build/schemas/contentTypeSchemas.js +73 -62
- package/build/schemas/filterVariantSchemas.js +17 -0
- package/build/schemas/patchSchemas/contentTypePatchSchemas.js +118 -0
- package/build/server.js +4 -0
- package/build/tools/delete-content-type-mapi.js +24 -0
- package/build/tools/filter-variants-mapi.js +3 -1
- package/build/tools/patch-content-type-mapi.js +76 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -65,6 +65,8 @@ npx @kontent-ai/mcp-server@latest sse
|
|
|
65
65
|
* **get-type-mapi** – Get Kontent.ai content type by internal ID from Management API
|
|
66
66
|
* **list-content-types-mapi** – Get all Kontent.ai content types from Management API
|
|
67
67
|
* **add-content-type-mapi** – Add new Kontent.ai content type via Management API
|
|
68
|
+
* **patch-content-type-mapi** – Update an existing Kontent.ai content type by codename using patch operations (move, addInto, remove, replace)
|
|
69
|
+
* **delete-content-type-mapi** – Delete a Kontent.ai content type by codename
|
|
68
70
|
|
|
69
71
|
### Content Type Snippet Management
|
|
70
72
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
// Define a reusable reference object schema
|
|
3
|
-
const referenceObjectSchema = z
|
|
3
|
+
export const referenceObjectSchema = z
|
|
4
4
|
.object({
|
|
5
5
|
id: z.string().optional(),
|
|
6
6
|
codename: z.string().optional(),
|
|
@@ -26,7 +26,7 @@ const namedElementSchema = {
|
|
|
26
26
|
};
|
|
27
27
|
// Limit schemas
|
|
28
28
|
const conditionEnum = z.enum(["at_most", "exactly", "at_least"]);
|
|
29
|
-
const countLimitSchema = z
|
|
29
|
+
export const countLimitSchema = z
|
|
30
30
|
.object({
|
|
31
31
|
value: z.number(),
|
|
32
32
|
condition: conditionEnum,
|
|
@@ -47,21 +47,21 @@ const imageLimitSchema = {
|
|
|
47
47
|
.optional(),
|
|
48
48
|
};
|
|
49
49
|
// Default value schemas
|
|
50
|
-
const arrayDefaultSchema = z
|
|
50
|
+
export const arrayDefaultSchema = z
|
|
51
51
|
.object({
|
|
52
52
|
global: z.object({
|
|
53
53
|
value: z.array(referenceObjectSchema),
|
|
54
54
|
}),
|
|
55
55
|
})
|
|
56
56
|
.optional();
|
|
57
|
-
const stringDefaultSchema = z
|
|
57
|
+
export const stringDefaultSchema = z
|
|
58
58
|
.object({
|
|
59
59
|
global: z.object({
|
|
60
60
|
value: z.string(),
|
|
61
61
|
}),
|
|
62
62
|
})
|
|
63
63
|
.optional();
|
|
64
|
-
const numberDefaultSchema = z
|
|
64
|
+
export const numberDefaultSchema = z
|
|
65
65
|
.object({
|
|
66
66
|
global: z.object({
|
|
67
67
|
value: z.number(),
|
|
@@ -69,7 +69,7 @@ const numberDefaultSchema = z
|
|
|
69
69
|
})
|
|
70
70
|
.optional();
|
|
71
71
|
// Regex validation schema
|
|
72
|
-
const regexValidationSchema = z
|
|
72
|
+
export const regexValidationSchema = z
|
|
73
73
|
.object({
|
|
74
74
|
is_active: z.boolean(),
|
|
75
75
|
regex: z.string(),
|
|
@@ -78,7 +78,7 @@ const regexValidationSchema = z
|
|
|
78
78
|
})
|
|
79
79
|
.optional();
|
|
80
80
|
// Text length limit schema
|
|
81
|
-
const textLengthLimitSchema = z
|
|
81
|
+
export const textLengthLimitSchema = z
|
|
82
82
|
.object({
|
|
83
83
|
value: z.number(),
|
|
84
84
|
applies_to: z.enum(["words", "characters"]),
|
|
@@ -133,15 +133,16 @@ const subpagesElementSchema = {
|
|
|
133
133
|
.optional(),
|
|
134
134
|
item_count_limit: countLimitSchema,
|
|
135
135
|
};
|
|
136
|
+
export const optionSchema = z.object({
|
|
137
|
+
name: z.string(),
|
|
138
|
+
codename: z.string().optional(),
|
|
139
|
+
external_id: z.string().optional(),
|
|
140
|
+
});
|
|
136
141
|
const multipleChoiceElementSchema = {
|
|
137
142
|
type: z.literal("multiple_choice"),
|
|
138
143
|
...namedElementSchema,
|
|
139
144
|
mode: z.enum(["single", "multiple"]),
|
|
140
|
-
options: z.array(
|
|
141
|
-
name: z.string(),
|
|
142
|
-
codename: z.string().optional(),
|
|
143
|
-
external_id: z.string().optional(),
|
|
144
|
-
})),
|
|
145
|
+
options: z.array(optionSchema),
|
|
145
146
|
default: arrayDefaultSchema.describe("Default value of the multiple choice element. Reference one of the options by its codename."),
|
|
146
147
|
};
|
|
147
148
|
const numberElementSchema = {
|
|
@@ -149,67 +150,78 @@ const numberElementSchema = {
|
|
|
149
150
|
...namedElementSchema,
|
|
150
151
|
default: numberDefaultSchema,
|
|
151
152
|
};
|
|
153
|
+
export const allowedBlockSchema = z.enum([
|
|
154
|
+
"images",
|
|
155
|
+
"text",
|
|
156
|
+
"tables",
|
|
157
|
+
"components-and-items",
|
|
158
|
+
]);
|
|
159
|
+
export const allowedFormattingSchema = z.enum([
|
|
160
|
+
"unstyled",
|
|
161
|
+
"bold",
|
|
162
|
+
"italic",
|
|
163
|
+
"code",
|
|
164
|
+
"link",
|
|
165
|
+
"subscript",
|
|
166
|
+
"superscript",
|
|
167
|
+
]);
|
|
168
|
+
export const allowedTextBlockSchema = z.enum([
|
|
169
|
+
"paragraph",
|
|
170
|
+
"heading-one",
|
|
171
|
+
"heading-two",
|
|
172
|
+
"heading-three",
|
|
173
|
+
"heading-four",
|
|
174
|
+
"heading-five",
|
|
175
|
+
"heading-six",
|
|
176
|
+
"ordered-list",
|
|
177
|
+
"unordered-list",
|
|
178
|
+
]);
|
|
179
|
+
export const allowedTableBlockSchema = z.enum(["images", "text"]);
|
|
180
|
+
export const allowedTableFormattingSchema = z.enum([
|
|
181
|
+
"unstyled",
|
|
182
|
+
"bold",
|
|
183
|
+
"italic",
|
|
184
|
+
"code",
|
|
185
|
+
"link",
|
|
186
|
+
"subscript",
|
|
187
|
+
"superscript",
|
|
188
|
+
]);
|
|
189
|
+
export const allowedTableTextBlockSchema = z.enum([
|
|
190
|
+
"paragraph",
|
|
191
|
+
"heading-one",
|
|
192
|
+
"heading-two",
|
|
193
|
+
"heading-three",
|
|
194
|
+
"heading-four",
|
|
195
|
+
"heading-five",
|
|
196
|
+
"heading-six",
|
|
197
|
+
"ordered-list",
|
|
198
|
+
"unordered-list",
|
|
199
|
+
]);
|
|
152
200
|
const richTextElementSchema = {
|
|
153
201
|
type: z.literal("rich_text"),
|
|
154
202
|
...namedElementSchema,
|
|
155
203
|
allowed_blocks: z
|
|
156
|
-
.array(
|
|
204
|
+
.array(allowedBlockSchema)
|
|
157
205
|
.optional()
|
|
158
206
|
.describe("Specifies allowed blocks. Use an empty array to allow all options."),
|
|
159
207
|
allowed_formatting: z
|
|
160
|
-
.array(
|
|
161
|
-
"unstyled",
|
|
162
|
-
"bold",
|
|
163
|
-
"italic",
|
|
164
|
-
"code",
|
|
165
|
-
"link",
|
|
166
|
-
"subscript",
|
|
167
|
-
"superscript",
|
|
168
|
-
]))
|
|
208
|
+
.array(allowedFormattingSchema)
|
|
169
209
|
.optional()
|
|
170
210
|
.describe("Specifies allowed formatting options. Use an empty array to allow all options."),
|
|
171
211
|
allowed_text_blocks: z
|
|
172
|
-
.array(
|
|
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
|
-
]))
|
|
212
|
+
.array(allowedTextBlockSchema)
|
|
183
213
|
.optional()
|
|
184
214
|
.describe("Specifies allowed text blocks. Use an empty array to allow all options."),
|
|
185
215
|
allowed_table_blocks: z
|
|
186
|
-
.array(
|
|
216
|
+
.array(allowedTableBlockSchema)
|
|
187
217
|
.optional()
|
|
188
218
|
.describe("Specifies allowed table blocks. Use an empty array to allow all options."),
|
|
189
219
|
allowed_table_formatting: z
|
|
190
|
-
.array(
|
|
191
|
-
"unstyled",
|
|
192
|
-
"bold",
|
|
193
|
-
"italic",
|
|
194
|
-
"code",
|
|
195
|
-
"link",
|
|
196
|
-
"subscript",
|
|
197
|
-
"superscript",
|
|
198
|
-
]))
|
|
220
|
+
.array(allowedTableFormattingSchema)
|
|
199
221
|
.optional()
|
|
200
222
|
.describe("Specifies allowed table formatting options. Use an empty array to allow all options."),
|
|
201
223
|
allowed_table_text_blocks: z
|
|
202
|
-
.array(
|
|
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
|
-
]))
|
|
224
|
+
.array(allowedTableTextBlockSchema)
|
|
213
225
|
.optional()
|
|
214
226
|
.describe("Specifies allowed table text blocks. Use an empty array to allow all options."),
|
|
215
227
|
allowed_content_types: z
|
|
@@ -244,17 +256,16 @@ const textElementSchema = {
|
|
|
244
256
|
validation_regex: regexValidationSchema,
|
|
245
257
|
default: stringDefaultSchema,
|
|
246
258
|
};
|
|
259
|
+
export const dependsOnSchema = z.object({
|
|
260
|
+
element: referenceObjectSchema.describe("An object with an id or codename property referencing an element."),
|
|
261
|
+
snippet: referenceObjectSchema
|
|
262
|
+
.describe("An object with an id or codename property referencing a content type snippet.")
|
|
263
|
+
.optional(),
|
|
264
|
+
});
|
|
247
265
|
const urlSlugElementSchema = {
|
|
248
266
|
type: z.literal("url_slug"),
|
|
249
267
|
...namedElementSchema,
|
|
250
|
-
depends_on:
|
|
251
|
-
.object({
|
|
252
|
-
element: referenceObjectSchema.describe("An object with an id or codename property referencing an element."),
|
|
253
|
-
snippet: referenceObjectSchema
|
|
254
|
-
.describe("An object with an id or codename property referencing a content type snippet.")
|
|
255
|
-
.optional(),
|
|
256
|
-
})
|
|
257
|
-
.describe("The element the URL slug depends on. If this element is within a snippet, the snippet must also be specified."),
|
|
268
|
+
depends_on: dependsOnSchema.describe("The element the URL slug depends on. If this element is within a snippet, the snippet must also be specified."),
|
|
258
269
|
validation_regex: regexValidationSchema,
|
|
259
270
|
};
|
|
260
271
|
// Define a union type of all possible element types for content types
|
|
@@ -20,6 +20,10 @@ export const filterVariantsSchema = z.object({
|
|
|
20
20
|
.min(1)
|
|
21
21
|
.optional()
|
|
22
22
|
.describe("Array of references to users by their id or email"),
|
|
23
|
+
has_no_contributors: z
|
|
24
|
+
.boolean()
|
|
25
|
+
.optional()
|
|
26
|
+
.describe("Filter for content item language variants that have no contributors assigned"),
|
|
23
27
|
completion_statuses: z
|
|
24
28
|
.array(z.enum(["unfinished", "completed", "not_translated", "all_done"]))
|
|
25
29
|
.min(1)
|
|
@@ -39,6 +43,19 @@ export const filterVariantsSchema = z.object({
|
|
|
39
43
|
.min(1)
|
|
40
44
|
.optional()
|
|
41
45
|
.describe("Array of workflows with workflow steps"),
|
|
46
|
+
taxonomy_groups: z
|
|
47
|
+
.array(z.object({
|
|
48
|
+
taxonomy_identifier: referenceObjectSchema.describe("Reference to a taxonomy group by its id, codename, or external id"),
|
|
49
|
+
term_identifiers: z
|
|
50
|
+
.array(referenceObjectSchema)
|
|
51
|
+
.describe("Array of references to taxonomy terms by their id, codename, or external id"),
|
|
52
|
+
include_uncategorized: z
|
|
53
|
+
.boolean()
|
|
54
|
+
.describe("Whether to include content item language variants that don't have any taxonomy terms assigned in this taxonomy group"),
|
|
55
|
+
}))
|
|
56
|
+
.min(1)
|
|
57
|
+
.optional()
|
|
58
|
+
.describe("Array of taxonomy groups with taxonomy terms"),
|
|
42
59
|
order_by: z
|
|
43
60
|
.enum(["name", "due", "last_modified"])
|
|
44
61
|
.optional()
|
|
@@ -0,0 +1,118 @@
|
|
|
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
|
+
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
|
|
9
|
+
.string()
|
|
10
|
+
.describe(`Identifies the object you want to move using a path reference. The path reference should be in format 'id:{uuid}'. Examples:
|
|
11
|
+
• '/elements/id:123e4567-e89b-12d3-a456-426614174000' - Move an element
|
|
12
|
+
• '/elements/id:123e4567-e89b-12d3-a456-426614174000/options/id:987fcdeb-51a2-43d1-9f4e-123456789abc' - Move a multiple choice option (first reference is element, second is option)
|
|
13
|
+
• '/content_groups/id:456e7890-a12b-34c5-d678-901234567def' - Move a content group`),
|
|
14
|
+
before: referenceObjectSchema
|
|
15
|
+
.describe("A reference to the object before which you want to move the object. For example, to move an element before an existing element with id:uuid 'text', set before to {codename: 'text'}. The before and after properties are mutually exclusive.")
|
|
16
|
+
.optional(),
|
|
17
|
+
after: referenceObjectSchema
|
|
18
|
+
.describe("A reference to the object after which you want to move the object. For example, to move an element after an existing element with id:uuid 'Text', set after to {codename: 'text'}. The before and after properties are mutually exclusive.")
|
|
19
|
+
.optional(),
|
|
20
|
+
});
|
|
21
|
+
// AddInto operation - Add new elements to content type
|
|
22
|
+
const addIntoOperationSchema = z.object({
|
|
23
|
+
op: z.literal("addInto"),
|
|
24
|
+
path: z
|
|
25
|
+
.string()
|
|
26
|
+
.describe(`JSON Pointer path where to add the item. The path reference should be in format 'id:{uuid}'. Examples:
|
|
27
|
+
• '/elements' - Add a new element to the content type
|
|
28
|
+
• '/content_groups' - Add a new content group
|
|
29
|
+
• '/elements/id:123e4567-e89b-12d3-a456-426614174000/allowed_content_types' - Add allowed content type to rich text or linked items element
|
|
30
|
+
• '/elements/id:123e4567-e89b-12d3-a456-426614174000/allowed_elements' - Add allowed element to custom element
|
|
31
|
+
• '/elements/id:123e4567-e89b-12d3-a456-426614174000/options' - Add multiple choice option
|
|
32
|
+
• '/elements/id:123e4567-e89b-12d3-a456-426614174000/allowed_blocks' - Add block for rich text element
|
|
33
|
+
• '/elements/id:123e4567-e89b-12d3-a456-426614174000/allowed_formatting' - Add formatting option for rich text element
|
|
34
|
+
(Replace with actual element UUID)
|
|
35
|
+
|
|
36
|
+
- CRITICAL: When adding a url slug that references a snippet element, first add the snippet element to the content type if it’s not already included.`),
|
|
37
|
+
value: z
|
|
38
|
+
.union([
|
|
39
|
+
elementSchema,
|
|
40
|
+
optionSchema,
|
|
41
|
+
contentGroupSchema,
|
|
42
|
+
referenceObjectSchema,
|
|
43
|
+
allowedBlockSchema,
|
|
44
|
+
allowedFormattingSchema,
|
|
45
|
+
allowedTextBlockSchema,
|
|
46
|
+
allowedTableBlockSchema,
|
|
47
|
+
allowedTableFormattingSchema,
|
|
48
|
+
allowedTableTextBlockSchema,
|
|
49
|
+
z.string(),
|
|
50
|
+
z.number(),
|
|
51
|
+
z.boolean(),
|
|
52
|
+
z.null(),
|
|
53
|
+
z.any(),
|
|
54
|
+
])
|
|
55
|
+
.describe("The item to add (element, content group, option, etc.)"),
|
|
56
|
+
});
|
|
57
|
+
// Remove operation - Remove elements from content type
|
|
58
|
+
const removeOperationSchema = z.object({
|
|
59
|
+
op: z.literal("remove"),
|
|
60
|
+
path: z
|
|
61
|
+
.string()
|
|
62
|
+
.describe(`JSON Pointer path to the item being removed. The path reference should be in format 'id:{uuid}'. Examples:
|
|
63
|
+
• '/elements/id:123e4567-e89b-12d3-a456-426614174000' - Remove an element
|
|
64
|
+
• '/elements/id:123e4567-e89b-12d3-a456-426614174000/allowed_content_types/id:987fcdeb-51a2-43d1-9f4e-123456789abc' - Remove allowed content type from rich text/linked items element
|
|
65
|
+
• '/elements/id:123e4567-e89b-12d3-a456-426614174000/allowed_element/id:456e7890-a12b-34c5-d678-901234567def' - Remove allowed element from custom element
|
|
66
|
+
• '/elements/id:123e4567-e89b-12d3-a456-426614174000/options/id:321dcba9-87f6-54e3-21b0-fedcba987654' - Remove multiple choice option
|
|
67
|
+
• '/content_groups/id:456e7890-a12b-34c5-d678-901234567def' - Remove content group (removes all elements within the group)
|
|
68
|
+
• '/elements/id:123e4567-e89b-12d3-a456-426614174000/allowed_blocks/images' - Remove rich-text element limitation (where {block} is the limitation type)
|
|
69
|
+
(Replace with actual UUIDs)`),
|
|
70
|
+
});
|
|
71
|
+
// Replace operation - Replace/update existing elements in content type
|
|
72
|
+
const replaceOperationSchema = z.object({
|
|
73
|
+
op: z.literal("replace"),
|
|
74
|
+
path: z
|
|
75
|
+
.string()
|
|
76
|
+
.describe(`JSON Pointer path to the item or property being replaced. The path reference should be in format 'id:{uuid}' Examples:
|
|
77
|
+
• '/name' - Change the content type's name
|
|
78
|
+
• '/codename' - Change the content type's codename
|
|
79
|
+
• '/content_groups/id:456e7890-a12b-34c5-d678-901234567def/name' - Change the name of a content group
|
|
80
|
+
• '/elements/id:123e4567-e89b-12d3-a456-426614174000/name' - Change an element property (property depends on element type)
|
|
81
|
+
• '/elements/id:123e4567-e89b-12d3-a456-426614174000/options/id:321dcba9-87f6-54e3-21b0-fedcba987654/name' - Change multiple choice option property (name or codename)
|
|
82
|
+
(Replace with actual element/group UUIDs)
|
|
83
|
+
|
|
84
|
+
REPLACE OPERATION RULES:
|
|
85
|
+
• CAN modify: Most element properties based on element type (name, guidelines, validation, etc.)
|
|
86
|
+
• CANNOT modify: external_id, id, or type of elements
|
|
87
|
+
• CANNOT replace individual object values - must replace the entire object at once
|
|
88
|
+
• FOR rich text elements: CANNOT replace individual items in allowed_blocks, allowed_formatting, allowed_text_blocks, allowed_table_blocks, allowed_table_formatting, allowed_table_text_blocks, allowed_content_types, allowed_item_link_types arrays - use addInto/remove operations instead for individual items
|
|
89
|
+
• FOR multiple choice options: Can modify name and codename properties`),
|
|
90
|
+
value: z
|
|
91
|
+
.union([
|
|
92
|
+
dependsOnSchema,
|
|
93
|
+
regexValidationSchema,
|
|
94
|
+
textLengthLimitSchema,
|
|
95
|
+
countLimitSchema,
|
|
96
|
+
arrayDefaultSchema,
|
|
97
|
+
stringDefaultSchema,
|
|
98
|
+
numberDefaultSchema,
|
|
99
|
+
z.string(),
|
|
100
|
+
z.number(),
|
|
101
|
+
z.boolean(),
|
|
102
|
+
z.null(),
|
|
103
|
+
z.any(), // in Union zod tries to match from top to down. any if there is something missing so agent dont fail on validation.
|
|
104
|
+
])
|
|
105
|
+
.describe("The new value to replace the existing one"),
|
|
106
|
+
});
|
|
107
|
+
// Union type for all patch operations
|
|
108
|
+
export const patchOperationSchema = z.discriminatedUnion("op", [
|
|
109
|
+
moveOperationSchema,
|
|
110
|
+
addIntoOperationSchema,
|
|
111
|
+
removeOperationSchema,
|
|
112
|
+
replaceOperationSchema,
|
|
113
|
+
]);
|
|
114
|
+
// Schema for array of patch operations
|
|
115
|
+
export const patchOperationsSchema = z
|
|
116
|
+
.array(patchOperationSchema)
|
|
117
|
+
.min(1)
|
|
118
|
+
.describe("Array of patch operations to apply to the content type. Must contain at least one operation.");
|
package/build/server.js
CHANGED
|
@@ -6,6 +6,7 @@ import { registerTool as registerAddContentTypeSnippetMapi } from "./tools/add-c
|
|
|
6
6
|
import { registerTool as registerAddTaxonomyGroupMapi } from "./tools/add-taxonomy-group-mapi.js";
|
|
7
7
|
import { registerTool as registerChangeVariantWorkflowStepMapi } from "./tools/change-variant-workflow-step-mapi.js";
|
|
8
8
|
import { registerTool as registerDeleteContentItemMapi } from "./tools/delete-content-item-mapi.js";
|
|
9
|
+
import { registerTool as registerDeleteContentTypeMapi } from "./tools/delete-content-type-mapi.js";
|
|
9
10
|
import { registerTool as registerDeleteLanguageVariantMapi } from "./tools/delete-language-variant-mapi.js";
|
|
10
11
|
import { registerTool as registerFilterVariantsMapi } from "./tools/filter-variants-mapi.js";
|
|
11
12
|
import { registerTool as registerGetAssetMapi } from "./tools/get-asset-mapi.js";
|
|
@@ -22,6 +23,7 @@ import { registerTool as registerListContentTypesMapi } from "./tools/list-conte
|
|
|
22
23
|
import { registerTool as registerListLanguagesMapi } from "./tools/list-languages-mapi.js";
|
|
23
24
|
import { registerTool as registerListTaxonomyGroupsMapi } from "./tools/list-taxonomy-groups-mapi.js";
|
|
24
25
|
import { registerTool as registerListWorkflowsMapi } from "./tools/list-workflows-mapi.js";
|
|
26
|
+
import { registerTool as registerPatchContentTypeMapi } from "./tools/patch-content-type-mapi.js";
|
|
25
27
|
import { registerTool as registerPublishVariantMapi } from "./tools/publish-variant-mapi.js";
|
|
26
28
|
import { registerTool as registerUnpublishVariantMapi } from "./tools/unpublish-variant-mapi.js";
|
|
27
29
|
import { registerTool as registerUpdateContentItemMapi } from "./tools/update-content-item-mapi.js";
|
|
@@ -43,10 +45,12 @@ export const createServer = () => {
|
|
|
43
45
|
registerGetVariantMapi(server);
|
|
44
46
|
registerGetTypeMapi(server);
|
|
45
47
|
registerListContentTypesMapi(server);
|
|
48
|
+
registerDeleteContentTypeMapi(server);
|
|
46
49
|
registerListLanguagesMapi(server);
|
|
47
50
|
registerGetAssetMapi(server);
|
|
48
51
|
registerListAssetsMapi(server);
|
|
49
52
|
registerAddContentTypeMapi(server);
|
|
53
|
+
registerPatchContentTypeMapi(server);
|
|
50
54
|
registerAddContentTypeSnippetMapi(server);
|
|
51
55
|
registerGetTypeSnippetMapi(server);
|
|
52
56
|
registerListContentTypeSnippetsMapi(server);
|
|
@@ -0,0 +1,24 @@
|
|
|
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-content-type-mapi", "Delete a content type by codename from Management API", {
|
|
7
|
+
codename: z.string().describe("Codename of the content type to delete"),
|
|
8
|
+
}, async ({ codename }) => {
|
|
9
|
+
const client = createMapiClient();
|
|
10
|
+
try {
|
|
11
|
+
const response = await client
|
|
12
|
+
.deleteContentType()
|
|
13
|
+
.byTypeCodename(codename)
|
|
14
|
+
.toPromise();
|
|
15
|
+
return createMcpToolSuccessResponse({
|
|
16
|
+
message: `Content type '${codename}' deleted successfully`,
|
|
17
|
+
deletedType: response.data,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
return handleMcpToolError(error, "Content Type Deletion");
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
};
|
|
@@ -3,16 +3,18 @@ import { handleMcpToolError } from "../utils/errorHandler.js";
|
|
|
3
3
|
import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
|
|
4
4
|
import { throwError } from "../utils/throwError.js";
|
|
5
5
|
export const registerTool = (server) => {
|
|
6
|
-
server.tool("filter-variants-mapi", "Search and filter Kontent.ai language variants of content items using Management API", filterVariantsSchema.shape, async ({ search_phrase, content_types, contributors, completion_statuses, language, workflow_steps, order_by, order_direction, continuation_token, }) => {
|
|
6
|
+
server.tool("filter-variants-mapi", "Search and filter Kontent.ai language variants of content items using Management API", filterVariantsSchema.shape, async ({ search_phrase, content_types, contributors, has_no_contributors, completion_statuses, language, workflow_steps, taxonomy_groups, order_by, order_direction, continuation_token, }) => {
|
|
7
7
|
try {
|
|
8
8
|
const requestPayload = {
|
|
9
9
|
filters: {
|
|
10
10
|
search_phrase,
|
|
11
11
|
content_types,
|
|
12
12
|
contributors,
|
|
13
|
+
has_no_contributors,
|
|
13
14
|
completion_statuses,
|
|
14
15
|
language,
|
|
15
16
|
workflow_steps,
|
|
17
|
+
taxonomy_groups,
|
|
16
18
|
},
|
|
17
19
|
order: order_by
|
|
18
20
|
? {
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { createMapiClient } from "../clients/kontentClients.js";
|
|
3
|
+
import { patchOperationsSchema } from "../schemas/patchSchemas/contentTypePatchSchemas.js";
|
|
4
|
+
import { handleMcpToolError } from "../utils/errorHandler.js";
|
|
5
|
+
import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
|
|
6
|
+
export const registerTool = (server) => {
|
|
7
|
+
server.tool("patch-content-type-mapi", "Update an existing Kontent.ai content type by codename via Management API. Supports move, addInto, remove, and replace operations following RFC 6902 JSON Patch specification.", {
|
|
8
|
+
codename: z.string().describe("Codename of the content type to update"),
|
|
9
|
+
operations: patchOperationsSchema.describe(`Array of patch operations to apply. Supports: 'move' (reorganize elements), 'addInto' (add new elements), 'remove' (delete elements), 'replace' (update existing elements/properties).
|
|
10
|
+
|
|
11
|
+
CRITICAL REQUIREMENTS:
|
|
12
|
+
- ALWAYS call get-type-mapi tool before patching to get the latest content type schema
|
|
13
|
+
- Use addInto/remove for array operations (adding/removing items from arrays like elements and element's array properties - allowed_content_types, allowed_item_link_types, allowed_blocks, allowed_text_blocks, allowed_formatting, allowed_table_blocks, allowed_table_text_blocks, allowed_table_formatting)
|
|
14
|
+
- Never ever use replace for element's array properties - use addInto/remove instead
|
|
15
|
+
- Use replace for element's primitive data types and object properties (maximum_text_length, validation_regex, etc.)
|
|
16
|
+
- External_id and type cannot be modified after creation
|
|
17
|
+
- Patch operations with URL Slug elements referencing snippet elements MUST ensure snippet is present first
|
|
18
|
+
- When adding to allowed_formatting or allowed_table_formatting, 'unstyled' must be the first item in the array. If it is not present, then add it as first operation.
|
|
19
|
+
|
|
20
|
+
RICH TEXT ELEMENT PROPERTIES:
|
|
21
|
+
- allowed_content_types: Array of content type references. Specifies allowed content types for components and linked items. Empty array allows all.
|
|
22
|
+
- allowed_item_link_types: Array of content type references. Specifies content types allowed in text links (applies to text and tables). Empty array allows all.
|
|
23
|
+
- allowed_blocks: Available options: "images", "text", "tables", "components-and-items". Empty array allows all blocks.
|
|
24
|
+
- allowed_image_types: Available options: "adjustable" (only transformable images), "any" (all image files).
|
|
25
|
+
- allowed_text_blocks: Available options: "paragraph", "heading-one", "heading-two", "heading-three", "heading-four", "heading-five", "heading-six", "ordered-list", "unordered-list". Empty array allows all.
|
|
26
|
+
- allowed_formatting: Available options: "unstyled", "bold", "italic", "code", "link", "subscript", "superscript". "unstyled" must be first if used. Empty array allows all.
|
|
27
|
+
- allowed_table_blocks: Available options: "images", "text". Use ["text"] for text-only or empty array for both text and images.
|
|
28
|
+
- allowed_table_text_blocks: Available options: "paragraph", "heading-one", "heading-two", "heading-three", "heading-four", "heading-five", "heading-six", "ordered-list", "unordered-list". Empty array allows all.
|
|
29
|
+
- allowed_table_formatting: Available options: "unstyled", "bold", "italic", "code", "link", "subscript", "superscript". "unstyled" must be first if used. Empty array allows all.
|
|
30
|
+
|
|
31
|
+
OPERATION TYPES:
|
|
32
|
+
1. move: Reorganize elements, options, or content groups. Uses 'before' or 'after' reference.
|
|
33
|
+
2. addInto: Add new elements, options, content groups, or array items. Use for all array operations.
|
|
34
|
+
3. remove: Remove elements, options, content groups, or array items. Use for all array removals.
|
|
35
|
+
4. replace: Update existing properties of primitive data types and objects. Cannot modify external_id, id, or type.
|
|
36
|
+
|
|
37
|
+
PATH FORMATS:
|
|
38
|
+
- Use JSON Pointer paths with id:{uuid} format for referencing objects
|
|
39
|
+
- Element: /elements/id:123e4567-e89b-12d3-a456-426614174000
|
|
40
|
+
- Element property: /elements/id:123e4567-e89b-12d3-a456-426614174000/name
|
|
41
|
+
- Multiple choice option: /elements/id:123e4567-e89b-12d3-a456-426614174000/options/id:987fcdeb-51a2-43d1-9f4e-123456789abc
|
|
42
|
+
- Content group: /content_groups/id:456e7890-a12b-34c5-d678-901234567def
|
|
43
|
+
- Rich text array property: /elements/id:123e4567-e89b-12d3-a456-426614174000/allowed_content_types/id:987fcdeb-51a2-43d1-9f4e-123456789abc
|
|
44
|
+
|
|
45
|
+
SPECIAL TECHNIQUES:
|
|
46
|
+
- To remove content groups while keeping elements: Set ALL elements' content_group to null AND remove ALL content groups in ONE request (atomic operation)
|
|
47
|
+
- URL Slug with snippet dependency: First add snippet element, then add URL slug with depends_on reference
|
|
48
|
+
|
|
49
|
+
BEST PRACTICES:
|
|
50
|
+
- Use descriptive codenames following naming conventions
|
|
51
|
+
- Group related operations in a single patch request when possible
|
|
52
|
+
- Use proper reference formats (id:{uuid}) in paths
|
|
53
|
+
- Validate element dependencies before adding URL slug elements
|
|
54
|
+
- Consider element ordering when using move operations
|
|
55
|
+
- Use atomic operations for complex changes like removing content groups
|
|
56
|
+
- When adding to allowed_formatting or allowed_table_formatting, always ensure 'unstyled' is the first item in the array`),
|
|
57
|
+
}, async ({ codename, operations }) => {
|
|
58
|
+
const client = createMapiClient();
|
|
59
|
+
try {
|
|
60
|
+
// Apply patch operations using the modifyContentType method
|
|
61
|
+
const response = await client
|
|
62
|
+
.modifyContentType()
|
|
63
|
+
.byTypeCodename(codename)
|
|
64
|
+
.withData(operations)
|
|
65
|
+
.toPromise();
|
|
66
|
+
return createMcpToolSuccessResponse({
|
|
67
|
+
message: `Content type '${codename}' updated successfully with ${operations.length} operation(s)`,
|
|
68
|
+
contentType: response.rawData,
|
|
69
|
+
appliedOperations: operations,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
return handleMcpToolError(error, `Content Type Patch`);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
};
|