@kontent-ai/mcp-server 0.2.0 → 0.4.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 CHANGED
@@ -5,9 +5,9 @@ This server provides a Model Context Protocol (MCP) interface for interacting wi
5
5
  ## Features
6
6
 
7
7
  - Retrieve content items, variants, and assets
8
- - Get content types and their structure
9
8
  - List available languages and assets
10
- - Create new content types and snippets
9
+ - Get, List, and Create content types and snippets
10
+ - Get, List, and Create taxonomies
11
11
 
12
12
  ## Getting Started
13
13
 
@@ -16,41 +16,53 @@ This server provides a Model Context Protocol (MCP) interface for interacting wi
16
16
  - Node.js (version specified in `.nvmrc`)
17
17
  - Kontent.ai account with API keys
18
18
 
19
- ### Environment Variables
19
+ ### Running
20
20
 
21
- The following environment variables are needed:
21
+ You can run this server with either stdio or sse transport.
22
22
 
23
- ```
24
- KONTENT_ENVIRONMENT_ID=your_environment_id
25
- KONTENT_API_KEY=your_api_key
23
+ ### Stdio transport
24
+
25
+ To run the server with stdio transport configure your MCP client with the command to run and the necessary environment variables.
26
+ Example:
27
+ ```json
28
+ {
29
+ "kontent-ai-stdio": {
30
+ "command": "npx @kontent-ai/mcp-server@latest stdio",
31
+ "env": {
32
+ "KONTENT_API_KEY": "<management-api-key>",
33
+ "KONTENT_ENVIRONMENT_ID": "<environment-id>"
34
+ }
35
+ }
36
+ }
26
37
  ```
27
38
 
28
- ### Using with npx
39
+ ### SSE transport
29
40
 
30
- You can run the server directly with npx:
41
+ You can also run your server manually with the SSE transport and configure your MCP client to connect to the port the server is running on.
42
+ Run the following command to start the server and ensure the environment variables are defined for it either by providing `.env` file in the `cwd` or providing the variables to the process any other way.
31
43
 
32
44
  ```bash
33
- # Run with SSE transport
34
- npx @kontent-ai/mcp-server sse
35
-
36
- # Run with STDIO transport
37
- npx @kontent-ai/mcp-server stdio
45
+ npx @kontent-ai/mcp-server@latest sse
46
+ ```
47
+ ```env
48
+ KONTENT_API_KEY=<management-api-key>
49
+ KONTENT_ENVIRONMENT_ID=<environment-id>
50
+ PORT=<port-number> # optionally specify port, defaults to 3001
38
51
  ```
39
52
 
40
- ### Example mcp.json usage
41
-
53
+ Then configure your MCP client to connect to the running server.
54
+ Example:
42
55
  ```json
43
56
  {
44
- "kontent-ai-stdio": {
45
- "command": "npx @kontent-ai/mcp stdio",
46
- "env": {
47
- "KONTENT_API_KEY": "<management-api-key>",
48
- "KONTENT_ENVIRONMENT_ID": "<environment-id>"
49
- }
50
- },
57
+ "kontent-ai-sse": {
58
+ "url": "http://localhost:3001/sse"
59
+ }
51
60
  }
52
61
  ```
53
62
 
63
+
64
+ ## Development
65
+
54
66
  ### Local Installation
55
67
 
56
68
  ```bash
@@ -69,8 +81,6 @@ npm run start:sse # For SSE transport
69
81
  npm run start:stdio # For STDIO transport
70
82
  ```
71
83
 
72
- ## Development
73
-
74
84
  ### Available Scripts
75
85
 
76
86
  - `npm run build` - Compile TypeScript to JavaScript
@@ -1,4 +1,9 @@
1
1
  import { createManagementClient } from '@kontent-ai/management-sdk';
2
+ import { readFileSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ const packageJsonPath = join(import.meta.dirname, '../../package.json');
5
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
6
+ const sourceTrackingHeaderName = 'X-KC-SOURCE';
2
7
  /**
3
8
  * Creates a Kontent.ai Management API client
4
9
  * @param environmentId Optional environment ID (defaults to process.env.KONTENT_ENVIRONMENT_ID)
@@ -9,6 +14,10 @@ export const createMapiClient = (environmentId, apiKey) => {
9
14
  return createManagementClient({
10
15
  apiKey: apiKey ?? process.env.KONTENT_API_KEY ?? throwError("KONTENT_API_KEY is not set"),
11
16
  environmentId: environmentId ?? process.env.KONTENT_ENVIRONMENT_ID ?? throwError("KONTENT_ENVIRONMENT_ID is not set"),
17
+ headers: [{
18
+ header: sourceTrackingHeaderName,
19
+ value: `${packageJson.name};${packageJson.version}`,
20
+ }],
12
21
  });
13
22
  };
14
23
  const throwError = (message) => {
@@ -8,7 +8,9 @@ const referenceObjectSchema = z.object({
8
8
  const baseElementSchema = {
9
9
  codename: z.string().optional(),
10
10
  external_id: z.string().optional(),
11
- content_group: referenceObjectSchema.optional(),
11
+ content_group: referenceObjectSchema
12
+ .describe("An object with an id or codename property referencing a content group.")
13
+ .optional(),
12
14
  };
13
15
  const namedElementSchema = {
14
16
  ...baseElementSchema,
@@ -61,120 +63,131 @@ const textLengthLimitSchema = z.object({
61
63
  value: z.number(),
62
64
  applies_to: z.enum(['words', 'characters'])
63
65
  }).optional();
66
+ // Individual element type schemas
67
+ const assetElementSchema = z.object({
68
+ type: z.literal('asset'),
69
+ ...namedElementSchema,
70
+ asset_count_limit: countLimitSchema,
71
+ maximum_file_size: z.number().optional(),
72
+ allowed_file_types: z.enum(['adjustable', 'any']).optional(),
73
+ ...imageLimitSchema,
74
+ default: arrayDefaultSchema(),
75
+ });
76
+ const customElementSchema = z.object({
77
+ type: z.literal('custom'),
78
+ ...namedElementSchema,
79
+ source_url: z.string(),
80
+ 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'),
86
+ ...namedElementSchema,
87
+ default: stringDefaultSchema,
88
+ });
89
+ const guidelinesElementSchema = z.object({
90
+ type: z.literal('guidelines'),
91
+ guidelines: z.string(),
92
+ ...baseElementSchema,
93
+ });
94
+ const modularContentElementSchema = z.object({
95
+ type: z.literal('modular_content'),
96
+ ...namedElementSchema,
97
+ allowed_content_types: z.array(referenceObjectSchema
98
+ .describe("An object with an id or codename property referencing a content type.")).optional(),
99
+ item_count_limit: countLimitSchema,
100
+ default: arrayDefaultSchema(),
101
+ });
102
+ const subpagesElementSchema = z.object({
103
+ type: z.literal('subpages'),
104
+ ...namedElementSchema,
105
+ allowed_content_types: z.array(referenceObjectSchema
106
+ .describe("An object with an id or codename property referencing a content type.")).optional(),
107
+ item_count_limit: countLimitSchema,
108
+ });
109
+ const multipleChoiceElementSchema = z.object({
110
+ type: z.literal('multiple_choice'),
111
+ ...namedElementSchema,
112
+ mode: z.enum(['single', 'multiple']),
113
+ options: z.array(z.object({
114
+ name: z.string(),
115
+ codename: z.string().optional(),
116
+ external_id: z.string().optional(),
117
+ })),
118
+ default: arrayDefaultSchema(),
119
+ });
120
+ const numberElementSchema = z.object({
121
+ type: z.literal('number'),
122
+ ...namedElementSchema,
123
+ default: numberDefaultSchema,
124
+ });
125
+ const richTextElementSchema = z.object({
126
+ type: z.literal('rich_text'),
127
+ ...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(),
138
+ ...imageLimitSchema,
139
+ allowed_image_types: z.enum(['adjustable', 'any']).optional(),
140
+ maximum_image_size: z.number().optional(),
141
+ 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."),
147
+ ...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."),
153
+ ...namedElementSchema,
154
+ term_count_limit: countLimitSchema,
155
+ default: arrayDefaultSchema(),
156
+ });
157
+ const textElementSchema = z.object({
158
+ type: z.literal('text'),
159
+ ...namedElementSchema,
160
+ maximum_text_length: textLengthLimitSchema,
161
+ validation_regex: regexValidationSchema,
162
+ default: stringDefaultSchema,
163
+ });
164
+ const urlSlugElementSchema = z.object({
165
+ type: z.literal('url_slug'),
166
+ ...namedElementSchema,
167
+ depends_on: z.object({
168
+ element: referenceObjectSchema
169
+ .describe("An object with an id or codename property referencing an element."),
170
+ snippet: referenceObjectSchema
171
+ .describe("An object with an id or codename property referencing a content type snippet.")
172
+ .optional(),
173
+ }),
174
+ validation_regex: regexValidationSchema,
175
+ });
64
176
  // Define a union type of all possible element types for content types
65
- export const elementSchema = z.union([
66
- // Asset element
67
- z.object({
68
- type: z.literal('asset'),
69
- ...namedElementSchema,
70
- asset_count_limit: countLimitSchema,
71
- maximum_file_size: z.number().optional(),
72
- allowed_file_types: z.enum(['adjustable', 'any']).optional(),
73
- ...imageLimitSchema,
74
- default: arrayDefaultSchema(),
75
- }),
76
- // Custom element
77
- z.object({
78
- type: z.literal('custom'),
79
- ...namedElementSchema,
80
- source_url: z.string(),
81
- json_parameters: z.string().optional(),
82
- allowed_elements: z.array(referenceObjectSchema).optional(),
83
- }),
84
- // Date time element
85
- z.object({
86
- type: z.literal('date_time'),
87
- ...namedElementSchema,
88
- default: stringDefaultSchema,
89
- }),
90
- // Guidelines element
91
- z.object({
92
- type: z.literal('guidelines'),
93
- guidelines: z.string(),
94
- ...baseElementSchema,
95
- }),
96
- // Linked items (modular content) element
97
- z.object({
98
- type: z.literal('modular_content'),
99
- ...namedElementSchema,
100
- allowed_content_types: z.array(referenceObjectSchema).optional(),
101
- item_count_limit: countLimitSchema,
102
- default: arrayDefaultSchema(),
103
- }),
104
- // Subpages element
105
- z.object({
106
- type: z.literal('subpages'),
107
- ...namedElementSchema,
108
- allowed_content_types: z.array(referenceObjectSchema).optional(),
109
- item_count_limit: countLimitSchema,
110
- }),
111
- // Multiple choice element
112
- z.object({
113
- type: z.literal('multiple_choice'),
114
- ...namedElementSchema,
115
- mode: z.enum(['single', 'multiple']),
116
- options: z.array(z.object({
117
- name: z.string(),
118
- codename: z.string().optional(),
119
- external_id: z.string().optional(),
120
- })),
121
- default: arrayDefaultSchema(),
122
- }),
123
- // Number element
124
- z.object({
125
- type: z.literal('number'),
126
- ...namedElementSchema,
127
- default: numberDefaultSchema,
128
- }),
129
- // Rich text element
130
- z.object({
131
- type: z.literal('rich_text'),
132
- ...namedElementSchema,
133
- allowed_blocks: z.array(z.enum(['images', 'text', 'tables', 'components-and-items'])).optional(),
134
- allowed_formatting: z.array(z.enum(['unstyled', 'bold', 'italic', 'code', 'link', 'subscript', 'superscript'])).optional(),
135
- 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(),
136
- allowed_table_blocks: z.array(z.enum(['images', 'text'])).optional(),
137
- allowed_table_formatting: z.array(z.enum(['unstyled', 'bold', 'italic', 'code', 'link', 'subscript', 'superscript'])).optional(),
138
- 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(),
139
- allowed_content_types: z.array(referenceObjectSchema).optional(),
140
- allowed_item_link_types: z.array(referenceObjectSchema).optional(),
141
- ...imageLimitSchema,
142
- allowed_image_types: z.enum(['adjustable', 'any']).optional(),
143
- maximum_image_size: z.number().optional(),
144
- maximum_text_length: textLengthLimitSchema,
145
- }),
146
- // Snippet element
147
- z.object({
148
- type: z.literal('snippet'),
149
- snippet: referenceObjectSchema,
150
- ...baseElementSchema,
151
- }),
152
- // Taxonomy element
153
- z.object({
154
- type: z.literal('taxonomy'),
155
- taxonomy_group: referenceObjectSchema,
156
- ...namedElementSchema,
157
- term_count_limit: countLimitSchema,
158
- default: arrayDefaultSchema(),
159
- }),
160
- // Text element
161
- z.object({
162
- type: z.literal('text'),
163
- ...namedElementSchema,
164
- maximum_text_length: textLengthLimitSchema,
165
- validation_regex: regexValidationSchema,
166
- default: stringDefaultSchema,
167
- }),
168
- // URL slug element
169
- z.object({
170
- type: z.literal('url_slug'),
171
- ...namedElementSchema,
172
- depends_on: z.object({
173
- element: referenceObjectSchema,
174
- snippet: referenceObjectSchema.optional(),
175
- }),
176
- validation_regex: regexValidationSchema,
177
- }),
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,
178
191
  ]);
179
192
  // Define schema for content groups
180
193
  export const contentGroupSchema = z.object({
@@ -183,101 +196,16 @@ export const contentGroupSchema = z.object({
183
196
  codename: z.string().optional(),
184
197
  });
185
198
  // Define a union type for snippet elements (excluding url_slug and snippet elements)
186
- export const snippetElementSchema = z.union([
187
- // Asset element
188
- z.object({
189
- type: z.literal('asset'),
190
- ...namedElementSchema,
191
- asset_count_limit: countLimitSchema,
192
- maximum_file_size: z.number().optional(),
193
- allowed_file_types: z.enum(['adjustable', 'any']).optional(),
194
- ...imageLimitSchema,
195
- default: arrayDefaultSchema(),
196
- }),
197
- // Custom element
198
- z.object({
199
- type: z.literal('custom'),
200
- ...namedElementSchema,
201
- source_url: z.string(),
202
- json_parameters: z.string().optional(),
203
- allowed_elements: z.array(referenceObjectSchema).optional(),
204
- }),
205
- // Date time element
206
- z.object({
207
- type: z.literal('date_time'),
208
- ...namedElementSchema,
209
- default: stringDefaultSchema,
210
- }),
211
- // Guidelines element
212
- z.object({
213
- type: z.literal('guidelines'),
214
- guidelines: z.string(),
215
- ...baseElementSchema,
216
- }),
217
- // Linked items (modular content) element
218
- z.object({
219
- type: z.literal('modular_content'),
220
- ...namedElementSchema,
221
- allowed_content_types: z.array(referenceObjectSchema).optional(),
222
- item_count_limit: countLimitSchema,
223
- default: arrayDefaultSchema(),
224
- }),
225
- // Subpages element
226
- z.object({
227
- type: z.literal('subpages'),
228
- ...namedElementSchema,
229
- allowed_content_types: z.array(referenceObjectSchema).optional(),
230
- item_count_limit: countLimitSchema,
231
- }),
232
- // Multiple choice element
233
- z.object({
234
- type: z.literal('multiple_choice'),
235
- ...namedElementSchema,
236
- mode: z.enum(['single', 'multiple']),
237
- options: z.array(z.object({
238
- name: z.string(),
239
- codename: z.string().optional(),
240
- external_id: z.string().optional(),
241
- })),
242
- default: arrayDefaultSchema(),
243
- }),
244
- // Number element
245
- z.object({
246
- type: z.literal('number'),
247
- ...namedElementSchema,
248
- default: numberDefaultSchema,
249
- }),
250
- // Rich text element
251
- z.object({
252
- type: z.literal('rich_text'),
253
- ...namedElementSchema,
254
- allowed_blocks: z.array(z.enum(['images', 'text', 'tables', 'components-and-items'])).optional(),
255
- allowed_formatting: z.array(z.enum(['unstyled', 'bold', 'italic', 'code', 'link', 'subscript', 'superscript'])).optional(),
256
- 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(),
257
- allowed_table_blocks: z.array(z.enum(['images', 'text'])).optional(),
258
- allowed_table_formatting: z.array(z.enum(['unstyled', 'bold', 'italic', 'code', 'link', 'subscript', 'superscript'])).optional(),
259
- 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(),
260
- allowed_content_types: z.array(referenceObjectSchema).optional(),
261
- allowed_item_link_types: z.array(referenceObjectSchema).optional(),
262
- ...imageLimitSchema,
263
- allowed_image_types: z.enum(['adjustable', 'any']).optional(),
264
- maximum_image_size: z.number().optional(),
265
- maximum_text_length: textLengthLimitSchema,
266
- }),
267
- // Taxonomy element
268
- z.object({
269
- type: z.literal('taxonomy'),
270
- taxonomy_group: referenceObjectSchema,
271
- ...namedElementSchema,
272
- term_count_limit: countLimitSchema,
273
- default: arrayDefaultSchema(),
274
- }),
275
- // Text element
276
- z.object({
277
- type: z.literal('text'),
278
- ...namedElementSchema,
279
- maximum_text_length: textLengthLimitSchema,
280
- validation_regex: regexValidationSchema,
281
- default: stringDefaultSchema,
282
- }),
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,
283
211
  ]);
@@ -0,0 +1,15 @@
1
+ import { z } from "zod";
2
+ // Schema for a taxonomy term
3
+ const taxonomyTermSchema = z.object({
4
+ name: z.string(),
5
+ codename: z.string().optional(),
6
+ external_id: z.string().optional(),
7
+ terms: z.lazy(() => z.array(taxonomyTermSchema)),
8
+ });
9
+ // Schema for a taxonomy group
10
+ export const taxonomyGroupSchemas = {
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"),
15
+ };
package/build/server.js CHANGED
@@ -9,6 +9,11 @@ import { registerTool as registerGetAssetMapi } from "./tools/get-asset-mapi.js"
9
9
  import { registerTool as registerListAssetsMapi } from "./tools/list-assets-mapi.js";
10
10
  import { registerTool as registerAddContentTypeMapi } from "./tools/add-content-type-mapi.js";
11
11
  import { registerTool as registerAddContentTypeSnippetMapi } from "./tools/add-content-type-snippet-mapi.js";
12
+ import { registerTool as registerGetTypeSnippetMapi } from "./tools/get-type-snippet-mapi.js";
13
+ import { registerTool as registerListContentTypeSnippetsMapi } from "./tools/list-content-type-snippets-mapi.js";
14
+ import { registerTool as registerAddTaxonomyGroupMapi } from "./tools/add-taxonomy-group-mapi.js";
15
+ import { registerTool as registerListTaxonomyGroupsMapi } from "./tools/list-taxonomy-groups-mapi.js";
16
+ import { registerTool as registerGetTaxonomyGroupMapi } from "./tools/get-taxonomy-group-mapi.js";
12
17
  // Create server instance
13
18
  export const createServer = () => {
14
19
  const server = new McpServer({
@@ -30,5 +35,10 @@ export const createServer = () => {
30
35
  registerListAssetsMapi(server);
31
36
  registerAddContentTypeMapi(server);
32
37
  registerAddContentTypeSnippetMapi(server);
38
+ registerGetTypeSnippetMapi(server);
39
+ registerListContentTypeSnippetsMapi(server);
40
+ registerAddTaxonomyGroupMapi(server);
41
+ registerListTaxonomyGroupsMapi(server);
42
+ registerGetTaxonomyGroupMapi(server);
33
43
  return { server };
34
44
  };
@@ -0,0 +1,19 @@
1
+ import { createMapiClient } from '../clients/kontentClients.js';
2
+ import { taxonomyGroupSchemas } from '../schemas/taxonomySchemas.js';
3
+ export const registerTool = (server) => {
4
+ server.tool("add-taxonomy-group-mapi", "Add a new taxonomy group via Management API", taxonomyGroupSchemas, async (taxonomyGroup) => {
5
+ const client = createMapiClient();
6
+ const response = await client
7
+ .addTaxonomy()
8
+ .withData(taxonomyGroup)
9
+ .toPromise();
10
+ return {
11
+ content: [
12
+ {
13
+ type: "text",
14
+ text: JSON.stringify(response.data),
15
+ },
16
+ ],
17
+ };
18
+ });
19
+ };
@@ -0,0 +1,21 @@
1
+ import { z } from "zod";
2
+ import { createMapiClient } from '../clients/kontentClients.js';
3
+ export const registerTool = (server) => {
4
+ server.tool("get-taxonomy-group-mapi", "Get taxonomy group by codename from Management API", {
5
+ codename: z.string().describe("Codename of the taxonomy group to get")
6
+ }, async ({ codename }) => {
7
+ const client = createMapiClient();
8
+ const response = await client
9
+ .getTaxonomy()
10
+ .byTaxonomyCodename(codename)
11
+ .toPromise();
12
+ return {
13
+ content: [
14
+ {
15
+ type: "text",
16
+ text: JSON.stringify(response.data),
17
+ },
18
+ ],
19
+ };
20
+ });
21
+ };
@@ -0,0 +1,21 @@
1
+ import { z } from "zod";
2
+ import { createMapiClient } from '../clients/kontentClients.js';
3
+ export const registerTool = (server) => {
4
+ server.tool("get-type-snippet-mapi", "Get content type snippet by codename from Management API", {
5
+ codename: z.string().describe("Codename of the content type snippet to get")
6
+ }, async ({ codename }) => {
7
+ const client = createMapiClient();
8
+ const response = await client
9
+ .viewContentTypeSnippet()
10
+ .byTypeCodename(codename)
11
+ .toPromise();
12
+ return {
13
+ content: [
14
+ {
15
+ type: "text",
16
+ text: JSON.stringify(response.data),
17
+ },
18
+ ],
19
+ };
20
+ });
21
+ };
@@ -0,0 +1,17 @@
1
+ import { createMapiClient } from '../clients/kontentClients.js';
2
+ export const registerTool = (server) => {
3
+ server.tool("list-content-type-snippets-mapi", "Get all content type snippets from Management API", {}, async () => {
4
+ const client = createMapiClient();
5
+ const response = await client
6
+ .listContentTypeSnippets()
7
+ .toAllPromise();
8
+ return {
9
+ content: [
10
+ {
11
+ type: "text",
12
+ text: JSON.stringify(response.data),
13
+ },
14
+ ],
15
+ };
16
+ });
17
+ };
@@ -0,0 +1,17 @@
1
+ import { createMapiClient } from '../clients/kontentClients.js';
2
+ export const registerTool = (server) => {
3
+ server.tool("list-taxonomy-groups-mapi", "Get all taxonomy groups from Management API", {}, async () => {
4
+ const client = createMapiClient();
5
+ const response = await client
6
+ .listTaxonomies()
7
+ .toPromise();
8
+ return {
9
+ content: [
10
+ {
11
+ type: "text",
12
+ text: JSON.stringify(response.data),
13
+ },
14
+ ],
15
+ };
16
+ });
17
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kontent-ai/mcp-server",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "build": "tsc",
@@ -17,16 +17,16 @@
17
17
  "author": "Jiri Lojda",
18
18
  "license": "MIT",
19
19
  "dependencies": {
20
- "@kontent-ai/delivery-sdk": "^16.1.0",
20
+ "@kontent-ai/delivery-sdk": "^16.2.0",
21
21
  "@kontent-ai/management-sdk": "^7.9.0",
22
- "@modelcontextprotocol/sdk": "^1.9.0",
22
+ "@modelcontextprotocol/sdk": "^1.11.4",
23
23
  "dotenv": "^16.5.0",
24
24
  "express": "^5.1.0",
25
- "zod": "^3.24.2"
25
+ "zod": "^3.25.7"
26
26
  },
27
27
  "devDependencies": {
28
- "@types/express": "^5.0.1",
29
- "@types/node": "^22.14.1",
28
+ "@types/express": "^5.0.2",
29
+ "@types/node": "^22.15.19",
30
30
  "typescript": "^5.8.3"
31
31
  }
32
32
  }