@kontent-ai/mcp-server 0.17.0 → 0.18.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 (33) hide show
  1. package/build/bin.js +9 -7
  2. package/build/clients/kontentClients.js +3 -1
  3. package/build/config/appConfiguration.js +51 -0
  4. package/build/server.js +29 -29
  5. package/build/tools/add-content-item-mapi.js +2 -2
  6. package/build/tools/add-content-type-mapi.js +2 -2
  7. package/build/tools/add-content-type-snippet-mapi.js +2 -2
  8. package/build/tools/add-taxonomy-group-mapi.js +2 -2
  9. package/build/tools/change-variant-workflow-step-mapi.js +2 -2
  10. package/build/tools/create-variant-version-mapi.js +2 -2
  11. package/build/tools/delete-content-item-mapi.js +2 -2
  12. package/build/tools/delete-content-type-mapi.js +2 -2
  13. package/build/tools/delete-language-variant-mapi.js +2 -2
  14. package/build/tools/filter-variants-mapi.js +5 -2
  15. package/build/tools/get-asset-mapi.js +2 -2
  16. package/build/tools/get-item-dapi.js +4 -1
  17. package/build/tools/get-item-mapi.js +2 -2
  18. package/build/tools/get-taxonomy-group-mapi.js +2 -2
  19. package/build/tools/get-type-mapi.js +2 -2
  20. package/build/tools/get-type-snippet-mapi.js +2 -2
  21. package/build/tools/get-variant-mapi.js +2 -2
  22. package/build/tools/list-assets-mapi.js +2 -2
  23. package/build/tools/list-content-type-snippets-mapi.js +2 -2
  24. package/build/tools/list-content-types-mapi.js +2 -2
  25. package/build/tools/list-languages-mapi.js +2 -2
  26. package/build/tools/list-taxonomy-groups-mapi.js +2 -2
  27. package/build/tools/list-workflows-mapi.js +2 -2
  28. package/build/tools/patch-content-type-mapi.js +2 -2
  29. package/build/tools/publish-variant-mapi.js +2 -2
  30. package/build/tools/unpublish-variant-mapi.js +2 -2
  31. package/build/tools/update-content-item-mapi.js +2 -2
  32. package/build/tools/upsert-language-variant-mapi.js +2 -2
  33. package/package.json +5 -1
package/build/bin.js CHANGED
@@ -4,16 +4,17 @@ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/
4
4
  import "dotenv/config";
5
5
  import express from "express";
6
6
  import packageJson from "../package.json" with { type: "json" };
7
+ import { loadAppConfiguration, } from "./config/appConfiguration.js";
7
8
  import { createServer } from "./server.js";
8
9
  import { extractBearerToken } from "./utils/extractBearerToken.js";
9
10
  import { isValidGuid } from "./utils/isValidGuid.js";
10
11
  const version = packageJson.version;
11
- async function startStreamableHTTP() {
12
+ async function startStreamableHTTP(config) {
12
13
  const app = express();
13
14
  app.use(express.json());
14
15
  app.post("/mcp", async (req, res) => {
15
16
  try {
16
- const { server } = createServer();
17
+ const { server } = createServer(config);
17
18
  const transport = new StreamableHTTPServerTransport({
18
19
  sessionIdGenerator: undefined,
19
20
  });
@@ -68,7 +69,7 @@ async function startStreamableHTTP() {
68
69
  });
69
70
  return;
70
71
  }
71
- const { server } = createServer();
72
+ const { server } = createServer(config);
72
73
  const transport = new StreamableHTTPServerTransport({
73
74
  sessionIdGenerator: undefined,
74
75
  });
@@ -135,13 +136,14 @@ Available endpoints:
135
136
  /{environmentId}/mcp (requires Bearer authentication)`);
136
137
  });
137
138
  }
138
- async function startStdio() {
139
- const { server } = createServer();
139
+ async function startStdio(config) {
140
+ const { server } = createServer(config);
140
141
  const transport = new StdioServerTransport();
141
142
  console.log(`Kontent.ai MCP Server v${version} (stdio) starting`);
142
143
  await server.connect(transport);
143
144
  }
144
145
  async function main() {
146
+ const config = await loadAppConfiguration();
145
147
  const args = process.argv.slice(2);
146
148
  const transportType = args[0]?.toLowerCase();
147
149
  if (!transportType ||
@@ -150,10 +152,10 @@ async function main() {
150
152
  process.exit(1);
151
153
  }
152
154
  if (transportType === "stdio") {
153
- await startStdio();
155
+ await startStdio(config);
154
156
  }
155
157
  else if (transportType === "shttp") {
156
- await startStreamableHTTP();
158
+ await startStreamableHTTP(config);
157
159
  }
158
160
  }
159
161
  main().catch((error) => {
@@ -6,9 +6,10 @@ const sourceTrackingHeaderName = "X-KC-SOURCE";
6
6
  * Creates a Kontent.ai Management API client
7
7
  * @param environmentId Optional environment ID (defaults to process.env.KONTENT_ENVIRONMENT_ID)
8
8
  * @param apiKey Optional API key (defaults to process.env.KONTENT_API_KEY)
9
+ * @param config Optional configuration object
9
10
  * @returns Management API client instance
10
11
  */
11
- export const createMapiClient = (environmentId, apiKey) => {
12
+ export const createMapiClient = (environmentId, apiKey, config) => {
12
13
  return createManagementClient({
13
14
  apiKey: apiKey ??
14
15
  process.env.KONTENT_API_KEY ??
@@ -22,5 +23,6 @@ export const createMapiClient = (environmentId, apiKey) => {
22
23
  value: `${packageJson.name};${packageJson.version}`,
23
24
  },
24
25
  ],
26
+ baseUrl: config ? `${config.manageApiUrl}v2` : undefined,
25
27
  });
26
28
  };
@@ -0,0 +1,51 @@
1
+ import { load } from "@azure/app-configuration-provider";
2
+ import { DefaultAzureCredential } from "@azure/identity";
3
+ function loadIndexedEnvVars(prefix) {
4
+ const values = [];
5
+ let index = 0;
6
+ while (true) {
7
+ const envVar = process.env[`${prefix}__${index}`];
8
+ if (!envVar)
9
+ break;
10
+ const trimmed = envVar.trim();
11
+ if (trimmed) {
12
+ values.push(trimmed);
13
+ }
14
+ index++;
15
+ }
16
+ return values;
17
+ }
18
+ function getConfigValue(configMap, key) {
19
+ const value = configMap.get(key);
20
+ return value && typeof value === "string" ? value : undefined;
21
+ }
22
+ export async function loadAppConfiguration() {
23
+ try {
24
+ const appConfigEndpoint = process.env.ConfigStore__Endpoints__0;
25
+ const labels = loadIndexedEnvVars("ConfigStore__Labels");
26
+ if (!appConfigEndpoint || labels.length === 0) {
27
+ return null;
28
+ }
29
+ const selectors = labels.flatMap((label) => [
30
+ { keyFilter: "ApplicationInsights:*", labelFilter: label },
31
+ { keyFilter: "Global:Runtime:*", labelFilter: label },
32
+ { keyFilter: "Draft:ManageApi:*", labelFilter: label },
33
+ { keyFilter: "Deliver:ApiClient:Domains:*", labelFilter: label },
34
+ ]);
35
+ const credential = new DefaultAzureCredential();
36
+ const configMap = await load(appConfigEndpoint, credential, {
37
+ selectors: selectors,
38
+ keyVaultOptions: {
39
+ credential: credential,
40
+ },
41
+ });
42
+ return {
43
+ manageApiUrl: getConfigValue(configMap, "Draft:ManageApi:Url"),
44
+ deliveryApiUrl: getConfigValue(configMap, "Deliver:ApiClient:Domains:LiveContentDomain"),
45
+ };
46
+ }
47
+ catch (error) {
48
+ console.log("Failed to load App Configuration:", error);
49
+ return null;
50
+ }
51
+ }
package/build/server.js CHANGED
@@ -30,7 +30,7 @@ import { registerTool as registerUnpublishVariantMapi } from "./tools/unpublish-
30
30
  import { registerTool as registerUpdateContentItemMapi } from "./tools/update-content-item-mapi.js";
31
31
  import { registerTool as registerUpsertLanguageVariantMapi } from "./tools/upsert-language-variant-mapi.js";
32
32
  // Create server instance
33
- export const createServer = () => {
33
+ export const createServer = (config) => {
34
34
  const server = new McpServer({
35
35
  name: "kontent-ai",
36
36
  version: packageJson.version,
@@ -41,33 +41,33 @@ export const createServer = () => {
41
41
  });
42
42
  // Register all tools
43
43
  registerGetInitialContext(server);
44
- registerGetItemMapi(server);
45
- registerGetItemDapi(server);
46
- registerGetVariantMapi(server);
47
- registerGetTypeMapi(server);
48
- registerListContentTypesMapi(server);
49
- registerDeleteContentTypeMapi(server);
50
- registerListLanguagesMapi(server);
51
- registerGetAssetMapi(server);
52
- registerListAssetsMapi(server);
53
- registerAddContentTypeMapi(server);
54
- registerPatchContentTypeMapi(server);
55
- registerAddContentTypeSnippetMapi(server);
56
- registerGetTypeSnippetMapi(server);
57
- registerListContentTypeSnippetsMapi(server);
58
- registerAddTaxonomyGroupMapi(server);
59
- registerListTaxonomyGroupsMapi(server);
60
- registerGetTaxonomyGroupMapi(server);
61
- registerAddContentItemMapi(server);
62
- registerUpdateContentItemMapi(server);
63
- registerDeleteContentItemMapi(server);
64
- registerUpsertLanguageVariantMapi(server);
65
- registerCreateVariantVersionMapi(server);
66
- registerDeleteLanguageVariantMapi(server);
67
- registerListWorkflowsMapi(server);
68
- registerChangeVariantWorkflowStepMapi(server);
69
- registerFilterVariantsMapi(server);
70
- registerPublishVariantMapi(server);
71
- registerUnpublishVariantMapi(server);
44
+ registerGetItemMapi(server, config);
45
+ registerGetItemDapi(server, config);
46
+ registerGetVariantMapi(server, config);
47
+ registerGetTypeMapi(server, config);
48
+ registerListContentTypesMapi(server, config);
49
+ registerDeleteContentTypeMapi(server, config);
50
+ registerListLanguagesMapi(server, config);
51
+ registerGetAssetMapi(server, config);
52
+ registerListAssetsMapi(server, config);
53
+ registerAddContentTypeMapi(server, config);
54
+ registerPatchContentTypeMapi(server, config);
55
+ registerAddContentTypeSnippetMapi(server, config);
56
+ registerGetTypeSnippetMapi(server, config);
57
+ registerListContentTypeSnippetsMapi(server, config);
58
+ registerAddTaxonomyGroupMapi(server, config);
59
+ registerListTaxonomyGroupsMapi(server, config);
60
+ registerGetTaxonomyGroupMapi(server, config);
61
+ registerAddContentItemMapi(server, config);
62
+ registerUpdateContentItemMapi(server, config);
63
+ registerDeleteContentItemMapi(server, config);
64
+ registerUpsertLanguageVariantMapi(server, config);
65
+ registerCreateVariantVersionMapi(server, config);
66
+ registerDeleteLanguageVariantMapi(server, config);
67
+ registerListWorkflowsMapi(server, config);
68
+ registerChangeVariantWorkflowStepMapi(server, config);
69
+ registerFilterVariantsMapi(server, config);
70
+ registerPublishVariantMapi(server, config);
71
+ registerUnpublishVariantMapi(server, config);
72
72
  return { server };
73
73
  };
@@ -2,7 +2,7 @@ import { z } from "zod";
2
2
  import { createMapiClient } from "../clients/kontentClients.js";
3
3
  import { handleMcpToolError } from "../utils/errorHandler.js";
4
4
  import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
5
- export const registerTool = (server) => {
5
+ export const registerTool = (server, config) => {
6
6
  server.tool("add-content-item-mapi", "Add new Kontent.ai 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
7
  name: z
8
8
  .string()
@@ -33,7 +33,7 @@ export const registerTool = (server) => {
33
33
  .optional()
34
34
  .describe("Reference to a collection by id, codename, or external_id (optional)"),
35
35
  }, async ({ name, type, codename, external_id, collection }, { authInfo: { token, clientId } = {} }) => {
36
- const client = createMapiClient(clientId, token);
36
+ const client = createMapiClient(clientId, token, config);
37
37
  try {
38
38
  const response = await client
39
39
  .addContentItem()
@@ -3,7 +3,7 @@ import { createMapiClient } from "../clients/kontentClients.js";
3
3
  import { contentGroupSchema, elementSchema, } from "../schemas/contentTypeSchemas.js";
4
4
  import { handleMcpToolError } from "../utils/errorHandler.js";
5
5
  import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
6
- export const registerTool = (server) => {
6
+ export const registerTool = (server, config) => {
7
7
  server.tool("add-content-type-mapi", "Add new Kontent.ai content type via Management API", {
8
8
  name: z.string().describe("Display name of the content type"),
9
9
  codename: z
@@ -22,7 +22,7 @@ export const registerTool = (server) => {
22
22
  .optional()
23
23
  .describe("Array of content groups (optional)"),
24
24
  }, async ({ name, codename, external_id, elements, content_groups }, { authInfo: { token, clientId } = {} }) => {
25
- const client = createMapiClient(clientId, token);
25
+ const client = createMapiClient(clientId, token, config);
26
26
  try {
27
27
  const response = await client
28
28
  .addContentType()
@@ -3,7 +3,7 @@ import { createMapiClient } from "../clients/kontentClients.js";
3
3
  import { snippetElementSchema } from "../schemas/contentTypeSchemas.js";
4
4
  import { handleMcpToolError } from "../utils/errorHandler.js";
5
5
  import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
6
- export const registerTool = (server) => {
6
+ export const registerTool = (server, config) => {
7
7
  server.tool("add-content-type-snippet-mapi", "Add new Kontent.ai content type snippet via Management API", {
8
8
  name: z.string().describe("Display name of the content type snippet"),
9
9
  codename: z
@@ -18,7 +18,7 @@ export const registerTool = (server) => {
18
18
  .array(snippetElementSchema)
19
19
  .describe("Array of elements that define the structure of the content type snippet"),
20
20
  }, async ({ name, codename, external_id, elements }, { authInfo: { token, clientId } = {} }) => {
21
- const client = createMapiClient(clientId, token);
21
+ const client = createMapiClient(clientId, token, config);
22
22
  try {
23
23
  const response = await client
24
24
  .addContentTypeSnippet()
@@ -2,9 +2,9 @@ import { createMapiClient } from "../clients/kontentClients.js";
2
2
  import { taxonomyGroupSchemas } from "../schemas/taxonomySchemas.js";
3
3
  import { handleMcpToolError } from "../utils/errorHandler.js";
4
4
  import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
5
- export const registerTool = (server) => {
5
+ export const registerTool = (server, config) => {
6
6
  server.tool("add-taxonomy-group-mapi", "Add new Kontent.ai taxonomy group via Management API", taxonomyGroupSchemas, async (taxonomyGroup, { authInfo: { token, clientId } = {} }) => {
7
- const client = createMapiClient(clientId, token);
7
+ const client = createMapiClient(clientId, token, config);
8
8
  try {
9
9
  const response = await client
10
10
  .addTaxonomy()
@@ -2,7 +2,7 @@ import { z } from "zod";
2
2
  import { createMapiClient } from "../clients/kontentClients.js";
3
3
  import { handleMcpToolError } from "../utils/errorHandler.js";
4
4
  import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
5
- export const registerTool = (server) => {
5
+ export const registerTool = (server, config) => {
6
6
  server.tool("change-variant-workflow-step-mapi", "Change the workflow step of a language variant in Kontent.ai. This operation moves a language variant to a different step in the workflow, enabling content lifecycle management such as moving content from draft to review, review to published, etc.", {
7
7
  itemId: z
8
8
  .string()
@@ -21,7 +21,7 @@ export const registerTool = (server) => {
21
21
  .uuid()
22
22
  .describe("Internal ID (UUID) of the target workflow step. This must be a valid step ID from the specified workflow. Common steps include Draft, Review, Published, and Archived, but the actual IDs depend on your specific workflow configuration"),
23
23
  }, async ({ itemId, languageId, workflowId, workflowStepId }, { authInfo: { token, clientId } = {} }) => {
24
- const client = createMapiClient(clientId, token);
24
+ const client = createMapiClient(clientId, token, config);
25
25
  try {
26
26
  const response = await client
27
27
  .changeWorkflowOfLanguageVariant()
@@ -2,7 +2,7 @@ import { z } from "zod";
2
2
  import { createMapiClient } from "../clients/kontentClients.js";
3
3
  import { handleMcpToolError } from "../utils/errorHandler.js";
4
4
  import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
5
- export const registerTool = (server) => {
5
+ export const registerTool = (server, config) => {
6
6
  server.tool("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.", {
7
7
  itemId: z
8
8
  .string()
@@ -13,7 +13,7 @@ export const registerTool = (server) => {
13
13
  .uuid()
14
14
  .describe("Internal ID (UUID) of the language variant to create a new version of. Use '00000000-0000-0000-0000-000000000000' for the default language"),
15
15
  }, async ({ itemId, languageId }, { authInfo: { token, clientId } = {} }) => {
16
- const client = createMapiClient(clientId, token);
16
+ const client = createMapiClient(clientId, token, config);
17
17
  try {
18
18
  const response = await client
19
19
  .createNewVersionOfLanguageVariant()
@@ -2,11 +2,11 @@ import { z } from "zod";
2
2
  import { createMapiClient } from "../clients/kontentClients.js";
3
3
  import { handleMcpToolError } from "../utils/errorHandler.js";
4
4
  import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
5
- export const registerTool = (server) => {
5
+ export const registerTool = (server, config) => {
6
6
  server.tool("delete-content-item-mapi", "Delete Kontent.ai content item by internal ID from Management API", {
7
7
  id: z.string().describe("Internal ID of the content item to delete"),
8
8
  }, async ({ id }, { authInfo: { token, clientId } = {} }) => {
9
- const client = createMapiClient(clientId, token);
9
+ const client = createMapiClient(clientId, token, config);
10
10
  try {
11
11
  const response = await client
12
12
  .deleteContentItem()
@@ -2,11 +2,11 @@ import { z } from "zod";
2
2
  import { createMapiClient } from "../clients/kontentClients.js";
3
3
  import { handleMcpToolError } from "../utils/errorHandler.js";
4
4
  import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
5
- export const registerTool = (server) => {
5
+ export const registerTool = (server, config) => {
6
6
  server.tool("delete-content-type-mapi", "Delete a content type by codename from Management API", {
7
7
  codename: z.string().describe("Codename of the content type to delete"),
8
8
  }, async ({ codename }, { authInfo: { token, clientId } = {} }) => {
9
- const client = createMapiClient(clientId, token);
9
+ const client = createMapiClient(clientId, token, config);
10
10
  try {
11
11
  const response = await client
12
12
  .deleteContentType()
@@ -2,14 +2,14 @@ import { z } from "zod";
2
2
  import { createMapiClient } from "../clients/kontentClients.js";
3
3
  import { handleMcpToolError } from "../utils/errorHandler.js";
4
4
  import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
5
- export const registerTool = (server) => {
5
+ export const registerTool = (server, config) => {
6
6
  server.tool("delete-language-variant-mapi", "Delete Kontent.ai language variant from Management API", {
7
7
  itemId: z.string().describe("Internal ID of the content item"),
8
8
  languageId: z
9
9
  .string()
10
10
  .describe("Internal ID of the language variant to delete"),
11
11
  }, async ({ itemId, languageId }, { authInfo: { token, clientId } = {} }) => {
12
- const client = createMapiClient(clientId, token);
12
+ const client = createMapiClient(clientId, token, config);
13
13
  try {
14
14
  const response = await client
15
15
  .deleteLanguageVariant()
@@ -2,7 +2,7 @@ import { filterVariantsSchema } from "../schemas/filterVariantSchemas.js";
2
2
  import { handleMcpToolError } from "../utils/errorHandler.js";
3
3
  import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
4
4
  import { throwError } from "../utils/throwError.js";
5
- export const registerTool = (server) => {
5
+ export const registerTool = (server, config) => {
6
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, }, { authInfo: { token, clientId } = {} }) => {
7
7
  try {
8
8
  const requestPayload = {
@@ -31,7 +31,10 @@ export const registerTool = (server) => {
31
31
  if (!apiKey) {
32
32
  throwError("Missing required API key");
33
33
  }
34
- const url = `https://manage.kontent.ai/v2/projects/${environmentId}/early-access/variants/filter`;
34
+ const baseUrl = config
35
+ ? `${config.manageApiUrl}`
36
+ : `https://manage.kontent.ai/`;
37
+ const url = `${baseUrl}v2/projects/${environmentId}/early-access/variants/filter`;
35
38
  const headers = {
36
39
  Authorization: `Bearer ${apiKey}`,
37
40
  "Content-Type": "application/json",
@@ -2,11 +2,11 @@ import { z } from "zod";
2
2
  import { createMapiClient } from "../clients/kontentClients.js";
3
3
  import { handleMcpToolError } from "../utils/errorHandler.js";
4
4
  import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
5
- export const registerTool = (server) => {
5
+ export const registerTool = (server, config) => {
6
6
  server.tool("get-asset-mapi", "Get a specific Kontent.ai asset by internal ID from Management API", {
7
7
  assetId: z.string().describe("Internal ID of the asset to retrieve"),
8
8
  }, async ({ assetId }, { authInfo: { token, clientId } = {} }) => {
9
- const client = createMapiClient(clientId, token);
9
+ const client = createMapiClient(clientId, token, config);
10
10
  try {
11
11
  const response = await client
12
12
  .viewAsset()
@@ -2,7 +2,7 @@ import { createDeliveryClient } from "@kontent-ai/delivery-sdk";
2
2
  import { z } from "zod";
3
3
  import { handleMcpToolError } from "../utils/errorHandler.js";
4
4
  import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
5
- export const registerTool = (server) => {
5
+ export const registerTool = (server, config) => {
6
6
  server.tool("get-item-dapi", "Get Kontent.ai item by codename from Delivery API", {
7
7
  codename: z.string().describe("Codename of the item to get"),
8
8
  environmentId: z
@@ -11,6 +11,9 @@ export const registerTool = (server) => {
11
11
  }, async ({ codename, environmentId }) => {
12
12
  const client = createDeliveryClient({
13
13
  environmentId,
14
+ proxy: {
15
+ baseUrl: config ? `https://${config.deliveryApiUrl}` : undefined,
16
+ },
14
17
  });
15
18
  try {
16
19
  const response = await client.item(codename).toPromise();
@@ -2,11 +2,11 @@ import { z } from "zod";
2
2
  import { createMapiClient } from "../clients/kontentClients.js";
3
3
  import { handleMcpToolError } from "../utils/errorHandler.js";
4
4
  import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
5
- export const registerTool = (server) => {
5
+ export const registerTool = (server, config) => {
6
6
  server.tool("get-item-mapi", "Get Kontent.ai item by internal ID from Management API", {
7
7
  id: z.string().describe("Internal ID of the item to get"),
8
8
  }, async ({ id }, { authInfo: { token, clientId } = {} }) => {
9
- const client = createMapiClient(clientId, token);
9
+ const client = createMapiClient(clientId, token, config);
10
10
  try {
11
11
  const response = await client
12
12
  .viewContentItem()
@@ -2,11 +2,11 @@ import { z } from "zod";
2
2
  import { createMapiClient } from "../clients/kontentClients.js";
3
3
  import { handleMcpToolError } from "../utils/errorHandler.js";
4
4
  import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
5
- export const registerTool = (server) => {
5
+ export const registerTool = (server, config) => {
6
6
  server.tool("get-taxonomy-group-mapi", "Get Kontent.ai taxonomy group by internal ID from Management API", {
7
7
  id: z.string().describe("Internal ID of the taxonomy group to get"),
8
8
  }, async ({ id }, { authInfo: { token, clientId } = {} }) => {
9
- const client = createMapiClient(clientId, token);
9
+ const client = createMapiClient(clientId, token, config);
10
10
  try {
11
11
  const response = await client
12
12
  .getTaxonomy()
@@ -2,11 +2,11 @@ import { z } from "zod";
2
2
  import { createMapiClient } from "../clients/kontentClients.js";
3
3
  import { handleMcpToolError } from "../utils/errorHandler.js";
4
4
  import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
5
- export const registerTool = (server) => {
5
+ export const registerTool = (server, config) => {
6
6
  server.tool("get-type-mapi", "Get Kontent.ai content type by internal ID from Management API", {
7
7
  id: z.string().describe("Internal ID of the content type to get"),
8
8
  }, async ({ id }, { authInfo: { token, clientId } = {} }) => {
9
- const client = createMapiClient(clientId, token);
9
+ const client = createMapiClient(clientId, token, config);
10
10
  try {
11
11
  const response = await client
12
12
  .viewContentType()
@@ -2,11 +2,11 @@ import { z } from "zod";
2
2
  import { createMapiClient } from "../clients/kontentClients.js";
3
3
  import { handleMcpToolError } from "../utils/errorHandler.js";
4
4
  import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
5
- export const registerTool = (server) => {
5
+ export const registerTool = (server, config) => {
6
6
  server.tool("get-type-snippet-mapi", "Get Kontent.ai content type snippet by internal ID from Management API", {
7
7
  id: z.string().describe("Internal ID of the content type snippet to get"),
8
8
  }, async ({ id }, { authInfo: { token, clientId } = {} }) => {
9
- const client = createMapiClient(clientId, token);
9
+ const client = createMapiClient(clientId, token, config);
10
10
  try {
11
11
  const response = await client
12
12
  .viewContentTypeSnippet()
@@ -2,14 +2,14 @@ import { z } from "zod";
2
2
  import { createMapiClient } from "../clients/kontentClients.js";
3
3
  import { handleMcpToolError } from "../utils/errorHandler.js";
4
4
  import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
5
- export const registerTool = (server) => {
5
+ export const registerTool = (server, config) => {
6
6
  server.tool("get-variant-mapi", "Get Kontent.ai language variant of content item from Management API", {
7
7
  itemId: z.string().describe("Internal ID of the content item"),
8
8
  languageId: z
9
9
  .string()
10
10
  .describe("Internal ID of the language variant to get"),
11
11
  }, async ({ itemId, languageId }, { authInfo: { token, clientId } = {} }) => {
12
- const client = createMapiClient(clientId, token);
12
+ const client = createMapiClient(clientId, token, config);
13
13
  try {
14
14
  const response = await client
15
15
  .viewLanguageVariant()
@@ -1,9 +1,9 @@
1
1
  import { createMapiClient } from "../clients/kontentClients.js";
2
2
  import { handleMcpToolError } from "../utils/errorHandler.js";
3
3
  import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
4
- export const registerTool = (server) => {
4
+ export const registerTool = (server, config) => {
5
5
  server.tool("list-assets-mapi", "Get all Kontent.ai assets from Management API", {}, async (_, { authInfo: { token, clientId } = {} }) => {
6
- const client = createMapiClient(clientId, token);
6
+ const client = createMapiClient(clientId, token, config);
7
7
  try {
8
8
  const response = await client.listAssets().toAllPromise();
9
9
  return createMcpToolSuccessResponse(response.data);
@@ -1,9 +1,9 @@
1
1
  import { createMapiClient } from "../clients/kontentClients.js";
2
2
  import { handleMcpToolError } from "../utils/errorHandler.js";
3
3
  import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
4
- export const registerTool = (server) => {
4
+ export const registerTool = (server, config) => {
5
5
  server.tool("list-content-type-snippets-mapi", "Get all Kontent.ai content type snippets from Management API", {}, async (_, { authInfo: { token, clientId } = {} }) => {
6
- const client = createMapiClient(clientId, token);
6
+ const client = createMapiClient(clientId, token, config);
7
7
  try {
8
8
  const response = await client.listContentTypeSnippets().toAllPromise();
9
9
  return createMcpToolSuccessResponse(response.data);
@@ -1,9 +1,9 @@
1
1
  import { createMapiClient } from "../clients/kontentClients.js";
2
2
  import { handleMcpToolError } from "../utils/errorHandler.js";
3
3
  import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
4
- export const registerTool = (server) => {
4
+ export const registerTool = (server, config) => {
5
5
  server.tool("list-content-types-mapi", "Get all Kontent.ai content types from Management API", {}, async (_, { authInfo: { token, clientId } = {} }) => {
6
- const client = createMapiClient(clientId, token);
6
+ const client = createMapiClient(clientId, token, config);
7
7
  try {
8
8
  const response = await client.listContentTypes().toAllPromise();
9
9
  return createMcpToolSuccessResponse(response.data);
@@ -1,9 +1,9 @@
1
1
  import { createMapiClient } from "../clients/kontentClients.js";
2
2
  import { handleMcpToolError } from "../utils/errorHandler.js";
3
3
  import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
4
- export const registerTool = (server) => {
4
+ export const registerTool = (server, config) => {
5
5
  server.tool("list-languages-mapi", "Get all Kontent.ai languages from Management API", {}, async (_, { authInfo: { token, clientId } = {} }) => {
6
- const client = createMapiClient(clientId, token);
6
+ const client = createMapiClient(clientId, token, config);
7
7
  try {
8
8
  const response = await client.listLanguages().toAllPromise();
9
9
  return createMcpToolSuccessResponse(response.data);
@@ -1,9 +1,9 @@
1
1
  import { createMapiClient } from "../clients/kontentClients.js";
2
2
  import { handleMcpToolError } from "../utils/errorHandler.js";
3
3
  import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
4
- export const registerTool = (server) => {
4
+ export const registerTool = (server, config) => {
5
5
  server.tool("list-taxonomy-groups-mapi", "Get all Kontent.ai taxonomy groups from Management API", {}, async (_, { authInfo: { token, clientId } = {} }) => {
6
- const client = createMapiClient(clientId, token);
6
+ const client = createMapiClient(clientId, token, config);
7
7
  try {
8
8
  const response = await client.listTaxonomies().toAllPromise();
9
9
  return createMcpToolSuccessResponse(response.data);
@@ -1,9 +1,9 @@
1
1
  import { createMapiClient } from "../clients/kontentClients.js";
2
2
  import { handleMcpToolError } from "../utils/errorHandler.js";
3
3
  import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
4
- export const registerTool = (server) => {
4
+ export const registerTool = (server, config) => {
5
5
  server.tool("list-workflows-mapi", "Get all Kontent.ai workflows from Management API. Workflows define the content lifecycle stages and transitions between them.", {}, async (_, { authInfo: { token, clientId } = {} }) => {
6
- const client = createMapiClient(clientId, token);
6
+ const client = createMapiClient(clientId, token, config);
7
7
  try {
8
8
  const response = await client.listWorkflows().toPromise();
9
9
  return createMcpToolSuccessResponse(response.data);
@@ -3,7 +3,7 @@ import { createMapiClient } from "../clients/kontentClients.js";
3
3
  import { patchOperationsSchema } from "../schemas/patchSchemas/contentTypePatchSchemas.js";
4
4
  import { handleMcpToolError } from "../utils/errorHandler.js";
5
5
  import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
6
- export const registerTool = (server) => {
6
+ export const registerTool = (server, config) => {
7
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
8
  codename: z.string().describe("Codename of the content type to update"),
9
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).
@@ -55,7 +55,7 @@ export const registerTool = (server) => {
55
55
  - Use atomic operations for complex changes like removing content groups
56
56
  - When adding to allowed_formatting or allowed_table_formatting, always ensure 'unstyled' is the first item in the array`),
57
57
  }, async ({ codename, operations }, { authInfo: { token, clientId } = {} }) => {
58
- const client = createMapiClient(clientId, token);
58
+ const client = createMapiClient(clientId, token, config);
59
59
  try {
60
60
  // Apply patch operations using the modifyContentType method
61
61
  const response = await client
@@ -2,7 +2,7 @@ import { z } from "zod";
2
2
  import { createMapiClient } from "../clients/kontentClients.js";
3
3
  import { handleMcpToolError } from "../utils/errorHandler.js";
4
4
  import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
5
- export const registerTool = (server) => {
5
+ export const registerTool = (server, config) => {
6
6
  server.tool("publish-variant-mapi", "Publish or schedule a language variant of a content item in Kontent.ai. This operation can either immediately publish the variant (publishing happens right now) or schedule it for publication at a specific future date and time. For immediate publishing: the variant is published immediately and becomes available through the Delivery API. For scheduled publishing: the variant moves to a 'Scheduled' workflow state and will automatically transition to 'Published' at the specified time. The variant must be in a valid state with all required fields filled and validation rules satisfied. A variant can only be published if a transition is defined between the variant's current workflow step and the Published workflow step.", {
7
7
  itemId: z
8
8
  .string()
@@ -22,7 +22,7 @@ export const registerTool = (server) => {
22
22
  .optional()
23
23
  .describe("The timezone identifier for displaying the scheduled time in the Kontent.ai UI (e.g., 'America/New_York', 'Europe/London', 'UTC'). This parameter is used for scheduled publishing to specify the timezone context for the scheduled_to parameter. If not provided, the system will use the default timezone. This helps content creators understand when content will be published in their local context."),
24
24
  }, async ({ itemId, languageId, scheduledTo, displayTimezone }, { authInfo: { token, clientId } = {} }) => {
25
- const client = createMapiClient(clientId, token);
25
+ const client = createMapiClient(clientId, token, config);
26
26
  try {
27
27
  // Validate that displayTimezone can only be used with scheduledTo
28
28
  if (displayTimezone && !scheduledTo) {
@@ -2,7 +2,7 @@ import { z } from "zod";
2
2
  import { createMapiClient } from "../clients/kontentClients.js";
3
3
  import { handleMcpToolError } from "../utils/errorHandler.js";
4
4
  import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
5
- export const registerTool = (server) => {
5
+ export const registerTool = (server, config) => {
6
6
  server.tool("unpublish-variant-mapi", "Unpublish or schedule unpublishing of a language variant of a content item in Kontent.ai. This operation can either immediately unpublish the variant (making it unavailable through the Delivery API) or schedule it for unpublishing at a specific future date and time. For immediate unpublishing: the variant is unpublished right away and moves to the 'Archived' workflow step, becoming unavailable through the Delivery API. For scheduled unpublishing: the variant remains published but is scheduled to be automatically unpublished at the specified time. The variant must currently be in the 'Published' state for this operation to succeed.", {
7
7
  itemId: z
8
8
  .string()
@@ -22,7 +22,7 @@ export const registerTool = (server) => {
22
22
  .optional()
23
23
  .describe("The timezone identifier for displaying the scheduled time in the Kontent.ai UI (e.g., 'America/New_York', 'Europe/London', 'UTC'). This parameter is used for scheduled unpublishing to specify the timezone context for the scheduled_to parameter. If not provided, the system will use the default timezone. This helps content creators understand when content will be unpublished in their local context."),
24
24
  }, async ({ itemId, languageId, scheduledTo, displayTimezone }, { authInfo: { token, clientId } = {} }) => {
25
- const client = createMapiClient(clientId, token);
25
+ const client = createMapiClient(clientId, token, config);
26
26
  try {
27
27
  // Validate that displayTimezone can only be used with scheduledTo
28
28
  if (displayTimezone && !scheduledTo) {
@@ -2,7 +2,7 @@ import { z } from "zod";
2
2
  import { createMapiClient } from "../clients/kontentClients.js";
3
3
  import { handleMcpToolError } from "../utils/errorHandler.js";
4
4
  import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
5
- export const registerTool = (server) => {
5
+ export const registerTool = (server, config) => {
6
6
  server.tool("update-content-item-mapi", "Update existing Kontent.ai content item by internal ID via Management API. The content item must already exist - this tool will not create new items.", {
7
7
  id: z.string().describe("Internal ID of the content item to update"),
8
8
  name: z
@@ -20,7 +20,7 @@ export const registerTool = (server) => {
20
20
  .optional()
21
21
  .describe("Reference to a collection by id, codename, or external_id (optional)"),
22
22
  }, async ({ id, name, collection }, { authInfo: { token, clientId } = {} }) => {
23
- const client = createMapiClient(clientId, token);
23
+ const client = createMapiClient(clientId, token, config);
24
24
  try {
25
25
  // First, verify the item exists by trying to get it
26
26
  await client.viewContentItem().byItemId(id).toPromise();
@@ -3,7 +3,7 @@ import { createMapiClient } from "../clients/kontentClients.js";
3
3
  import { languageVariantElementSchema } from "../schemas/contentItemSchemas.js";
4
4
  import { handleMcpToolError } from "../utils/errorHandler.js";
5
5
  import { createMcpToolSuccessResponse } from "../utils/responseHelper.js";
6
- export const registerTool = (server) => {
6
+ export const registerTool = (server, config) => {
7
7
  server.tool("upsert-language-variant-mapi", "Create or update Kontent.ai language variant of a content item via Management API. This adds actual content to the content item elements. When updating an existing variant, only the provided elements will be modified.", {
8
8
  itemId: z.string().describe("Internal ID of the content item"),
9
9
  languageId: z
@@ -17,7 +17,7 @@ export const registerTool = (server) => {
17
17
  .optional()
18
18
  .describe("Internal ID of the workflow step (optional)"),
19
19
  }, async ({ itemId, languageId, elements, workflow_step_id }, { authInfo: { token, clientId } = {} }) => {
20
- const client = createMapiClient(clientId, token);
20
+ const client = createMapiClient(clientId, token, config);
21
21
  const data = {
22
22
  elements,
23
23
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kontent-ai/mcp-server",
3
- "version": "0.17.0",
3
+ "version": "0.18.0",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "build": "rimraf build && tsc",
@@ -21,9 +21,13 @@
21
21
  "author": "Jiri Lojda",
22
22
  "license": "MIT",
23
23
  "dependencies": {
24
+ "@azure/app-configuration": "^1.9.0",
25
+ "@azure/app-configuration-provider": "^2.2.0",
26
+ "@azure/identity": "^4.11.1",
24
27
  "@kontent-ai/delivery-sdk": "^16.2.0",
25
28
  "@kontent-ai/management-sdk": "^7.9.0",
26
29
  "@modelcontextprotocol/sdk": "^1.12.0",
30
+ "applicationinsights": "^2.9.8",
27
31
  "dotenv": "^16.5.0",
28
32
  "express": "^5.1.0",
29
33
  "zod": "^3.25.30"