@configcat/mcp-server 0.1.4 → 0.1.5

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/DEPLOY.md CHANGED
@@ -1,7 +1,9 @@
1
1
  # Steps to deploy
2
2
  ## Preparation
3
3
  1. Increase the `serverVersion` in [src/index.ts](src/index.ts).
4
- 2. Commit & Push
4
+ 2. Increase the `version` in [server.json](server.json).
5
+ 3. Increase the `version` in [package.json](package.json).
6
+ 4. Commit & Push
5
7
  ## Publish
6
8
  Use the **same version** for the git tag as in [src/index.ts](src/index.ts).
7
9
  - Via git tag
package/build/index.js CHANGED
@@ -8,7 +8,7 @@ const baseUrl = process.env.CONFIGCAT_BASE_URL ?? "https://api.configcat.com";
8
8
  const username = process.env.CONFIGCAT_API_USER ?? "";
9
9
  const password = process.env.CONFIGCAT_API_PASS ?? "";
10
10
  const serverName = "ConfigCat MCP";
11
- const serverVersion = "0.1.4";
11
+ const serverVersion = "0.1.5";
12
12
  const http = new HttpClient({ baseUrl, username, password, userAgent: `${serverName}/${serverVersion}` });
13
13
  const server = new McpServer({ name: serverName, version: serverVersion }, { capabilities: { tools: {} } });
14
14
  async function main() {
@@ -185,6 +185,7 @@ The Parameters dictionary differs for each IntegrationType:
185
185
  - Slack
186
186
  Connecting the Slack integration through the Public Management API will not post messages with the ConfigCat Feature Flags Slack app but with an incoming webhook.
187
187
  - \`incoming_webhook.url\`: Required. The [incoming webhook URL](https://api.slack.com/messaging/webhooks) where the integration should post messages.
188
+ - \`includeSensitiveData\`: Set to "true" to include [sensitive (hashed) comparison values](https://configcat.com/docs/targeting/targeting-rule/user-condition/#confidential-text-comparators). By default, the integration will mask these values in the posted messages. We recommend hiding sensitive comparison values for shared or public Slack channels.
188
189
  - Amplitude
189
190
  - \`apiKey\`: Required. Amplitude API Key.
190
191
  - \`secretKey\`: Required. Amplitude Secret Key.
@@ -201,10 +202,10 @@ The Parameters dictionary differs for each IntegrationType:
201
202
  productId: z.string().uuid().describe("The identifier of the Product."),
202
203
  requestBody: z.object({
203
204
  integrationType: z.enum(["dataDog", "slack", "amplitude", "mixPanel", "segment", "pubNub"]),
204
- name: z.string().min(1).describe("Name of the Integration."),
205
+ name: z.string().min(1).max(255).describe("Name of the Integration."),
205
206
  parameters: z.record(z.string().nullable()).describe("Parameters of the Integration."),
206
- environmentIds: z.array(z.string().uuid()).describe("List of Environment IDs that are connected with this Integration. If the list is empty, all of the Environments are connected."),
207
- configIds: z.array(z.string().uuid()).describe("List of Config IDs that are connected with this Integration. If the list is empty, all of the Configs are connected."),
207
+ environmentIds: z.array(z.string().uuid()).describe("List of Environment IDs that are connected with this Integration. If the list is empty, all the Environments are connected."),
208
+ configIds: z.array(z.string().uuid()).describe("List of Config IDs that are connected with this Integration. If the list is empty, all the Configs are connected."),
208
209
  }),
209
210
  },
210
211
  method: "post",
@@ -272,9 +273,19 @@ identified by the \`configId\` parameter.
272
273
  key: z.string().min(1).max(255).describe("The key of the Feature Flag or Setting."),
273
274
  name: z.string().min(1).max(255).describe("The name of the Feature Flag or Setting."),
274
275
  settingType: z.enum(["boolean", "string", "int", "double"]).describe("The type of the Feature Flag or Setting."),
276
+ predefinedVariations: z.array(z.object({
277
+ value: z.object({
278
+ boolValue: z.boolean().nullable().optional().describe("The served value in case of a boolean Feature Flag."),
279
+ stringValue: z.string().nullable().optional().describe("The served value in case of a text Setting."),
280
+ intValue: z.number().int().nullable().optional().describe("The served value in case of a whole number Setting."),
281
+ doubleValue: z.number().nullable().optional().describe("The served value in case of a decimal number Setting."),
282
+ }).describe("Represents the value of a Predefined Variation."),
283
+ name: z.string().min(0).max(255).nullable().optional().describe("The name of the Predefined Variation, shown on the Dashboard UI. If not set, the Value will be shown."),
284
+ hint: z.string().min(0).max(1000).nullable().optional().describe("The name of the Predefined Variation, shown on the Dashboard UI. If not set, the Value will be shown."),
285
+ }).describe("A Predefined Variation.")).nullable().optional().describe("The Feature Flag or Setting's Variations."),
275
286
  initialValues: z.array(z.object({
276
287
  environmentId: z.string().uuid().describe("The ID of the Environment where the initial value must be set."),
277
- value: z.union([z.boolean(), z.string(), z.number()]).describe("The initial value in the given Environment. It must respect the setting type. In some generated clients for strictly typed languages you may use double/float properties to handle integer values."),
288
+ value: z.union([z.boolean(), z.string(), z.number()]).describe("The initial value in the given Environment. It must respect the setting type. In some generated clients for strictly typed languages, you may use double/float properties to handle integer values. In case of a Feature Flag with predefined variations, the value must match one of the predefined variations' value."),
278
289
  })).nullable().optional().describe("Optional, initial value of the Feature Flag or Setting in the given Environments. Only one of the SettingIdToInitFrom or the InitialValues properties can be set."),
279
290
  settingIdToInitFrom: z.number().int().nullable().optional().describe("Optional, the SettingId to initialize the values and tags of the Feature Flag or Setting from. Only can be set if you have at least ReadOnly access in all the Environments. Only one of the SettingIdToInitFrom or the InitialValues properties can be set."),
280
291
  }),
@@ -301,7 +312,8 @@ The distance between \`fromUtcDateTime\` and \`toUtcDateTime\` cannot exceed **3
301
312
  "teamMemberRemoved", "teamMemberLeft", "teamMemberInvitationChanged", "teamMemberInvitationResent",
302
313
  "teamMemberInvitationRejected", "configCreated", "configChanged", "configDeleted", "configsReordered",
303
314
  "environmentCreated", "environmentChanged", "environmentDeleted", "environmentsReordered", "settingCreated",
304
- "settingChanged", "settingDeleted", "settingsReordered", "settingValueChanged", "webHookCreated",
315
+ "settingChanged", "settingDeleted", "settingsReordered", "predefinedVariationsChanged",
316
+ "settingConvertedToPredefinedVariations", "settingConvertedToFreeFormValues", "settingValueChanged", "webHookCreated",
305
317
  "webHookChanged", "webHookDeleted", "permissionGroupCreated", "permissionGroupChanged", "permissionGroupDeleted",
306
318
  "permissionGroupDefault", "apiKeyAdded", "apiKeyRemoved", "integrationAdded", "integrationChanged",
307
319
  "integrationRemoved", "apiKeyConnected", "integrationLinkAdded", "integrationLinkRemoved", "organizationAdded",
@@ -513,6 +525,7 @@ The Parameters dictionary differs for each IntegrationType:
513
525
  - Slack
514
526
  Connecting the Slack integration through the Public Management API will not post messages with the ConfigCat Feature Flags Slack app but with an incoming webhook.
515
527
  - \`incoming_webhook.url\`: Required. The [incoming webhook URL](https://api.slack.com/messaging/webhooks) where the integration should post messages.
528
+ - \`includeSensitiveData\`: Set to "true" to include [sensitive (hashed) comparison values](https://configcat.com/docs/targeting/targeting-rule/user-condition/#confidential-text-comparators). By default, the integration will mask these values in the posted messages. We recommend hiding sensitive comparison values for shared or public Slack channels.
516
529
  - Amplitude
517
530
  - \`apiKey\`: Required. Amplitude API Key.
518
531
  - \`secretKey\`: Required. Amplitude Secret Key.
@@ -528,10 +541,10 @@ The Parameters dictionary differs for each IntegrationType:
528
541
  inputSchema: {
529
542
  integrationId: z.string().uuid().describe("The identifier of the Integration."),
530
543
  requestBody: z.object({
531
- name: z.string().min(1).describe("Name of the Integration."),
544
+ name: z.string().min(1).max(255).describe("Name of the Integration."),
532
545
  parameters: z.record(z.string().nullable()).describe("Parameters of the Integration."),
533
- environmentIds: z.array(z.string().uuid()).describe("List of Environment IDs that are connected with this Integration. If the list is empty, all of the Environments are connected."),
534
- configIds: z.array(z.string().uuid()).describe("List of Config IDs that are connected with this Integration. If the list is empty, all of the Configs are connected."),
546
+ environmentIds: z.array(z.string().uuid()).describe("List of Environment IDs that are connected with this Integration. If the list is empty, all the Environments are connected."),
547
+ configIds: z.array(z.string().uuid()).describe("List of Config IDs that are connected with this Integration. If the list is empty, all the Configs are connected."),
535
548
  }),
536
549
  },
537
550
  method: "put",
@@ -578,7 +591,8 @@ The distance between \`fromUtcDateTime\` and \`toUtcDateTime\` cannot exceed **3
578
591
  "teamMemberRemoved", "teamMemberLeft", "teamMemberInvitationChanged", "teamMemberInvitationResent",
579
592
  "teamMemberInvitationRejected", "configCreated", "configChanged", "configDeleted", "configsReordered",
580
593
  "environmentCreated", "environmentChanged", "environmentDeleted", "environmentsReordered", "settingCreated",
581
- "settingChanged", "settingDeleted", "settingsReordered", "settingValueChanged", "webHookCreated",
594
+ "settingChanged", "settingDeleted", "settingsReordered", "predefinedVariationsChanged",
595
+ "settingConvertedToPredefinedVariations", "settingConvertedToFreeFormValues", "settingValueChanged", "webHookCreated",
582
596
  "webHookChanged", "webHookDeleted", "permissionGroupCreated", "permissionGroupChanged", "permissionGroupDeleted",
583
597
  "permissionGroupDefault", "apiKeyAdded", "apiKeyRemoved", "integrationAdded", "integrationChanged",
584
598
  "integrationRemoved", "apiKeyConnected", "integrationLinkAdded", "integrationLinkRemoved", "organizationAdded",
@@ -643,6 +657,40 @@ given Product identified by the \`productId\` parameter.`,
643
657
  pathTemplate: "/v1/products/{productId}/invitations",
644
658
  executionParameters: [{ "name": "productId", "in": "path" }],
645
659
  }],
660
+ ["list-predefined-variations", {
661
+ name: "list-predefined-variations",
662
+ description: "This endpoint returns the predefined variations along with their usages in the Environments for a Feature Flag or Setting identified by the `settingId` parameter.",
663
+ inputSchema: {
664
+ settingId: z.number().int().describe("The identifier of the Setting."),
665
+ },
666
+ method: "get",
667
+ pathTemplate: "/v1/settings/{settingId}/predefined-variations",
668
+ executionParameters: [{ "name": "settingId", "in": "path" }],
669
+ }],
670
+ ["update-predefined-variations", {
671
+ name: "update-predefined-variations",
672
+ description: `This endpoint updates the predefined variations for a Feature Flag or Setting identified by the \`settingId\` parameter.
673
+ **Important:** You can only update a predefined variation's value if it is not used anywhere in your feature flags.`,
674
+ inputSchema: {
675
+ settingId: z.number().int().describe("The identifier of the Setting."),
676
+ requestBody: z.object({
677
+ predefinedVariations: z.array(z.object({
678
+ value: z.object({
679
+ boolValue: z.boolean().nullable().optional().describe("The served value in case of a boolean Feature Flag."),
680
+ stringValue: z.string().nullable().optional().describe("The served value in case of a text Setting."),
681
+ intValue: z.number().int().nullable().optional().describe("The served value in case of a whole number Setting."),
682
+ doubleValue: z.number().nullable().optional().describe("The served value in case of a decimal number Setting."),
683
+ }).describe("Represents the value of a Predefined Variation."),
684
+ name: z.string().min(0).max(255).nullable().optional().describe("The name of the Predefined Variation, shown on the Dashboard UI. If not set, the Value will be shown."),
685
+ hint: z.string().min(0).max(1000).nullable().optional().describe("The name of the Predefined Variation, shown on the Dashboard UI. If not set, the Value will be shown."),
686
+ predefinedVariationId: z.string().uuid().nullable().optional().describe("The Predefined Variation's identifier to update. Omit the value if you want to add a new predefined variation."),
687
+ }).describe("A Predefined Variation.")).describe("A collection of Predefined Variations."),
688
+ }),
689
+ },
690
+ method: "put",
691
+ pathTemplate: "/v1/settings/{settingId}/predefined-variations",
692
+ executionParameters: [{ "name": "settingId", "in": "path" }],
693
+ }],
646
694
  ["get-product", {
647
695
  name: "get-product",
648
696
  description: `This endpoint returns the metadata of a Product
@@ -786,10 +834,10 @@ want to change in its original state. Not listing one means it will reset.`,
786
834
  inputSchema: {
787
835
  settingId: z.number().int().describe("The identifier of the Setting."),
788
836
  requestBody: z.object({
789
- hint: z.string().min(0).max(1000).nullable().describe("A short description for the setting, shown on the Dashboard UI."),
790
- tags: z.array(z.number().int()).nullable().describe("The IDs of the tags which are attached to the setting."),
791
- order: z.number().int().nullable().describe("The order of the Setting represented on the ConfigCat Dashboard. Determined from an ascending sequence of integers."),
792
- name: z.string().min(1).max(255).nullable().describe("The name of the Feature Flag or Setting."),
837
+ name: z.string().min(1).max(255).describe("The name of the Feature Flag or Setting."),
838
+ hint: z.string().min(0).max(1000).nullable().optional().describe("A short description for the setting, shown on the Dashboard UI."),
839
+ tags: z.array(z.number().int()).nullable().optional().describe("The IDs of the tags which are attached to the setting."),
840
+ order: z.number().int().nullable().optional().describe("The order of the Setting represented on the ConfigCat Dashboard. Determined from an ascending sequence of integers."),
793
841
  }),
794
842
  },
795
843
  method: "put",
@@ -1158,6 +1206,7 @@ So we get a response like this:
1158
1206
  stringValue: z.string().nullable().optional().describe("The served value in case of a text Setting."),
1159
1207
  intValue: z.number().int().nullable().optional().describe("The served value in case of a whole number Setting."),
1160
1208
  doubleValue: z.number().nullable().optional().describe("The served value in case of a decimal number Setting."),
1209
+ predefinedVariationId: z.string().uuid().nullable().optional().describe("The served Variation's identifier."),
1161
1210
  }).describe("Represents the value of a Feature Flag or Setting."),
1162
1211
  targetingRules: z.array(z.object({
1163
1212
  conditions: z.array(z.object({
@@ -1185,6 +1234,7 @@ So we get a response like this:
1185
1234
  stringValue: z.string().nullable().optional().describe("The served value in case of a text Setting."),
1186
1235
  intValue: z.number().int().nullable().optional().describe("The served value in case of a whole number Setting."),
1187
1236
  doubleValue: z.number().nullable().optional().describe("The served value in case of a decimal number Setting."),
1237
+ predefinedVariationId: z.string().uuid().nullable().optional().describe("The served Variation's identifier."),
1188
1238
  }).describe("Represents the value of a Feature Flag or Setting."),
1189
1239
  }).nullable().optional().describe("Describes a condition that is based on a prerequisite flag."),
1190
1240
  })).nullable().optional().describe("The list of conditions that are combined with logical AND operators. It can be one of the following: User condition, Segment condition, Prerequisite flag condition"),
@@ -1195,6 +1245,7 @@ So we get a response like this:
1195
1245
  stringValue: z.string().nullable().optional().describe("The served value in case of a text Setting."),
1196
1246
  intValue: z.number().int().nullable().optional().describe("The served value in case of a whole number Setting."),
1197
1247
  doubleValue: z.number().nullable().optional().describe("The served value in case of a decimal number Setting."),
1248
+ predefinedVariationId: z.string().uuid().nullable().optional().describe("The served Variation's identifier."),
1198
1249
  }).describe("Represents the value of a Feature Flag or Setting."),
1199
1250
  })).nullable().optional().describe("The percentage options from where the evaluation process will choose a value based on the flag's percentage evaluation attribute."),
1200
1251
  value: z.object({
@@ -1202,6 +1253,7 @@ So we get a response like this:
1202
1253
  stringValue: z.string().nullable().optional().describe("The served value in case of a text Setting."),
1203
1254
  intValue: z.number().int().nullable().optional().describe("The served value in case of a whole number Setting."),
1204
1255
  doubleValue: z.number().nullable().optional().describe("The served value in case of a decimal number Setting."),
1256
+ predefinedVariationId: z.string().uuid().nullable().optional().describe("The served Variation's identifier."),
1205
1257
  }).nullable().optional().describe("Represents the value of a Feature Flag or Setting."),
1206
1258
  })).nullable().optional().describe("The targeting rules of the Feature Flag or Setting."),
1207
1259
  percentageEvaluationAttribute: z.string().max(1000).nullable().optional().describe("The user attribute used for percentage evaluation. If not set, it defaults to the `Identifier` user object attribute."),
@@ -1523,6 +1575,7 @@ So we get a response like this:
1523
1575
  stringValue: z.string().nullable().optional().describe("The served value in case of a text Setting."),
1524
1576
  intValue: z.number().int().nullable().optional().describe("The served value in case of a whole number Setting."),
1525
1577
  doubleValue: z.number().nullable().optional().describe("The served value in case of a decimal number Setting."),
1578
+ predefinedVariationId: z.string().uuid().nullable().optional().describe("The served Variation's identifier."),
1526
1579
  }).describe("Represents the value of a Feature Flag or Setting."),
1527
1580
  targetingRules: z.array(z.object({
1528
1581
  conditions: z.array(z.object({
@@ -1550,6 +1603,7 @@ So we get a response like this:
1550
1603
  stringValue: z.string().nullable().optional().describe("The served value in case of a text Setting."),
1551
1604
  intValue: z.number().int().nullable().optional().describe("The served value in case of a whole number Setting."),
1552
1605
  doubleValue: z.number().nullable().optional().describe("The served value in case of a decimal number Setting."),
1606
+ predefinedVariationId: z.string().uuid().nullable().optional().describe("The served Variation's identifier."),
1553
1607
  }).describe("Represents the value of a Feature Flag or Setting."),
1554
1608
  }).nullable().optional(),
1555
1609
  })).nullable().optional(),
@@ -1560,6 +1614,7 @@ So we get a response like this:
1560
1614
  stringValue: z.string().nullable().optional().describe("The served value in case of a text Setting."),
1561
1615
  intValue: z.number().int().nullable().optional().describe("The served value in case of a whole number Setting."),
1562
1616
  doubleValue: z.number().nullable().optional().describe("The served value in case of a decimal number Setting."),
1617
+ predefinedVariationId: z.string().uuid().nullable().optional().describe("The served Variation's identifier."),
1563
1618
  }).describe("Represents the value of a Feature Flag or Setting."),
1564
1619
  })).nullable().optional().describe("The percentage options from where the evaluation process will choose a value based on the flag's percentage evaluation attribute."),
1565
1620
  value: z.object({
@@ -1567,6 +1622,7 @@ So we get a response like this:
1567
1622
  stringValue: z.string().nullable().optional().describe("The served value in case of a text Setting."),
1568
1623
  intValue: z.number().int().nullable().optional().describe("The served value in case of a whole number Setting."),
1569
1624
  doubleValue: z.number().nullable().optional().describe("The served value in case of a decimal number Setting."),
1625
+ predefinedVariationId: z.string().uuid().nullable().optional().describe("The served Variation's identifier."),
1570
1626
  }).nullable().optional().describe("Represents the value of a Feature Flag or Setting."),
1571
1627
  })).nullable().optional().describe("The targeting rules of the Feature Flag or Setting."),
1572
1628
  percentageEvaluationAttribute: z.string().max(1000).nullable().optional().describe("The user attribute used for percentage evaluation. If not set, it defaults to the `Identifier` user object attribute."),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@configcat/mcp-server",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "mcpName": "io.github.configcat/mcp-server",
5
5
  "type": "module",
6
6
  "description": "MCP server exposing ConfigCat Public Management API (products, configs, environments, values v1/v2).",
package/server.json CHANGED
@@ -6,12 +6,12 @@
6
6
  "url": "https://github.com/configcat/mcp-server",
7
7
  "source": "github"
8
8
  },
9
- "version": "0.1.4",
9
+ "version": "0.1.5",
10
10
  "packages": [
11
11
  {
12
12
  "registryType": "npm",
13
13
  "identifier": "@configcat/mcp-server",
14
- "version": "0.1.4",
14
+ "version": "0.1.5",
15
15
  "transport": {
16
16
  "type": "stdio"
17
17
  },