@kontent-ai/mcp-server 0.20.0 → 0.21.1

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
@@ -91,7 +91,7 @@ npx @kontent-ai/mcp-server@latest shttp
91
91
  * **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
92
92
  * **create-variant-version-mapi** – Create new version of Kontent.ai language variant via Management API. This operation creates a new version of an existing language variant, useful for content versioning and creating new drafts from published content
93
93
  * **delete-language-variant-mapi** – Delete Kontent.ai language variant from Management API
94
- * **filter-variants-mapi** – Filter Kontent.ai language variants of content items using Management API. Use for exact keyword matching and finding specific terms in content. Supports full filtering capabilities (content types, workflow steps, taxonomies, etc.)
94
+ * **filter-variants-mapi** – Filter Kontent.ai language variants of content items using Management API. Use for exact keyword matching and finding specific terms in content. Supports full filtering capabilities (content types, workflow steps, taxonomies, etc.) and optionally includes full content of variants
95
95
  * **search-variants-mapi** – AI-powered semantic search for finding content by meaning and concepts in a specific language variant. Use for: conceptual searches when you don't know exact keywords. Limited filtering options (variant ID only)
96
96
 
97
97
  ### Asset Management
@@ -1,9 +1,18 @@
1
1
  import { z } from "zod";
2
2
  import { referenceObjectSchema } from "./referenceObjectSchema.js";
3
- const userReferenceSchema = z.object({
4
- id: z.string().optional().describe("User identifier"),
5
- email: z.string().email().optional().describe("User email address"),
6
- });
3
+ // UserReferenceDataContract is a union type - either id or email, but not both
4
+ const userReferenceSchema = z
5
+ .union([
6
+ z.object({
7
+ id: z.string().describe("User identifier"),
8
+ email: z.never().optional(),
9
+ }),
10
+ z.object({
11
+ id: z.never().optional(),
12
+ email: z.string().email().describe("User email address"),
13
+ }),
14
+ ])
15
+ .describe("Reference to a user by either their id or email (but not both)");
7
16
  // Search variants tool input schema
8
17
  export const filterVariantsSchema = z.object({
9
18
  search_phrase: z
@@ -19,13 +28,13 @@ export const filterVariantsSchema = z.object({
19
28
  .array(userReferenceSchema)
20
29
  .min(1)
21
30
  .optional()
22
- .describe("Array of references to users by their id or email"),
31
+ .describe("Array of references to users by their id or email (but not both per user)"),
23
32
  has_no_contributors: z
24
33
  .boolean()
25
34
  .optional()
26
35
  .describe("Filter for content item language variants that have no contributors assigned"),
27
36
  completion_statuses: z
28
- .array(z.enum(["unfinished", "completed", "not_translated", "all_done"]))
37
+ .array(z.enum(["unfinished", "ready", "not_translated", "all_done"]))
29
38
  .min(1)
30
39
  .optional()
31
40
  .describe("Array of completion statuses to filter by. It is not the same thing as workflow steps, it reflects e.g. not filled in required elements"),
@@ -48,24 +57,26 @@ export const filterVariantsSchema = z.object({
48
57
  taxonomy_identifier: referenceObjectSchema.describe("Reference to a taxonomy group by its id, codename, or external id"),
49
58
  term_identifiers: z
50
59
  .array(referenceObjectSchema)
60
+ .optional()
51
61
  .describe("Array of references to taxonomy terms by their id, codename, or external id"),
52
62
  include_uncategorized: z
53
63
  .boolean()
64
+ .optional()
54
65
  .describe("Whether to include content item language variants that don't have any taxonomy terms assigned in this taxonomy group"),
55
66
  }))
56
67
  .min(1)
57
68
  .optional()
58
69
  .describe("Array of taxonomy groups with taxonomy terms"),
59
70
  order_by: z
60
- .enum(["name", "due", "last_modified"])
71
+ .enum(["name", "due_date", "last_modified"])
61
72
  .optional()
62
73
  .describe("Field to order by"),
63
74
  order_direction: z
64
75
  .enum(["asc", "desc"])
65
76
  .optional()
66
77
  .describe("Order direction"),
67
- continuation_token: z
68
- .string()
78
+ include_content: z
79
+ .boolean()
69
80
  .optional()
70
- .describe("Continuation token for pagination"),
81
+ .describe("Whether to include the full content of language variants in the response"),
71
82
  });
@@ -149,8 +149,8 @@ All MCP tools have been optimized to work with internal IDs for maximum efficien
149
149
 
150
150
  ### Content Search Tools
151
151
 
152
- The MCP server provides two search tools with distinct purposes:
153
- - **filter-variants-mapi**: Exact keyword matching with advanced filtering capabilities
154
- - **search-variants-mapi**: AI-powered semantic/conceptual search (when available)
152
+ **CRITICAL DISTINCTION**:
153
+ - **search-variants-mapi**: Finds content WHERE THE MAIN TOPIC matches a concept (e.g., "articles about wildlife")
154
+ - **filter-variants-mapi**: Finds SPECIFIC WORDS anywhere in content, regardless of topic (e.g., brand compliance, detecting prohibited terms in any content)
155
155
 
156
- See each tool's description for detailed usage guidelines and selection criteria.`;
156
+ See each tool's description for detailed usage guidelines.`;
@@ -5,22 +5,27 @@ import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
5
5
  import { throwError } from "../utils/throwError.js";
6
6
  export const registerTool = (server) => {
7
7
  server.tool("filter-variants-mapi", `Filter Kontent.ai language variants of content items using Management API.
8
-
8
+
9
9
  USE FOR:
10
- - EXACT keyword matching: finding specific words, phrases, names, codes, or IDs in content. Example: 'find items containing rabbit' → search 'rabbit'
11
- - Advanced filtering by content type, contributors, workflow steps, taxonomies etc
10
+ - EXACT keyword matching: finding specific words, phrases, names, codes, or IDs anywhere in content, regardless of overall topic
11
+ Example: 'find items containing rabbit' search 'rabbit'
12
+ - Brand guideline compliance: detecting prohibited terms across all content
13
+ ✓ Example: Search "hunt beast prey" to find content containing ANY of these terms (natural OR operator)
12
14
  - CAN expand concepts to keywords when using filter (e.g., "neurology-related" → "neurology neurological brain nervous system")
13
- - Also use as fallback when AI search is unavailable`, filterVariantsSchema.shape, async ({ search_phrase, content_types, contributors, has_no_contributors, completion_statuses, language, workflow_steps, taxonomy_groups, order_by, order_direction, continuation_token, }, { authInfo: { token, clientId } = {} }) => {
15
+ - Advanced filtering by content type, contributors, workflow steps, taxonomies etc
16
+ - Also use as fallback when AI search is unavailable
17
+ - Optionally includes full content of variants with include_content parameter
18
+
19
+ BEST FOR: Finding needles in haystacks - specific words in otherwise unrelated content. Multiple search terms use OR logic.`, filterVariantsSchema.shape, async ({ search_phrase, content_types, contributors, has_no_contributors, completion_statuses, language, workflow_steps, taxonomy_groups, order_by, order_direction, include_content, }, { authInfo: { token, clientId } = {} }) => {
14
20
  try {
15
21
  const environmentId = clientId ?? process.env.KONTENT_ENVIRONMENT_ID;
16
22
  if (!environmentId) {
17
23
  throwError("Missing required environment ID");
18
24
  }
19
- const additionalHeaders = continuation_token
20
- ? [{ header: "X-Continuation", value: continuation_token }]
21
- : undefined;
22
- const client = createMapiClient(environmentId, token, additionalHeaders);
23
- const requestPayload = {
25
+ const client = createMapiClient(environmentId, token);
26
+ const response = await client.earlyAccess
27
+ .filterLanguageVariants()
28
+ .withData({
24
29
  filters: {
25
30
  search_phrase,
26
31
  content_types,
@@ -34,19 +39,16 @@ export const registerTool = (server) => {
34
39
  order: order_by
35
40
  ? {
36
41
  by: order_by,
37
- direction: order_direction === "desc" ? "Descending" : "Ascending",
42
+ direction: order_direction || "asc",
38
43
  }
39
- : null,
40
- };
41
- const response = await client
42
- .post()
43
- .withAction(`projects/${environmentId}/early-access/variants/filter`)
44
- .withData(requestPayload)
45
- .toPromise();
46
- return createMcpToolSuccessResponse(response.data);
44
+ : undefined,
45
+ include_content: include_content ?? false,
46
+ })
47
+ .toAllPromise();
48
+ return createMcpToolSuccessResponse(response.responses.flatMap((r) => r.rawData.data));
47
49
  }
48
50
  catch (error) {
49
- return handleMcpToolError(error, "Variant Search");
51
+ return handleMcpToolError(error, "Variant Filter");
50
52
  }
51
53
  });
52
54
  };
@@ -6,7 +6,7 @@ import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
6
6
  import { throwError } from "../utils/throwError.js";
7
7
  export const registerTool = (server) => {
8
8
  server.tool("search-variants-mapi", `AI-powered semantic search for finding Kontent.ai content by meaning, concepts, themes, and content similarity in a specific language variant. This tool uses vector database and AI to enable searching by meaning and similarity rather than exact keyword matching.
9
-
9
+
10
10
  CRITICAL REQUIREMENTS:
11
11
  - The AI search feature may not be available for all Kontent.ai environments
12
12
  - If you receive an "unavailable" status response, DO NOT attempt to use this tool again in the same session
@@ -14,12 +14,24 @@ export const registerTool = (server) => {
14
14
  - Requires language variant filter parameter (e.g., default language '00000000-0000-0000-0000-000000000000')
15
15
  - The tool always RETURNS ONLY TOP 50 most relevant items at max
16
16
  - Limited filtering options (only by variant ID) - use filter-variants-mapi for advanced filtering by content types, workflow steps, taxonomies, etc.
17
-
17
+
18
18
  USE FOR:
19
- - Conceptual search: NEVER extract keywords, pass the single concept/theme as-is (e.g., "find content about keeping beverages cold" → searchPhrase: "beverage coolers")
20
- - Finding content about topics: Use topic as-is (e.g., "find fairy tales" → searchPhrase: "fairy tales")
21
- - Content similarity: Find articles similar to a given topic or story theme (e.g. "<<larger piece of content to search similar items>>" -> searchPhrase: "<<larger piece of content to search similar items>>")
22
- - Thematic content discovery based on meaning and context`, searchOperationSchema.shape, async ({ searchPhrase, filter }, { authInfo: { token, clientId } = {} }) => {
19
+ - Finding content WHERE THE OVERALL TOPIC/THEME matches a concept
20
+ Example: "fairy tales" → finds articles primarily about fairy tales
21
+ Example: "beverage temperature control" finds content focused on keeping drinks cold/hot
22
+ - Content similarity: Finding articles with similar overall themes
23
+ - Thematic content discovery when the main subject matter is what you're looking for
24
+
25
+ DO NOT USE FOR:
26
+ - Finding specific words scattered in otherwise unrelated content
27
+ ✗ Example: Finding "challenge" term in articles about various topics (use filter-variants-mapi)
28
+ - Brand guideline violations or prohibited term detection (use filter-variants-mapi)
29
+ - Compliance audits looking for specific keywords (use filter-variants-mapi)
30
+ - Finding exhaustive and exact number of results (use filter-variants-mapi)
31
+
32
+ CRITICAL: This is SEMANTIC search for topic matching. Pass natural language concepts AS-IS. DO NOT generate keyword lists or concatenate multiple keywords.
33
+ ✓ CORRECT: "animal predators" or "articles about temperature control"
34
+ ✗ WRONG: "animal beast creature wild hunt predator prey attack"`, searchOperationSchema.shape, async ({ searchPhrase, filter }, { authInfo: { token, clientId } = {} }) => {
23
35
  try {
24
36
  const environmentId = clientId ?? process.env.KONTENT_ENVIRONMENT_ID;
25
37
  if (!environmentId) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kontent-ai/mcp-server",
3
- "version": "0.20.0",
3
+ "version": "0.21.1",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "build": "rimraf build && tsc",
@@ -8,8 +8,8 @@
8
8
  "start:shttp": "node build/bin.js shttp",
9
9
  "dev:stdio": "tsx watch src/bin.ts stdio",
10
10
  "dev:shttp": "tsx watch src/bin.ts shttp",
11
- "format": "cross-env node node_modules/@biomejs/biome/bin/biome ci ./ --config-path=./biome.json",
12
- "format:fix": "cross-env node node_modules/@biomejs/biome/bin/biome check ./ --fix --unsafe --config-path=./biome.json"
11
+ "format": "cross-env node node_modules/@biomejs/biome/bin/biome ci ./",
12
+ "format:fix": "cross-env node node_modules/@biomejs/biome/bin/biome check ./ --fix --unsafe"
13
13
  },
14
14
  "bin": {
15
15
  "@kontent-ai/mcp-server": "./build/bin.js"
@@ -21,7 +21,7 @@
21
21
  "author": "Jiri Lojda",
22
22
  "license": "MIT",
23
23
  "dependencies": {
24
- "@kontent-ai/management-sdk": "^7.9.0",
24
+ "@kontent-ai/management-sdk": "^7.11.0",
25
25
  "@modelcontextprotocol/sdk": "^1.12.0",
26
26
  "applicationinsights": "^2.9.8",
27
27
  "dotenv": "^16.5.0",