@configcat/mcp-server 0.1.2

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.
@@ -0,0 +1,1965 @@
1
+ import { z, ZodError } from "zod";
2
+ // Map of tool definitions by name
3
+ const toolDefinitionMap = new Map([
4
+ ["list-organizations", {
5
+ name: "list-organizations",
6
+ description: "This endpoint returns the list of the Organizations that belongs to the user.",
7
+ inputSchema: {},
8
+ method: "get",
9
+ pathTemplate: "/v1/organizations",
10
+ executionParameters: [],
11
+ }],
12
+ ["list-products", {
13
+ name: "list-products",
14
+ description: "This endpoint returns the list of the Products that belongs to the user.",
15
+ inputSchema: {},
16
+ method: "get",
17
+ pathTemplate: "/v1/products",
18
+ executionParameters: [],
19
+ }],
20
+ ["list-tags", {
21
+ name: "list-tags",
22
+ description: `This endpoint returns the list of the Tags in a
23
+ specified Product, identified by the \`productId\` parameter.`,
24
+ inputSchema: {
25
+ productId: z.string().uuid().describe("The identifier of the Product."),
26
+ },
27
+ method: "get",
28
+ pathTemplate: "/v1/products/{productId}/tags",
29
+ executionParameters: [{ "name": "productId", "in": "path" }],
30
+ }],
31
+ ["create-tag", {
32
+ name: "create-tag",
33
+ description: `This endpoint creates a new Tag in a specified Product
34
+ identified by the \`productId\` parameter, which can be obtained from the [List Products](#operation/list-products) endpoint.`,
35
+ inputSchema: {
36
+ productId: z.string().uuid().describe("The identifier of the Organization."),
37
+ requestBody: z.object({
38
+ name: z.string().min(1).max(255).describe("Name of the Tag."),
39
+ color: z.string().max(255).nullable().optional().describe("Color of the Tag. Possible values: `panther`, `whale`, `salmon`, `lizard`, `canary`, `koala`, or any HTML color code."),
40
+ }),
41
+ },
42
+ method: "post",
43
+ pathTemplate: "/v1/products/{productId}/tags",
44
+ executionParameters: [{ "name": "productId", "in": "path" }],
45
+ }],
46
+ ["list-webhooks", {
47
+ name: "list-webhooks",
48
+ description: `This endpoint returns the list of the Webhooks that belongs to the given Product identified by the
49
+ \`productId\` parameter, which can be obtained from the [List Products](#operation/list-products) endpoint.`,
50
+ inputSchema: {
51
+ productId: z.string().uuid().describe("The identifier of the Product."),
52
+ },
53
+ method: "get",
54
+ pathTemplate: "/v1/products/{productId}/webhooks",
55
+ executionParameters: [{ "name": "productId", "in": "path" }],
56
+ }],
57
+ ["list-configs", {
58
+ name: "list-configs",
59
+ description: `This endpoint returns the list of the Configs that belongs to the given Product identified by the
60
+ \`productId\` parameter, which can be obtained from the [List Products](#operation/list-products) endpoint.`,
61
+ inputSchema: {
62
+ productId: z.string().uuid().describe("The identifier of the Product."),
63
+ },
64
+ method: "get",
65
+ pathTemplate: "/v1/products/{productId}/configs",
66
+ executionParameters: [{ "name": "productId", "in": "path" }],
67
+ }],
68
+ ["create-config", {
69
+ name: "create-config",
70
+ description: `This endpoint creates a new Config in a specified Product
71
+ identified by the \`productId\` parameter, which can be obtained from the [List Products](#operation/list-products) endpoint.`,
72
+ inputSchema: {
73
+ productId: z.string().uuid().describe("The identifier of the Product."),
74
+ requestBody: z.object({
75
+ name: z.string().min(1).max(255).describe("The name of the Config."),
76
+ description: z.string().max(1000).nullable().optional().describe("The description of the Config."),
77
+ order: z.number().int().nullable().optional().describe("The order of the Config represented on the ConfigCat Dashboard.\nDetermined from an ascending sequence of integers."),
78
+ evaluationVersion: z.enum(["v1", "v2"]).optional().describe("Determines the evaluation version of a Config.\nUsing `v2` enables the new features of Config V2 (https://configcat.com/docs/advanced/config-v2)."),
79
+ }),
80
+ },
81
+ method: "post",
82
+ pathTemplate: "/v1/products/{productId}/configs",
83
+ executionParameters: [{ "name": "productId", "in": "path" }],
84
+ }],
85
+ ["list-environments", {
86
+ name: "list-environments",
87
+ description: `This endpoint returns the list of the Environments that belongs to the given Product identified by the
88
+ \`productId\` parameter, which can be obtained from the [List Products](#operation/list-products) endpoint.`,
89
+ inputSchema: {
90
+ productId: z.string().uuid().describe("The identifier of the Product."),
91
+ },
92
+ method: "get",
93
+ pathTemplate: "/v1/products/{productId}/environments",
94
+ executionParameters: [{ "name": "productId", "in": "path" }],
95
+ }],
96
+ ["create-environment", {
97
+ name: "create-environment",
98
+ description: `This endpoint creates a new Environment in a specified Product
99
+ identified by the \`productId\` parameter, which can be obtained from the [List Products](#operation/list-products) endpoint.`,
100
+ inputSchema: {
101
+ productId: z.string().uuid().describe("The identifier of the Product."),
102
+ requestBody: z.object({
103
+ name: z.string().min(1).max(255).describe("The name of the Environment."),
104
+ color: z.string().max(255).nullable().optional().describe("The color of the Environment. RGB or HTML color codes are allowed."),
105
+ description: z.string().max(1000).nullable().optional().describe("The description of the Environment."),
106
+ order: z.number().int().nullable().optional().describe("The order of the Environment represented on the ConfigCat Dashboard.\nDetermined from an ascending sequence of integers."),
107
+ }),
108
+ },
109
+ method: "post",
110
+ pathTemplate: "/v1/products/{productId}/environments",
111
+ executionParameters: [{ "name": "productId", "in": "path" }],
112
+ }],
113
+ ["list-permission-groups", {
114
+ name: "list-permission-groups",
115
+ description: `This endpoint returns the list of the Permission Groups that belongs to the given Product identified by the
116
+ \`productId\` parameter, which can be obtained from the [List Products](#operation/list-products) endpoint.`,
117
+ inputSchema: {
118
+ productId: z.string().uuid().describe("The identifier of the Product."),
119
+ },
120
+ method: "get",
121
+ pathTemplate: "/v1/products/{productId}/permissions",
122
+ executionParameters: [{ "name": "productId", "in": "path" }],
123
+ }],
124
+ ["create-permission-group", {
125
+ name: "create-permission-group",
126
+ description: `This endpoint creates a new Permission Group in a specified Product
127
+ identified by the \`productId\` parameter, which can be obtained from the [List Products](#operation/list-products) endpoint.`,
128
+ inputSchema: {
129
+ productId: z.string().uuid().describe("The identifier of the Product."),
130
+ requestBody: z.object({
131
+ name: z.string().min(1).max(255).describe("Name of the Permission Group."),
132
+ canManageMembers: z.boolean().optional().describe("Group members can manage team members."),
133
+ canCreateOrUpdateConfig: z.boolean().optional().describe("Group members can create/update Configs."),
134
+ canDeleteConfig: z.boolean().optional().describe("Group members can delete Configs."),
135
+ canCreateOrUpdateEnvironment: z.boolean().optional().describe("Group members can create/update Environments."),
136
+ canDeleteEnvironment: z.boolean().optional().describe("Group members can delete Environments."),
137
+ canCreateOrUpdateSetting: z.boolean().optional().describe("Group members can create/update Feature Flags and Settings."),
138
+ canTagSetting: z.boolean().optional().describe("Group members can attach/detach Tags to Feature Flags and Settings."),
139
+ canDeleteSetting: z.boolean().optional().describe("Group members can delete Feature Flags and Settings."),
140
+ canCreateOrUpdateTag: z.boolean().optional().describe("Group members can create/update Tags."),
141
+ canDeleteTag: z.boolean().optional().describe("Group members can delete Tags."),
142
+ canManageWebhook: z.boolean().optional().describe("Group members can create/update/delete Webhooks."),
143
+ canUseExportImport: z.boolean().optional().describe("Group members can use the export/import feature."),
144
+ canManageProductPreferences: z.boolean().optional().describe("Group members can update Product preferences."),
145
+ canManageIntegrations: z.boolean().optional().describe("Group members can add and configure integrations."),
146
+ canViewSdkKey: z.boolean().optional().describe("Group members has access to SDK keys."),
147
+ canRotateSdkKey: z.boolean().optional().describe("Group members can rotate SDK keys."),
148
+ canCreateOrUpdateSegments: z.boolean().optional().describe("Group members can create/update Segments."),
149
+ canDeleteSegments: z.boolean().optional().describe("Group members can delete Segments."),
150
+ canViewProductAuditLog: z.boolean().optional().describe("Group members has access to audit logs."),
151
+ canViewProductStatistics: z.boolean().optional().describe("Group members has access to product statistics."),
152
+ accessType: z.enum(["readOnly", "full", "custom"]).optional().describe("Represent the Feature Management permission."),
153
+ newEnvironmentAccessType: z.enum(["full", "readOnly", "none"]).optional().describe("Represent the environment specific Feature Management permission."),
154
+ environmentAccesses: z.array(z.object({
155
+ environmentId: z.string().uuid().describe("Identifier of the Environment."),
156
+ environmentAccessType: z.enum(["full", "readOnly", "none"]).describe("Represent the environment specific Feature Management permission."),
157
+ })).nullable().optional().describe("List of environment specific permissions."),
158
+ canDisable2FA: z.boolean().optional().describe("Group members can disable two-factor authentication for other members."),
159
+ }),
160
+ },
161
+ method: "post",
162
+ pathTemplate: "/v1/products/{productId}/permissions",
163
+ executionParameters: [{ "name": "productId", "in": "path" }],
164
+ }],
165
+ ["list-integrations", {
166
+ name: "list-integrations",
167
+ description: `This endpoint returns the list of the Integrations that belongs to the given Product identified by the
168
+ \`productId\` parameter, which can be obtained from the [List Products](#operation/list-products) endpoint.`,
169
+ inputSchema: {
170
+ productId: z.string().uuid().describe("The identifier of the Product."),
171
+ },
172
+ method: "get",
173
+ pathTemplate: "/v1/products/{productId}/integrations",
174
+ executionParameters: [{ "name": "productId", "in": "path" }],
175
+ }],
176
+ ["create-integration", {
177
+ name: "create-integration",
178
+ description: `This endpoint creates a new Integration in a specified Product
179
+ identified by the \`productId\` parameter, which can be obtained from the [List Products](#operation/list-products) endpoint.
180
+
181
+ The Parameters dictionary differs for each IntegrationType:
182
+ - Datadog
183
+ - \`apikey\`: Required. Datadog API key.
184
+ - \`site\`: Datadog site. Available values: \`Us\`, \`Eu\`, \`Us1Fed\`, \`Us3\`, \`Us5\`. Default: \`Us\`.
185
+ - Slack
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
+ - \`incoming_webhook.url\`: Required. The [incoming webhook URL](https://api.slack.com/messaging/webhooks) where the integration should post messages.
188
+ - Amplitude
189
+ - \`apiKey\`: Required. Amplitude API Key.
190
+ - \`secretKey\`: Required. Amplitude Secret Key.
191
+ - Mixpanel
192
+ - \`serviceAccountUserName\`: Required. Mixpanel Service Account Username.
193
+ - \`serviceAccountSecret\`: Required. Mixpanel Service Account Secret.
194
+ - \`projectId\`: Required. Mixpanel Project ID.
195
+ - \`server\`: Mixpanel Server. Available values: \`StandardServer\`, \`EUResidencyServer\`. Default: \`StandardServer\`.
196
+ - Twilio Segment
197
+ - \`writeKey\`: Required. Twilio Segment Write Key.
198
+ - \`server\`: Twilio Segment Server. Available values: \`Us\`, \`Eu\`. Default: \`Us\`.
199
+ - PubNub (work in progress)`,
200
+ inputSchema: {
201
+ productId: z.string().uuid().describe("The identifier of the Product."),
202
+ requestBody: z.object({
203
+ integrationType: z.enum(["dataDog", "slack", "amplitude", "mixPanel", "segment", "pubNub"]),
204
+ name: z.string().min(1).describe("Name of the Integration."),
205
+ 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."),
208
+ }),
209
+ },
210
+ method: "post",
211
+ pathTemplate: "/v1/products/{productId}/integrations",
212
+ executionParameters: [{ "name": "productId", "in": "path" }],
213
+ }],
214
+ ["list-segments", {
215
+ name: "list-segments",
216
+ description: `This endpoint returns the list of the Segments that belongs to the given Product identified by the
217
+ \`productId\` parameter, which can be obtained from the [List Products](#operation/list-products) endpoint.`,
218
+ inputSchema: {
219
+ productId: z.string().uuid().describe("The identifier of the Product."),
220
+ },
221
+ method: "get",
222
+ pathTemplate: "/v1/products/{productId}/segments",
223
+ executionParameters: [{ "name": "productId", "in": "path" }],
224
+ }],
225
+ ["create-segment", {
226
+ name: "create-segment",
227
+ description: `This endpoint creates a new Segment in a specified Product
228
+ identified by the \`productId\` parameter, which can be obtained from the [List Products](#operation/list-products) endpoint.`,
229
+ inputSchema: {
230
+ productId: z.string().uuid().describe("The identifier of the Product."),
231
+ requestBody: z.object({
232
+ name: z.string().min(1).max(255).describe("Name of the Segment."),
233
+ description: z.string().min(0).max(1000).nullable().optional().describe("Description of the Segment."),
234
+ comparisonAttribute: z.string().min(1).max(1000).describe("The user's attribute the evaluation process must take into account."),
235
+ comparator: z.enum([
236
+ "isOneOf", "isNotOneOf", "contains", "doesNotContain",
237
+ "semVerIsOneOf", "semVerIsNotOneOf", "semVerLess", "semVerLessOrEquals",
238
+ "semVerGreater", "semVerGreaterOrEquals", "numberEquals", "numberDoesNotEqual",
239
+ "numberLess", "numberLessOrEquals", "numberGreater", "numberGreaterOrEquals",
240
+ "sensitiveIsOneOf", "sensitiveIsNotOneOf",
241
+ ]).describe("The comparison operator the evaluation process must use when it compares the given user attribute's value with the comparison value."),
242
+ comparisonValue: z.string().min(1).describe("The value to compare with the given user attribute's value."),
243
+ }),
244
+ },
245
+ method: "post",
246
+ pathTemplate: "/v1/products/{productId}/segments",
247
+ executionParameters: [{ "name": "productId", "in": "path" }],
248
+ }],
249
+ ["list-settings", {
250
+ name: "list-settings",
251
+ description: `This endpoint returns the list of the Feature Flags and Settings defined in a
252
+ specified Config, identified by the \`configId\` parameter.`,
253
+ inputSchema: {
254
+ configId: z.string().uuid().describe("The identifier of the Config."),
255
+ },
256
+ method: "get",
257
+ pathTemplate: "/v1/configs/{configId}/settings",
258
+ executionParameters: [{ "name": "configId", "in": "path" }],
259
+ }],
260
+ ["create-setting", {
261
+ name: "create-setting",
262
+ description: `This endpoint creates a new Feature Flag or Setting in a specified Config
263
+ identified by the \`configId\` parameter.
264
+
265
+ **Important:** The \`key\` attribute must be unique within the given Config.`,
266
+ inputSchema: {
267
+ configId: z.string().uuid().describe("The identifier of the Config."),
268
+ requestBody: z.object({
269
+ hint: z.string().min(0).max(1000).nullable().describe("A short description for the setting, shown on the Dashboard UI."),
270
+ tags: z.array(z.number().int()).nullable().describe("The IDs of the tags which are attached to the setting."),
271
+ order: z.number().int().nullable().describe("The order of the Setting represented on the ConfigCat Dashboard. Determined from an ascending sequence of integers."),
272
+ key: z.string().min(1).max(255).describe("The key of the Feature Flag or Setting."),
273
+ name: z.string().min(1).max(255).describe("The name of the Feature Flag or Setting."),
274
+ settingType: z.enum(["boolean", "string", "int", "double"]).describe("The type of the Feature Flag or Setting."),
275
+ initialValues: z.array(z.object({
276
+ 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."),
278
+ })).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
+ 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
+ }),
281
+ },
282
+ method: "post",
283
+ pathTemplate: "/v1/configs/{configId}/settings",
284
+ executionParameters: [{ "name": "configId", "in": "path" }],
285
+ }],
286
+ ["list-auditlogs", {
287
+ name: "list-auditlogs",
288
+ description: `This endpoint returns the list of Audit log items for a given Product
289
+ and the result can be optionally filtered by Config and/or Environment.
290
+
291
+ If neither \`fromUtcDateTime\` nor \`toUtcDateTime\` is set, the audit logs for the **last 7 days** will be returned.
292
+
293
+ The distance between \`fromUtcDateTime\` and \`toUtcDateTime\` cannot exceed **30 days**.`,
294
+ inputSchema: {
295
+ productId: z.string().uuid().describe("The identifier of the Product."),
296
+ configId: z.string().uuid().optional().describe("The identifier of the Config."),
297
+ environmentId: z.string().uuid().optional().describe("The identifier of the Environment."),
298
+ auditLogType: z.enum([
299
+ "productCreated", "productChanged", "productOwnershipTransferred", "productDeleted", "productsReordered",
300
+ "teamMemberInvited", "teamMemberInvitationRevoked", "teamMemberJoined", "teamMemberPermissionGroupChanged",
301
+ "teamMemberRemoved", "teamMemberLeft", "teamMemberInvitationChanged", "teamMemberInvitationResent",
302
+ "teamMemberInvitationRejected", "configCreated", "configChanged", "configDeleted", "configsReordered",
303
+ "environmentCreated", "environmentChanged", "environmentDeleted", "environmentsReordered", "settingCreated",
304
+ "settingChanged", "settingDeleted", "settingsReordered", "settingValueChanged", "webHookCreated",
305
+ "webHookChanged", "webHookDeleted", "permissionGroupCreated", "permissionGroupChanged", "permissionGroupDeleted",
306
+ "permissionGroupDefault", "apiKeyAdded", "apiKeyRemoved", "integrationAdded", "integrationChanged",
307
+ "integrationRemoved", "apiKeyConnected", "integrationLinkAdded", "integrationLinkRemoved", "organizationAdded",
308
+ "organizationRemoved", "organizationChanged", "organizationSubscriptionTypeChanged", "organizationAdminChanged",
309
+ "organizationAdminLeft", "twoFactorDisabledForMember", "tagAdded", "tagChanged", "tagRemoved", "settingTagAdded",
310
+ "settingTagRemoved", "publicApiAccessTokenAdded", "publicApiAccessTokenRemoved", "domainAdded", "domainVerified",
311
+ "domainRemoved", "domainSamlConfigured", "domainSamlDeleted", "autoProvisioningConfigurationChanged",
312
+ "samlIdpConfigurationAdded", "samlIdpConfigurationRemoved", "samlIdpConfigurationUpdated",
313
+ "autoProvisioningEnabledChanged", "organizationMemberJoined", "organizationMemberProductJoinRequested",
314
+ "organizationMemberProductJoinRequestRejected", "organizationMemberProductJoinRequestApproved",
315
+ "organizationMemberRemoved", "codeReferencesUploaded", "codeReferenceDeleted", "codeReferenceStaleBranchDeleted",
316
+ "segmentCreated", "segmentChanged", "segmentDeleted", "webhookSigningKeyDeleted", "webhookSigningKeyCreated",
317
+ "userProvisioningConfigurationChanged", "syncGroupProvisioningRuleChanged", "syncGroupsReordered",
318
+ "syncUserProvisioningEnabled", "syncUserProvisioningDisabled", "userEmailChanged", "userFullNameChanged",
319
+ "userDisabled", "awsConnected", "awsDisconnected", "userEnabled", "syncUserDeleted", "syncGroupDeleted",
320
+ "proxyConfigurationCreated", "proxyConfigurationChanged", "proxyConfigurationDeleted",
321
+ "proxyConfigurationSecretRegenerated", "proxyNotificationSettingsUpdated", "proxyNotificationSettingsDeleted",
322
+ "proxyNotificationSigningKeyAdded", "proxyNotificationSigningKeyDeleted",
323
+ ]).nullable().optional().describe("Filter Audit logs by Audit log type."),
324
+ fromUtcDateTime: z.string().datetime().optional().describe("Filter Audit logs by starting UTC date."),
325
+ toUtcDateTime: z.string().datetime().optional().describe("Filter Audit logs by ending UTC date."),
326
+ },
327
+ method: "get",
328
+ pathTemplate: "/v1/products/{productId}/auditlogs",
329
+ executionParameters: [{ "name": "productId", "in": "path" }, { "name": "configId", "in": "query" }, { "name": "environmentId", "in": "query" }, { "name": "auditLogType", "in": "query" }, { "name": "fromUtcDateTime", "in": "query" }, { "name": "toUtcDateTime", "in": "query" }],
330
+ }],
331
+ ["list-staleflags", {
332
+ name: "list-staleflags",
333
+ description: `This endpoint returns the list of Zombie (stale) flags for a given Product
334
+ and the result can be optionally filtered by various parameters.`,
335
+ inputSchema: {
336
+ productId: z.string().uuid().describe("The identifier of the Product."),
337
+ scope: z.enum(["all", "watchedByMe"]).optional().describe("The scope of the report."),
338
+ staleFlagAgeDays: z.number().int().min(7).max(90).optional().describe("The inactivity in days after a feature flag should be considered stale."),
339
+ staleFlagStaleInEnvironmentsType: z.enum(["staleInAnyEnvironments", "staleInAllEnvironments"]).optional().describe("Consider a feature flag as stale if the feature flag is stale in all/any of the environments."),
340
+ ignoredEnvironmentIds: z.array(z.string().uuid()).optional().describe("Ignore environment identifiers from the report."),
341
+ ignoredTagIds: z.array(z.number().int()).optional().describe("Ignore feature flags from the report based on their tag identifiers."),
342
+ },
343
+ method: "get",
344
+ pathTemplate: "/v1/products/{productId}/staleflags",
345
+ executionParameters: [{ "name": "productId", "in": "path" }, { "name": "scope", "in": "query" }, { "name": "staleFlagAgeDays", "in": "query" }, { "name": "staleFlagStaleInEnvironmentsType", "in": "query" }, { "name": "ignoredEnvironmentIds", "in": "query" }, { "name": "ignoredTagIds", "in": "query" }],
346
+ }],
347
+ ["get-code-references", {
348
+ name: "get-code-references",
349
+ description: "Get References for Feature Flag or Setting",
350
+ inputSchema: {
351
+ settingId: z.number().int().describe("The identifier of the Feature Flag or Setting."),
352
+ },
353
+ method: "get",
354
+ pathTemplate: "/v1/settings/{settingId}/code-references",
355
+ executionParameters: [{ "name": "settingId", "in": "path" }],
356
+ }],
357
+ ["get-config", {
358
+ name: "get-config",
359
+ description: `This endpoint returns the metadata of a Config
360
+ identified by the \`configId\`.`,
361
+ inputSchema: {
362
+ configId: z.string().uuid().describe("The identifier of the Config."),
363
+ },
364
+ method: "get",
365
+ pathTemplate: "/v1/configs/{configId}",
366
+ executionParameters: [{ "name": "configId", "in": "path" }],
367
+ }],
368
+ ["update-config", {
369
+ name: "update-config",
370
+ description: "This endpoint updates a Config identified by the `configId` parameter.",
371
+ inputSchema: {
372
+ configId: z.string().uuid().describe("The identifier of the Config."),
373
+ requestBody: z.object({
374
+ name: z.string().min(0).max(255).nullable().describe("The name of the Config."),
375
+ description: z.string().min(0).max(1000).nullable().describe("The description of the Config."),
376
+ order: z.number().int().nullable().describe("The order of the Config represented on the ConfigCat Dashboard. Determined from an ascending sequence of integers."),
377
+ }),
378
+ },
379
+ method: "put",
380
+ pathTemplate: "/v1/configs/{configId}",
381
+ executionParameters: [{ "name": "configId", "in": "path" }],
382
+ }],
383
+ ["delete-config", {
384
+ name: "delete-config",
385
+ description: "This endpoint removes a Config identified by the `configId` parameter.",
386
+ inputSchema: {
387
+ configId: z.string().uuid().describe("The identifier of the Config."),
388
+ },
389
+ method: "delete",
390
+ pathTemplate: "/v1/configs/{configId}",
391
+ executionParameters: [{ "name": "configId", "in": "path" }],
392
+ }],
393
+ ["get-environment", {
394
+ name: "get-environment",
395
+ description: `This endpoint returns the metadata of an Environment
396
+ identified by the \`environmentId\`.`,
397
+ inputSchema: {
398
+ environmentId: z.string().uuid().describe("The identifier of the Environment."),
399
+ },
400
+ method: "get",
401
+ pathTemplate: "/v1/environments/{environmentId}",
402
+ executionParameters: [{ "name": "environmentId", "in": "path" }],
403
+ }],
404
+ ["update-environment", {
405
+ name: "update-environment",
406
+ description: "This endpoint updates an Environment identified by the `environmentId` parameter.",
407
+ inputSchema: {
408
+ environmentId: z.string().uuid().describe("The identifier of the Environment."),
409
+ requestBody: z.object({
410
+ name: z.string().min(0).max(255).nullable().optional().describe("The name of the Environment."),
411
+ color: z.string().min(0).max(255).nullable().optional().describe("The color of the Environment. RGB or HTML color codes are allowed."),
412
+ description: z.string().min(0).max(1000).nullable().optional().describe("The description of the Environment."),
413
+ order: z.number().int().nullable().optional().describe("The order of the Environment represented on the ConfigCat Dashboard.\nDetermined from an ascending sequence of integers."),
414
+ }).describe("The JSON request body."),
415
+ },
416
+ method: "put",
417
+ pathTemplate: "/v1/environments/{environmentId}",
418
+ executionParameters: [{ "name": "environmentId", "in": "path" }],
419
+ }],
420
+ ["delete-environment", {
421
+ name: "delete-environment",
422
+ description: `This endpoint removes an Environment identified by the \`environmentId\` parameter.
423
+ If the \`cleanupAuditLogs\` flag is set to true, it also deletes the audit log records related to the environment
424
+ (except for the \`Created a new environment\` and \`Deleted an environment\` records).`,
425
+ inputSchema: {
426
+ environmentId: z.string().uuid().describe("The identifier of the Environment."),
427
+ cleanupAuditLogs: z.boolean().optional().describe("An optional flag which indicates whether the audit log records related to the environment should be deleted or not."),
428
+ },
429
+ method: "delete",
430
+ pathTemplate: "/v1/environments/{environmentId}",
431
+ executionParameters: [{ "name": "environmentId", "in": "path" }, { "name": "cleanupAuditLogs", "in": "query" }],
432
+ }],
433
+ ["get-permission-group", {
434
+ name: "get-permission-group",
435
+ description: `This endpoint returns the metadata of a Permission Group
436
+ identified by the \`permissionGroupId\`.`,
437
+ inputSchema: {
438
+ permissionGroupId: z.number().int().describe("The identifier of the Permission Group."),
439
+ },
440
+ method: "get",
441
+ pathTemplate: "/v1/permissions/{permissionGroupId}",
442
+ executionParameters: [{ "name": "permissionGroupId", "in": "path" }],
443
+ }],
444
+ ["update-permission-group", {
445
+ name: "update-permission-group",
446
+ description: "This endpoint updates a Permission Group identified by the `permissionGroupId` parameter.",
447
+ inputSchema: {
448
+ permissionGroupId: z.number().int().describe("The identifier of the Permission Group."),
449
+ requestBody: z.object({
450
+ name: z.string().min(0).max(255).nullable().describe("Name of the Permission Group."),
451
+ canManageMembers: z.boolean().nullable().describe("Group members can manage team members."),
452
+ canCreateOrUpdateConfig: z.boolean().nullable().describe("Group members can create/update Configs."),
453
+ canDeleteConfig: z.boolean().nullable().describe("Group members can delete Configs."),
454
+ canCreateOrUpdateEnvironment: z.boolean().nullable().describe("Group members can create/update Environments."),
455
+ canDeleteEnvironment: z.boolean().nullable().describe("Group members can delete Environments."),
456
+ canCreateOrUpdateSetting: z.boolean().nullable().describe("Group members can create/update Feature Flags and Settings."),
457
+ canTagSetting: z.boolean().nullable().describe("Group members can attach/detach Tags to Feature Flags and Settings."),
458
+ canDeleteSetting: z.boolean().nullable().describe("Group members can delete Feature Flags and Settings."),
459
+ canCreateOrUpdateTag: z.boolean().nullable().describe("Group members can create/update Tags."),
460
+ canDeleteTag: z.boolean().nullable().describe("Group members can delete Tags."),
461
+ canManageWebhook: z.boolean().nullable().describe("Group members can create/update/delete Webhooks."),
462
+ canUseExportImport: z.boolean().nullable().describe("Group members can use the export/import feature."),
463
+ canManageProductPreferences: z.boolean().nullable().describe("Group members can update Product preferences."),
464
+ canManageIntegrations: z.boolean().nullable().describe("Group members can add and configure integrations."),
465
+ canViewSdkKey: z.boolean().nullable().describe("Group members has access to SDK keys."),
466
+ canRotateSdkKey: z.boolean().nullable().describe("Group members can rotate SDK keys."),
467
+ canCreateOrUpdateSegments: z.boolean().nullable().describe("Group members can create/update Segments."),
468
+ canDeleteSegments: z.boolean().nullable().describe("Group members can delete Segments."),
469
+ canViewProductAuditLog: z.boolean().nullable().describe("Group members has access to audit logs."),
470
+ canViewProductStatistics: z.boolean().nullable().describe("Group members has access to product statistics."),
471
+ canDisable2FA: z.boolean().nullable().describe("Group members can disable two-factor authentication for other members."),
472
+ accessType: z.enum(["readOnly", "full", "custom"]).nullable().describe("Represent the Feature Management permission."),
473
+ newEnvironmentAccessType: z.enum(["full", "readOnly", "none"]).nullable().describe("Represent the environment specific Feature Management permission."),
474
+ environmentAccesses: z.array(z.object({
475
+ environmentId: z.string().uuid().describe("Identifier of the Environment."),
476
+ environmentAccessType: z.enum(["full", "readOnly", "none"]).describe("Represent the environment specific Feature Management permission."),
477
+ })).nullable().describe("List of environment specific permissions."),
478
+ }),
479
+ },
480
+ method: "put",
481
+ pathTemplate: "/v1/permissions/{permissionGroupId}",
482
+ executionParameters: [{ "name": "permissionGroupId", "in": "path" }],
483
+ }],
484
+ ["delete-permission-group", {
485
+ name: "delete-permission-group",
486
+ description: "This endpoint removes a Permission Group identified by the `permissionGroupId` parameter.",
487
+ inputSchema: {
488
+ permissionGroupId: z.number().int().describe("The identifier of the Permission Group."),
489
+ },
490
+ method: "delete",
491
+ pathTemplate: "/v1/permissions/{permissionGroupId}",
492
+ executionParameters: [{ "name": "permissionGroupId", "in": "path" }],
493
+ }],
494
+ ["get-integration", {
495
+ name: "get-integration",
496
+ description: `This endpoint returns the metadata of an Integration
497
+ identified by the \`integrationId\`.`,
498
+ inputSchema: {
499
+ integrationId: z.string().uuid().describe("The identifier of the Integration."),
500
+ },
501
+ method: "get",
502
+ pathTemplate: "/v1/integrations/{integrationId}",
503
+ executionParameters: [{ "name": "integrationId", "in": "path" }],
504
+ }],
505
+ ["update-integration", {
506
+ name: "update-integration",
507
+ description: `This endpoint updates a Config identified by the \`integrationId\` parameter.
508
+
509
+ The Parameters dictionary differs for each IntegrationType:
510
+ - Datadog
511
+ - \`apikey\`: Required. Datadog API key.
512
+ - \`site\`: Datadog site. Available values: \`Us\`, \`Eu\`, \`Us1Fed\`, \`Us3\`, \`Us5\`. Default: \`Us\`.
513
+ - Slack
514
+ 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
+ - \`incoming_webhook.url\`: Required. The [incoming webhook URL](https://api.slack.com/messaging/webhooks) where the integration should post messages.
516
+ - Amplitude
517
+ - \`apiKey\`: Required. Amplitude API Key.
518
+ - \`secretKey\`: Required. Amplitude Secret Key.
519
+ - Mixpanel
520
+ - \`serviceAccountUserName\`: Required. Mixpanel Service Account Username.
521
+ - \`serviceAccountSecret\`: Required. Mixpanel Service Account Secret.
522
+ - \`projectId\`: Required. Mixpanel Project ID.
523
+ - \`server\`: Mixpanel Server. Available values: \`StandardServer\`, \`EUResidencyServer\`. Default: \`StandardServer\`.
524
+ - Twilio Segment
525
+ - \`writeKey\`: Required. Twilio Segment Write Key.
526
+ - \`server\`: Twilio Segment Server. Available values: \`Us\`, \`Eu\`. Default: \`Us\`.
527
+ - PubNub (work in progress)`,
528
+ inputSchema: {
529
+ integrationId: z.string().uuid().describe("The identifier of the Integration."),
530
+ requestBody: z.object({
531
+ name: z.string().min(1).describe("Name of the Integration."),
532
+ 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."),
535
+ }),
536
+ },
537
+ method: "put",
538
+ pathTemplate: "/v1/integrations/{integrationId}",
539
+ executionParameters: [{ "name": "integrationId", "in": "path" }],
540
+ }],
541
+ ["delete-integration", {
542
+ name: "delete-integration",
543
+ description: "This endpoint removes a Integration identified by the `integrationId` parameter.",
544
+ inputSchema: {
545
+ integrationId: z.string().uuid().describe("The identifier of the Integration."),
546
+ },
547
+ method: "delete",
548
+ pathTemplate: "/v1/integrations/{integrationId}",
549
+ executionParameters: [{ "name": "integrationId", "in": "path" }],
550
+ }],
551
+ ["get-sdk-keys", {
552
+ name: "get-sdk-keys",
553
+ description: "This endpoint returns the SDK Key for your Config in a specified Environment.",
554
+ inputSchema: {
555
+ configId: z.string().uuid().describe("The identifier of the Config."),
556
+ environmentId: z.string().uuid().describe("The identifier of the Environment."),
557
+ },
558
+ method: "get",
559
+ pathTemplate: "/v1/configs/{configId}/environments/{environmentId}",
560
+ executionParameters: [{ "name": "configId", "in": "path" }, { "name": "environmentId", "in": "path" }],
561
+ }],
562
+ ["list-organization-auditlogs", {
563
+ name: "list-organization-auditlogs",
564
+ description: `This endpoint returns the list of Audit log items for a given Organization
565
+ and the result can be optionally filtered by Product and/or Config and/or Environment.
566
+
567
+ If neither \`fromUtcDateTime\` nor \`toUtcDateTime\` is set, the audit logs for the **last 7 days** will be returned.
568
+
569
+ The distance between \`fromUtcDateTime\` and \`toUtcDateTime\` cannot exceed **30 days**.`,
570
+ inputSchema: {
571
+ organizationId: z.string().uuid().describe("The identifier of the Organization."),
572
+ productId: z.string().uuid().optional().describe("The identifier of the Product."),
573
+ configId: z.string().uuid().optional().describe("The identifier of the Config."),
574
+ environmentId: z.string().uuid().optional().describe("The identifier of the Environment."),
575
+ auditLogType: z.enum([
576
+ "productCreated", "productChanged", "productOwnershipTransferred", "productDeleted", "productsReordered",
577
+ "teamMemberInvited", "teamMemberInvitationRevoked", "teamMemberJoined", "teamMemberPermissionGroupChanged",
578
+ "teamMemberRemoved", "teamMemberLeft", "teamMemberInvitationChanged", "teamMemberInvitationResent",
579
+ "teamMemberInvitationRejected", "configCreated", "configChanged", "configDeleted", "configsReordered",
580
+ "environmentCreated", "environmentChanged", "environmentDeleted", "environmentsReordered", "settingCreated",
581
+ "settingChanged", "settingDeleted", "settingsReordered", "settingValueChanged", "webHookCreated",
582
+ "webHookChanged", "webHookDeleted", "permissionGroupCreated", "permissionGroupChanged", "permissionGroupDeleted",
583
+ "permissionGroupDefault", "apiKeyAdded", "apiKeyRemoved", "integrationAdded", "integrationChanged",
584
+ "integrationRemoved", "apiKeyConnected", "integrationLinkAdded", "integrationLinkRemoved", "organizationAdded",
585
+ "organizationRemoved", "organizationChanged", "organizationSubscriptionTypeChanged", "organizationAdminChanged",
586
+ "organizationAdminLeft", "twoFactorDisabledForMember", "tagAdded", "tagChanged", "tagRemoved", "settingTagAdded",
587
+ "settingTagRemoved", "publicApiAccessTokenAdded", "publicApiAccessTokenRemoved", "domainAdded", "domainVerified",
588
+ "domainRemoved", "domainSamlConfigured", "domainSamlDeleted", "autoProvisioningConfigurationChanged",
589
+ "samlIdpConfigurationAdded", "samlIdpConfigurationRemoved", "samlIdpConfigurationUpdated",
590
+ "autoProvisioningEnabledChanged", "organizationMemberJoined", "organizationMemberProductJoinRequested",
591
+ "organizationMemberProductJoinRequestRejected", "organizationMemberProductJoinRequestApproved",
592
+ "organizationMemberRemoved", "codeReferencesUploaded", "codeReferenceDeleted", "codeReferenceStaleBranchDeleted",
593
+ "segmentCreated", "segmentChanged", "segmentDeleted", "webhookSigningKeyDeleted", "webhookSigningKeyCreated",
594
+ "userProvisioningConfigurationChanged", "syncGroupProvisioningRuleChanged", "syncGroupsReordered",
595
+ "syncUserProvisioningEnabled", "syncUserProvisioningDisabled", "userEmailChanged", "userFullNameChanged",
596
+ "userDisabled", "awsConnected", "awsDisconnected", "userEnabled", "syncUserDeleted", "syncGroupDeleted",
597
+ "proxyConfigurationCreated", "proxyConfigurationChanged", "proxyConfigurationDeleted",
598
+ "proxyConfigurationSecretRegenerated", "proxyNotificationSettingsUpdated", "proxyNotificationSettingsDeleted",
599
+ "proxyNotificationSigningKeyAdded", "proxyNotificationSigningKeyDeleted",
600
+ ]).nullable().optional().describe("Filter Audit logs by Audit log type."),
601
+ fromUtcDateTime: z.string().datetime().optional().describe("Filter Audit logs by starting UTC date."),
602
+ toUtcDateTime: z.string().datetime().optional().describe("Filter Audit logs by ending UTC date."),
603
+ },
604
+ method: "get",
605
+ pathTemplate: "/v1/organizations/{organizationId}/auditlogs",
606
+ executionParameters: [{ "name": "organizationId", "in": "path" }, { "name": "productId", "in": "query" }, { "name": "configId", "in": "query" }, { "name": "environmentId", "in": "query" }, { "name": "auditLogType", "in": "query" }, { "name": "fromUtcDateTime", "in": "query" }, { "name": "toUtcDateTime", "in": "query" }],
607
+ }],
608
+ ["list-organization-members", {
609
+ name: "list-organization-members",
610
+ description: `This endpoint returns the list of Members that belongs
611
+ to the given Organization, identified by the \`organizationId\` parameter.
612
+
613
+ The results may vary based on the access level of the user who calls the endpoint:
614
+ - When it's called with Organization Admin privileges, the result will contain each member in the Organization.
615
+ - When it's called without Organization Admin privileges, the result will contain each Organization Admin along with members
616
+ of those products where the caller has \`Team members and permission groups\` (\`canManageMembers\`) permission.`,
617
+ inputSchema: {
618
+ organizationId: z.string().uuid().describe("The identifier of the Organization."),
619
+ },
620
+ method: "get",
621
+ pathTemplate: "/v2/organizations/{organizationId}/members",
622
+ executionParameters: [{ "name": "organizationId", "in": "path" }],
623
+ }],
624
+ ["list-pending-invitations-org", {
625
+ name: "list-pending-invitations-org",
626
+ description: `This endpoint returns the list of pending invitations within the
627
+ given Organization identified by the \`organizationId\` parameter.`,
628
+ inputSchema: {
629
+ organizationId: z.string().uuid().describe("The identifier of the Organization."),
630
+ },
631
+ method: "get",
632
+ pathTemplate: "/v1/organizations/{organizationId}/invitations",
633
+ executionParameters: [{ "name": "organizationId", "in": "path" }],
634
+ }],
635
+ ["list-pending-invitations", {
636
+ name: "list-pending-invitations",
637
+ description: `This endpoint returns the list of pending invitations within the
638
+ given Product identified by the \`productId\` parameter.`,
639
+ inputSchema: {
640
+ productId: z.string().uuid().describe("The identifier of the Product."),
641
+ },
642
+ method: "get",
643
+ pathTemplate: "/v1/products/{productId}/invitations",
644
+ executionParameters: [{ "name": "productId", "in": "path" }],
645
+ }],
646
+ ["get-product", {
647
+ name: "get-product",
648
+ description: `This endpoint returns the metadata of a Product
649
+ identified by the \`productId\`.`,
650
+ inputSchema: {
651
+ productId: z.string().uuid().describe("The identifier of the Product."),
652
+ },
653
+ method: "get",
654
+ pathTemplate: "/v1/products/{productId}",
655
+ executionParameters: [{ "name": "productId", "in": "path" }],
656
+ }],
657
+ ["update-product", {
658
+ name: "update-product",
659
+ description: "This endpoint updates a Product identified by the `productId` parameter.",
660
+ inputSchema: {
661
+ productId: z.string().uuid().describe("The identifier of the Product."),
662
+ requestBody: z.object({
663
+ name: z.string().min(0).max(1000).nullable().describe("The name of the Product."),
664
+ description: z.string().min(0).max(1000).nullable().describe("The description of the Product."),
665
+ order: z.number().int().nullable().describe("The order of the Product represented on the ConfigCat Dashboard. Determined from an ascending sequence of integers."),
666
+ }),
667
+ },
668
+ method: "put",
669
+ pathTemplate: "/v1/products/{productId}",
670
+ executionParameters: [{ "name": "productId", "in": "path" }],
671
+ }],
672
+ ["delete-product", {
673
+ name: "delete-product",
674
+ description: "This endpoint removes a Product identified by the `productId` parameter.",
675
+ inputSchema: {
676
+ productId: z.string().uuid().describe("The identifier of the Product."),
677
+ },
678
+ method: "delete",
679
+ pathTemplate: "/v1/products/{productId}",
680
+ executionParameters: [{ "name": "productId", "in": "path" }],
681
+ }],
682
+ ["list-product-members", {
683
+ name: "list-product-members",
684
+ description: `This endpoint returns the list of Members that belongs
685
+ to the given Product, identified by the \`productId\` parameter.`,
686
+ inputSchema: {
687
+ productId: z.string().uuid().describe("The identifier of the Product."),
688
+ },
689
+ method: "get",
690
+ pathTemplate: "/v1/products/{productId}/members",
691
+ executionParameters: [{ "name": "productId", "in": "path" }],
692
+ }],
693
+ ["get-product-preferences", {
694
+ name: "get-product-preferences",
695
+ description: `This endpoint returns the preferences of a Product
696
+ identified by the \`productId\`.`,
697
+ inputSchema: {
698
+ productId: z.string().uuid().describe("The identifier of the Product."),
699
+ },
700
+ method: "get",
701
+ pathTemplate: "/v1/products/{productId}/preferences",
702
+ executionParameters: [{ "name": "productId", "in": "path" }],
703
+ }],
704
+ ["update-product-preferences", {
705
+ name: "update-product-preferences",
706
+ description: "This endpoint updates the preferences of a Product identified by the `productId` parameter.",
707
+ inputSchema: {
708
+ productId: z.string().uuid().describe("The identifier of the Product."),
709
+ requestBody: z.object({
710
+ reasonRequired: z.boolean().nullable().describe("Indicates that a mandatory note is required for saving and publishing."),
711
+ keyGenerationMode: z.enum(["camelCase", "lowerCase", "upperCase", "pascalCase", "kebabCase"]).nullable().describe("Determines the Feature Flag key generation mode."),
712
+ showVariationId: z.boolean().nullable().describe("Indicates whether a variation ID's must be shown on the ConfigCat Dashboard."),
713
+ mandatorySettingHint: z.boolean().nullable().describe("Indicates whether Feature flags and Settings must have a hint."),
714
+ reasonRequiredEnvironments: z.array(z.object({
715
+ environmentId: z.string().uuid().describe("Identifier of the Environment."),
716
+ reasonRequired: z.boolean().describe("Indicates that a mandatory note is required in this Environment for saving and publishing."),
717
+ })).nullable().describe("List of Environments where mandatory note must be set before saving and publishing."),
718
+ }),
719
+ },
720
+ method: "post",
721
+ pathTemplate: "/v1/products/{productId}/preferences",
722
+ executionParameters: [{ "name": "productId", "in": "path" }],
723
+ }],
724
+ ["get-segment", {
725
+ name: "get-segment",
726
+ description: `This endpoint returns the metadata of a Segment
727
+ identified by the \`segmentId\`.`,
728
+ inputSchema: {
729
+ segmentId: z.string().uuid().describe("The identifier of the Segment."),
730
+ },
731
+ method: "get",
732
+ pathTemplate: "/v1/segments/{segmentId}",
733
+ executionParameters: [{ "name": "segmentId", "in": "path" }],
734
+ }],
735
+ ["update-segment", {
736
+ name: "update-segment",
737
+ description: "This endpoint updates a Segment identified by the `segmentId` parameter.",
738
+ inputSchema: {
739
+ segmentId: z.string().uuid().describe("The identifier of the Segment."),
740
+ requestBody: z.object({
741
+ name: z.string().min(0).max(255).nullable().optional().describe("Name of the Segment."),
742
+ description: z.string().min(0).max(1000).nullable().optional().describe("Description of the Segment."),
743
+ comparisonAttribute: z.string().min(0).max(1000).nullable().optional().describe("The user's attribute the evaluation process must take into account."),
744
+ comparator: z.enum([
745
+ "isOneOf", "isNotOneOf", "contains", "doesNotContain",
746
+ "semVerIsOneOf", "semVerIsNotOneOf", "semVerLess", "semVerLessOrEquals",
747
+ "semVerGreater", "semVerGreaterOrEquals", "numberEquals", "numberDoesNotEqual",
748
+ "numberLess", "numberLessOrEquals", "numberGreater", "numberGreaterOrEquals",
749
+ "sensitiveIsOneOf", "sensitiveIsNotOneOf",
750
+ ]).nullable().describe("The comparison operator the evaluation process must use when it compares the given user attribute's value with the comparison value."),
751
+ comparisonValue: z.string().nullable().optional().describe("The value to compare with the given user attribute's value."),
752
+ }),
753
+ },
754
+ method: "put",
755
+ pathTemplate: "/v1/segments/{segmentId}",
756
+ executionParameters: [{ "name": "segmentId", "in": "path" }],
757
+ }],
758
+ ["delete-segment", {
759
+ name: "delete-segment",
760
+ description: "This endpoint removes a Segment identified by the `segmentId` parameter.",
761
+ inputSchema: {
762
+ segmentId: z.string().uuid().describe("The identifier of the Segment."),
763
+ },
764
+ method: "delete",
765
+ pathTemplate: "/v1/segments/{segmentId}",
766
+ executionParameters: [{ "name": "segmentId", "in": "path" }],
767
+ }],
768
+ ["get-setting", {
769
+ name: "get-setting",
770
+ description: `This endpoint returns the metadata attributes of a Feature Flag or Setting
771
+ identified by the \`settingId\` parameter.`,
772
+ inputSchema: {
773
+ settingId: z.number().int().describe("The identifier of the Setting."),
774
+ },
775
+ method: "get",
776
+ pathTemplate: "/v1/settings/{settingId}",
777
+ executionParameters: [{ "name": "settingId", "in": "path" }],
778
+ }],
779
+ ["replace-setting", {
780
+ name: "replace-setting",
781
+ description: `This endpoint replaces the whole value of a Feature Flag or Setting
782
+ identified by the \`settingId\` parameter.
783
+
784
+ **Important:** As this endpoint is doing a complete replace, it's important to set every other attribute that you don't
785
+ want to change in its original state. Not listing one means it will reset.`,
786
+ inputSchema: {
787
+ settingId: z.number().int().describe("The identifier of the Setting."),
788
+ 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."),
793
+ }),
794
+ },
795
+ method: "put",
796
+ pathTemplate: "/v1/settings/{settingId}",
797
+ executionParameters: [{ "name": "settingId", "in": "path" }],
798
+ }],
799
+ ["delete-setting", {
800
+ name: "delete-setting",
801
+ description: `This endpoint removes a Feature Flag or Setting from a specified Config,
802
+ identified by the \`configId\` parameter.`,
803
+ inputSchema: {
804
+ settingId: z.number().int().describe("The identifier of the Setting."),
805
+ },
806
+ method: "delete",
807
+ pathTemplate: "/v1/settings/{settingId}",
808
+ executionParameters: [{ "name": "settingId", "in": "path" }],
809
+ }],
810
+ ["update-setting", {
811
+ name: "update-setting",
812
+ description: `This endpoint updates the metadata of a Feature Flag or Setting
813
+ with a collection of [JSON Patch](https://jsonpatch.com) operations in a specified Config.
814
+
815
+ Only the \`name\`, \`hint\` and \`tags\` attributes are modifiable by this endpoint.
816
+ The \`tags\` attribute is a simple collection of the [tag IDs](#operation/list-tags) attached to the given setting.
817
+
818
+ The advantage of using JSON Patch is that you can describe individual update operations on a resource
819
+ without touching attributes that you don't want to change.
820
+
821
+ For example: We have the following resource.
822
+ \`\`\`json
823
+ {
824
+ "settingId": 5345,
825
+ "key": "myGrandFeature",
826
+ "name": "Tihs is a naem with soem typos.",
827
+ "hint": "This flag controls my grandioso feature.",
828
+ "settingType": "boolean",
829
+ "tags": [
830
+ {
831
+ "tagId": 0,
832
+ "name": "sample tag",
833
+ "color": "whale"
834
+ }
835
+ ]
836
+ }
837
+ \`\`\`
838
+ If we send an update request body as below (it changes the \`name\` and adds the already existing tag with the id \`2\`):
839
+ \`\`\`json
840
+ [
841
+ {
842
+ "op": "replace",
843
+ "path": "/name",
844
+ "value": "This is the name without typos."
845
+ },
846
+ {
847
+ "op": "add",
848
+ "path": "/tags/-",
849
+ "value": 2
850
+ }
851
+ ]
852
+ \`\`\`
853
+ Only the \`name\` and \`tags\` are updated and all the other attributes remain unchanged.
854
+ So we get a response like this:
855
+ \`\`\`json
856
+ {
857
+ "settingId": 5345,
858
+ "key": "myGrandFeature",
859
+ "name": "This is the name without typos.",
860
+ "hint": "This flag controls my grandioso feature.",
861
+ "settingType": "boolean",
862
+ "tags": [
863
+ {
864
+ "tagId": 0,
865
+ "name": "sample tag",
866
+ "color": "whale"
867
+ },
868
+ {
869
+ "tagId": 2,
870
+ "name": "another tag",
871
+ "color": "koala"
872
+ }
873
+ ]
874
+ }
875
+ \`\`\``,
876
+ inputSchema: {
877
+ settingId: z.number().int().describe("The identifier of the Setting."),
878
+ requestBody: z.array(z.object({
879
+ op: z.enum(["unknown", "add", "remove", "replace", "move", "copy", "test"]).describe("The operation type."),
880
+ path: z.string().min(1).describe("The source path."),
881
+ from: z.string().nullable().describe("The target path."),
882
+ value: z.any().describe("The discrete value."),
883
+ })),
884
+ },
885
+ method: "patch",
886
+ pathTemplate: "/v1/settings/{settingId}",
887
+ executionParameters: [{ "name": "settingId", "in": "path" }],
888
+ }],
889
+ ["list-settings-by-tag", {
890
+ name: "list-settings-by-tag",
891
+ description: `This endpoint returns the list of the Settings that
892
+ has the specified Tag, identified by the \`tagId\` parameter.`,
893
+ inputSchema: {
894
+ tagId: z.number().int().describe("The identifier of the Tag."),
895
+ },
896
+ method: "get",
897
+ pathTemplate: "/v1/tags/{tagId}/settings",
898
+ executionParameters: [{ "name": "tagId", "in": "path" }],
899
+ }],
900
+ ["get-setting-value", {
901
+ name: "get-setting-value",
902
+ description: `This endpoint returns the value of a Feature Flag or Setting
903
+ in a specified Environment identified by the \`environmentId\` parameter.
904
+
905
+ The most important attributes in the response are the \`value\`, \`rolloutRules\` and \`percentageRules\`.
906
+ The \`value\` represents what the clients will get when the evaluation requests of our SDKs
907
+ are not matching to any of the defined Targeting or Percentage Rules, or when there are no additional rules to evaluate.
908
+
909
+ The \`rolloutRules\` and \`percentageRules\` attributes are representing the current
910
+ Targeting and Percentage Rules configuration of the actual Feature Flag or Setting
911
+ in an **ordered** collection, which means the order of the returned rules is matching to the
912
+ evaluation order. You can read more about these rules [here](https://configcat.com/docs/targeting/targeting-overview).`,
913
+ inputSchema: {
914
+ environmentId: z.string().uuid().describe("The identifier of the Environment."),
915
+ settingId: z.number().int().describe("The id of the Setting."),
916
+ },
917
+ method: "get",
918
+ pathTemplate: "/v1/environments/{environmentId}/settings/{settingId}/value",
919
+ executionParameters: [{ "name": "environmentId", "in": "path" }, { "name": "settingId", "in": "path" }],
920
+ }],
921
+ ["replace-setting-value", {
922
+ name: "replace-setting-value",
923
+ description: `This endpoint replaces the whole value of a Feature Flag or Setting in a specified Environment.
924
+
925
+ Only the \`value\`, \`rolloutRules\` and \`percentageRules\` attributes are modifiable by this endpoint.
926
+
927
+ **Important:** As this endpoint is doing a complete replace, it's important to set every other attribute that you don't
928
+ want to change in its original state. Not listing one means it will reset.
929
+
930
+ For example: We have the following resource.
931
+ \`\`\`json
932
+ {
933
+ "rolloutPercentageItems": [
934
+ {
935
+ "percentage": 30,
936
+ "value": true
937
+ },
938
+ {
939
+ "percentage": 70,
940
+ "value": false
941
+ }
942
+ ],
943
+ "rolloutRules": [],
944
+ "value": false
945
+ }
946
+ \`\`\`
947
+ If we send a replace request body as below:
948
+ \`\`\`json
949
+ {
950
+ "value": true
951
+ }
952
+ \`\`\`
953
+ Then besides that the default value is set to \`true\`, all the Percentage Rules are deleted.
954
+ So we get a response like this:
955
+ \`\`\`json
956
+ {
957
+ "rolloutPercentageItems": [],
958
+ "rolloutRules": [],
959
+ "value": true
960
+ }
961
+ \`\`\`
962
+
963
+ The \`rolloutRules\` property describes two types of rules:
964
+
965
+ - **Targeting rules**: When you want to add or update a targeting rule, the \`comparator\`, \`comparisonAttribute\`, and \`comparisonValue\` members are required.
966
+ - **Segment rules**: When you want to add add or update a segment rule, the \`segmentId\` which identifies the desired segment and the \`segmentComparator\` members are required.`,
967
+ inputSchema: {
968
+ environmentId: z.string().uuid().describe("The identifier of the Environment."),
969
+ settingId: z.number().int().describe("The id of the Setting."),
970
+ reason: z.string().optional().describe("The reason note for the Audit Log if the Product's \"Config changes require a reason\" preference is turned on."),
971
+ requestBody: z.object({
972
+ rolloutRules: z.array(z.object({
973
+ comparisonAttribute: z.string().min(0).max(1000).nullable().describe("The user attribute to compare."),
974
+ comparator: z.enum([
975
+ "isOneOf", "isNotOneOf", "contains", "doesNotContain",
976
+ "semVerIsOneOf", "semVerIsNotOneOf", "semVerLess", "semVerLessOrEquals",
977
+ "semVerGreater", "semVerGreaterOrEquals", "numberEquals", "numberDoesNotEqual",
978
+ "numberLess", "numberLessOrEquals", "numberGreater", "numberGreaterOrEquals",
979
+ "sensitiveIsOneOf", "sensitiveIsNotOneOf",
980
+ ]).nullable().describe("The comparison operator the evaluation process must use when it compares the given user attribute's value with the comparison value."),
981
+ comparisonValue: z.string().nullable().describe("The value to compare against."),
982
+ value: z.union([z.boolean(), z.string(), z.number()]).describe("The value to serve when the comparison matches. It must respect the setting type. In some generated clients for strictly typed languages you may use double/float properties to handle integer values."),
983
+ segmentComparator: z.enum(["isIn", "isNotIn"]).nullable().describe("The segment comparison operator used during the evaluation process."),
984
+ segmentId: z.string().uuid().nullable().describe("The segment to compare against."),
985
+ })).describe("The targeting rule collection."),
986
+ rolloutPercentageItems: z.array(z.object({
987
+ percentage: z.number().int().describe("The percentage value for the rule."),
988
+ value: z.union([z.boolean(), z.string(), z.number()]).describe("The value to serve when the user falls in the percentage rule. It must respect the setting type. In some generated clients for strictly typed languages you may use double/float properties to handle integer values."),
989
+ })).describe("The percentage rule collection."),
990
+ value: z.union([z.boolean(), z.string(), z.number()]).describe("The value to serve. It must respect the setting type. In some generated clients for strictly typed languages you may use double/float properties to handle integer values."),
991
+ }),
992
+ },
993
+ method: "put",
994
+ pathTemplate: "/v1/environments/{environmentId}/settings/{settingId}/value",
995
+ executionParameters: [{ "name": "environmentId", "in": "path" }, { "name": "settingId", "in": "path" }, { "name": "reason", "in": "query" }],
996
+ }],
997
+ ["update-setting-value", {
998
+ name: "update-setting-value",
999
+ description: `This endpoint updates the value of a Feature Flag or Setting
1000
+ with a collection of [JSON Patch](https://jsonpatch.com) operations in a specified Environment.
1001
+
1002
+ Only the \`value\`, \`rolloutRules\` and \`percentageRules\` attributes are modifiable by this endpoint.
1003
+
1004
+ The advantage of using JSON Patch is that you can describe individual update operations on a resource
1005
+ without touching attributes that you don't want to change. It supports collection reordering, so it also
1006
+ can be used for reordering the targeting rules of a Feature Flag or Setting.
1007
+
1008
+ For example: We have the following resource.
1009
+ \`\`\`json
1010
+ {
1011
+ "rolloutPercentageItems": [
1012
+ {
1013
+ "percentage": 30,
1014
+ "value": true
1015
+ },
1016
+ {
1017
+ "percentage": 70,
1018
+ "value": false
1019
+ }
1020
+ ],
1021
+ "rolloutRules": [],
1022
+ "value": false
1023
+ }
1024
+ \`\`\`
1025
+ If we send an update request body as below:
1026
+ \`\`\`json
1027
+ [
1028
+ {
1029
+ "op": "replace",
1030
+ "path": "/value",
1031
+ "value": true
1032
+ }
1033
+ ]
1034
+ \`\`\`
1035
+ Only the default value is going to be set to \`true\` and all the Percentage Rules are remaining unchanged.
1036
+ So we get a response like this:
1037
+ \`\`\`json
1038
+ {
1039
+ "rolloutPercentageItems": [
1040
+ {
1041
+ "percentage": 30,
1042
+ "value": true
1043
+ },
1044
+ {
1045
+ "percentage": 70,
1046
+ "value": false
1047
+ }
1048
+ ],
1049
+ "rolloutRules": [],
1050
+ "value": true
1051
+ }
1052
+ \`\`\`
1053
+
1054
+ The \`rolloutRules\` property describes two types of rules:
1055
+
1056
+ - **Targeting rules**: When you want to add or update a targeting rule, the \`comparator\`, \`comparisonAttribute\`, and \`comparisonValue\` members are required.
1057
+ - **Segment rules**: When you want to add add or update a segment rule, the \`segmentId\` which identifies the desired segment and the \`segmentComparator\` members are required.`,
1058
+ inputSchema: {
1059
+ environmentId: z.string().uuid().describe("The identifier of the Environment."),
1060
+ settingId: z.number().int().describe("The identifier of the Setting."),
1061
+ reason: z.string().optional().describe("The reason note for the Audit Log if the Product's \"Config changes require a reason\" preference is turned on."),
1062
+ requestBody: z.array(z.object({
1063
+ op: z.enum(["unknown", "add", "remove", "replace", "move", "copy", "test"]).describe("The operation type."),
1064
+ path: z.string().min(1).describe("The source path."),
1065
+ from: z.string().nullable().optional().describe("The target path."),
1066
+ value: z.any().optional().describe("The discrete value."),
1067
+ })),
1068
+ },
1069
+ method: "patch",
1070
+ pathTemplate: "/v1/environments/{environmentId}/settings/{settingId}/value",
1071
+ executionParameters: [{ "name": "environmentId", "in": "path" }, { "name": "settingId", "in": "path" }, { "name": "reason", "in": "query" }],
1072
+ }],
1073
+ ["get-setting-value-v2", {
1074
+ name: "get-setting-value-v2",
1075
+ description: `This endpoint returns the value of a Feature Flag or Setting
1076
+ in a specified Environment identified by the \`environmentId\` parameter.
1077
+
1078
+ The most important fields in the response are the \`defaultValue\`, \`targetingRules\`, and \`percentageEvaluationAttribute\`.
1079
+ The \`defaultValue\` represents what the clients will get when the evaluation requests of our SDKs
1080
+ are not matching to any of the defined Targeting Rules, or when there are no additional rules to evaluate.
1081
+
1082
+ The \`targetingRules\` represents the current
1083
+ Targeting Rule configuration of the actual Feature Flag or Setting
1084
+ in an **ordered** collection, which means the order of the returned rules is matching to the
1085
+ evaluation order. You can read more about these rules [here](https://configcat.com/docs/targeting/targeting-overview/).
1086
+
1087
+ The \`percentageEvaluationAttribute\` represents the custom [User Object](https://configcat.com/docs/targeting/user-object/) attribute that must be used for [percentage evaluation](https://configcat.com/docs/targeting/percentage-options/) of the Feature Flag or Setting.`,
1088
+ inputSchema: {
1089
+ environmentId: z.string().uuid().describe("The identifier of the Environment."),
1090
+ settingId: z.number().int().describe("The id of the Setting."),
1091
+ },
1092
+ method: "get",
1093
+ pathTemplate: "/v2/environments/{environmentId}/settings/{settingId}/value",
1094
+ executionParameters: [{ "name": "environmentId", "in": "path" }, { "name": "settingId", "in": "path" }],
1095
+ }],
1096
+ ["replace-setting-value-v2", {
1097
+ name: "replace-setting-value-v2",
1098
+ description: `This endpoint replaces the value and the Targeting Rules of a Feature Flag or Setting
1099
+ in a specified Environment identified by the <a target="_blank" rel="noopener noreferrer" href="https://app.configcat.com/sdkkey">SDK key</a> passed in the \`X-CONFIGCAT-SDKKEY\` header.
1100
+
1101
+ Only the \`defaultValue\`, \`targetingRules\`, and \`percentageEvaluationAttribute\` fields are modifiable by this endpoint.
1102
+
1103
+ **Important:** As this endpoint is doing a complete replace, it's important to set every other field that you don't
1104
+ want to change to its original state. Not listing one means it will reset.
1105
+
1106
+ For example: We have the following resource of a Feature Flag.
1107
+ \`\`\`json
1108
+ {
1109
+ "defaultValue": {
1110
+ "boolValue": false
1111
+ },
1112
+ "targetingRules": [
1113
+ {
1114
+ "conditions": [
1115
+ {
1116
+ "userCondition": {
1117
+ "comparisonAttribute": "Email",
1118
+ "comparator": "sensitiveTextEquals",
1119
+ "comparisonValue": {
1120
+ "stringValue": "test@example.com"
1121
+ }
1122
+ }
1123
+ }
1124
+ ],
1125
+ "percentageOptions": [],
1126
+ "value": {
1127
+ "boolValue": true
1128
+ }
1129
+ }
1130
+ ]
1131
+ }
1132
+ \`\`\`
1133
+ If we send a replace request body as below:
1134
+ \`\`\`json
1135
+ {
1136
+ "defaultValue": {
1137
+ "boolValue": true
1138
+ }
1139
+ }
1140
+ \`\`\`
1141
+ Then besides that the default served value is set to \`true\`, all the Targeting Rules are deleted.
1142
+ So we get a response like this:
1143
+ \`\`\`json
1144
+ {
1145
+ "defaultValue": {
1146
+ "boolValue": true
1147
+ },
1148
+ "targetingRules": []
1149
+ }
1150
+ \`\`\``,
1151
+ inputSchema: {
1152
+ environmentId: z.string().uuid().describe("The identifier of the Environment."),
1153
+ settingId: z.number().int().describe("The identifier of the Setting."),
1154
+ reason: z.string().optional().describe("The reason note for the Audit Log if the Product's \"Config changes require a reason\" preference is turned on."),
1155
+ requestBody: z.object({
1156
+ defaultValue: z.object({
1157
+ boolValue: z.boolean().nullable().optional().describe("The served value in case of a boolean Feature Flag."),
1158
+ stringValue: z.string().nullable().optional().describe("The served value in case of a text Setting."),
1159
+ intValue: z.number().int().nullable().optional().describe("The served value in case of a whole number Setting."),
1160
+ doubleValue: z.number().nullable().optional().describe("The served value in case of a decimal number Setting."),
1161
+ }).describe("Represents the value of a Feature Flag or Setting."),
1162
+ targetingRules: z.array(z.object({
1163
+ conditions: z.array(z.object({
1164
+ userCondition: z.object({
1165
+ comparisonAttribute: z.string().min(1).max(1000).describe("The User Object attribute that the condition is based on. Can be \"User ID\", \"Email\", \"Country\" or any custom attribute."),
1166
+ comparator: z.enum(["isOneOf", "isNotOneOf", "containsAnyOf", "doesNotContainAnyOf", "semVerIsOneOf", "semVerIsNotOneOf", "semVerLess", "semVerLessOrEquals", "semVerGreater", "semVerGreaterOrEquals", "numberEquals", "numberDoesNotEqual", "numberLess", "numberLessOrEquals", "numberGreater", "numberGreaterOrEquals", "sensitiveIsOneOf", "sensitiveIsNotOneOf", "dateTimeBefore", "dateTimeAfter", "sensitiveTextEquals", "sensitiveTextDoesNotEqual", "sensitiveTextStartsWithAnyOf", "sensitiveTextNotStartsWithAnyOf", "sensitiveTextEndsWithAnyOf", "sensitiveTextNotEndsWithAnyOf", "sensitiveArrayContainsAnyOf", "sensitiveArrayDoesNotContainAnyOf", "textEquals", "textDoesNotEqual", "textStartsWithAnyOf", "textNotStartsWithAnyOf", "textEndsWithAnyOf", "textNotEndsWithAnyOf", "arrayContainsAnyOf", "arrayDoesNotContainAnyOf"]).describe("The comparison operator which defines the relation between the comparison attribute and the comparison value."),
1167
+ comparisonValue: z.object({
1168
+ stringValue: z.string().nullable().optional().describe("The string representation of the comparison value."),
1169
+ doubleValue: z.number().nullable().optional().describe("The number representation of the comparison value."),
1170
+ listValue: z.array(z.object({
1171
+ value: z.string().describe("The actual comparison value."),
1172
+ hint: z.string().min(0).max(1500).nullable().optional().describe("An optional hint for the comparison value."),
1173
+ })).nullable().optional().describe("The list representation of the comparison value."),
1174
+ }).describe("The value that the user object's attribute is compared to."),
1175
+ }).nullable().optional().describe("Describes a condition that is based on user attributes."),
1176
+ segmentCondition: z.object({
1177
+ segmentId: z.string().uuid().describe("The segment's identifier."),
1178
+ comparator: z.enum(["isIn", "isNotIn"]).describe("The segment comparison operator used during the evaluation process."),
1179
+ }).nullable().optional().describe("Describes a condition that is based on a segment."),
1180
+ prerequisiteFlagCondition: z.object({
1181
+ prerequisiteSettingId: z.number().int().describe("The prerequisite flag's identifier."),
1182
+ comparator: z.enum(["equals", "doesNotEqual"]).describe("Prerequisite flag comparison operator used during the evaluation process."),
1183
+ prerequisiteComparisonValue: z.object({
1184
+ boolValue: z.boolean().nullable().optional().describe("The served value in case of a boolean Feature Flag."),
1185
+ stringValue: z.string().nullable().optional().describe("The served value in case of a text Setting."),
1186
+ intValue: z.number().int().nullable().optional().describe("The served value in case of a whole number Setting."),
1187
+ doubleValue: z.number().nullable().optional().describe("The served value in case of a decimal number Setting."),
1188
+ }).describe("Represents the value of a Feature Flag or Setting."),
1189
+ }).nullable().optional().describe("Describes a condition that is based on a prerequisite flag."),
1190
+ })).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"),
1191
+ percentageOptions: z.array(z.object({
1192
+ percentage: z.number().int().describe("A number between 0 and 100 that represents a randomly allocated fraction of the users."),
1193
+ value: z.object({
1194
+ boolValue: z.boolean().nullable().optional().describe("The served value in case of a boolean Feature Flag."),
1195
+ stringValue: z.string().nullable().optional().describe("The served value in case of a text Setting."),
1196
+ intValue: z.number().int().nullable().optional().describe("The served value in case of a whole number Setting."),
1197
+ doubleValue: z.number().nullable().optional().describe("The served value in case of a decimal number Setting."),
1198
+ }).describe("Represents the value of a Feature Flag or Setting."),
1199
+ })).nullable().optional().describe("The percentage options from where the evaluation process will choose a value based on the flag's percentage evaluation attribute."),
1200
+ value: z.object({
1201
+ boolValue: z.boolean().nullable().optional().describe("The served value in case of a boolean Feature Flag."),
1202
+ stringValue: z.string().nullable().optional().describe("The served value in case of a text Setting."),
1203
+ intValue: z.number().int().nullable().optional().describe("The served value in case of a whole number Setting."),
1204
+ doubleValue: z.number().nullable().optional().describe("The served value in case of a decimal number Setting."),
1205
+ }).nullable().optional().describe("Represents the value of a Feature Flag or Setting."),
1206
+ })).nullable().optional().describe("The targeting rules of the Feature Flag or Setting."),
1207
+ 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."),
1208
+ }),
1209
+ },
1210
+ method: "put",
1211
+ pathTemplate: "/v2/environments/{environmentId}/settings/{settingId}/value",
1212
+ executionParameters: [{ "name": "environmentId", "in": "path" }, { "name": "settingId", "in": "path" }, { "name": "reason", "in": "query" }],
1213
+ }],
1214
+ ["update-setting-value-v2", {
1215
+ name: "update-setting-value-v2",
1216
+ description: `This endpoint updates the value of a Feature Flag or Setting
1217
+ with a collection of [JSON Patch](https://jsonpatch.com) operations in a specified Environment.
1218
+
1219
+ Only the \`defaultValue\`, \`targetingRules\`, and \`percentageEvaluationAttribute\` fields are modifiable by this endpoint.
1220
+
1221
+ The advantage of using JSON Patch is that you can describe individual update operations on a resource
1222
+ without touching attributes that you don't want to change. It supports collection reordering, so it also
1223
+ can be used for reordering the targeting rules of a Feature Flag or Setting.
1224
+
1225
+ For example: We have the following resource of a Feature Flag.
1226
+ \`\`\`json
1227
+ {
1228
+ "defaultValue": {
1229
+ "boolValue": false
1230
+ },
1231
+ "targetingRules": [
1232
+ {
1233
+ "conditions": [
1234
+ {
1235
+ "userCondition": {
1236
+ "comparisonAttribute": "Email",
1237
+ "comparator": "sensitiveTextEquals",
1238
+ "comparisonValue": {
1239
+ "stringValue": "test@example.com"
1240
+ }
1241
+ }
1242
+ }
1243
+ ],
1244
+ "percentageOptions": [],
1245
+ "value": {
1246
+ "boolValue": true
1247
+ }
1248
+ }
1249
+ ]
1250
+ }
1251
+ \`\`\`
1252
+ If we send an update request body as below:
1253
+ \`\`\`json
1254
+ [
1255
+ {
1256
+ "op": "replace",
1257
+ "path": "/targetingRules/0/value/boolValue",
1258
+ "value": true
1259
+ }
1260
+ ]
1261
+ \`\`\`
1262
+ Only the first Targeting Rule's \`value\` is going to be set to \`false\` and all the other fields are remaining unchanged.
1263
+
1264
+ So we get a response like this:
1265
+ \`\`\`json
1266
+ {
1267
+ "defaultValue": {
1268
+ "boolValue": false
1269
+ },
1270
+ "targetingRules": [
1271
+ {
1272
+ "conditions": [
1273
+ {
1274
+ "userCondition": {
1275
+ "comparisonAttribute": "Email",
1276
+ "comparator": "sensitiveTextEquals",
1277
+ "comparisonValue": {
1278
+ "stringValue": "test@example.com"
1279
+ }
1280
+ }
1281
+ }
1282
+ ],
1283
+ "percentageOptions": [],
1284
+ "value": {
1285
+ "boolValue": false
1286
+ }
1287
+ }
1288
+ ]
1289
+ }
1290
+ \`\`\``,
1291
+ inputSchema: {
1292
+ environmentId: z.string().uuid().describe("The identifier of the Environment."),
1293
+ settingId: z.number().int().describe("The identifier of the Setting."),
1294
+ reason: z.string().optional().describe("The reason note for the Audit Log if the Product's \"Config changes require a reason\" preference is turned on."),
1295
+ requestBody: z.array(z.object({
1296
+ op: z.enum(["unknown", "add", "remove", "replace", "move", "copy", "test"]).describe("The operation type."),
1297
+ path: z.string().min(1).describe("The source path."),
1298
+ from: z.string().nullable().optional().describe("The target path."),
1299
+ value: z.any().optional().describe("The discrete value."),
1300
+ })),
1301
+ },
1302
+ method: "patch",
1303
+ pathTemplate: "/v2/environments/{environmentId}/settings/{settingId}/value",
1304
+ executionParameters: [{ "name": "environmentId", "in": "path" }, { "name": "settingId", "in": "path" }, { "name": "reason", "in": "query" }],
1305
+ }],
1306
+ ["get-setting-values", {
1307
+ name: "get-setting-values",
1308
+ description: `This endpoint returns the value of a specified Config's Feature Flags or Settings identified by the \`configId\` parameter
1309
+ in a specified Environment identified by the \`environmentId\` parameter.
1310
+
1311
+ The most important attributes in the response are the \`value\`, \`rolloutRules\` and \`percentageRules\`.
1312
+ The \`value\` represents what the clients will get when the evaluation requests of our SDKs
1313
+ are not matching to any of the defined Targeting or Percentage Rules, or when there are no additional rules to evaluate.
1314
+
1315
+ The \`rolloutRules\` and \`percentageRules\` attributes are representing the current
1316
+ Targeting and Percentage Rules configuration of the actual Feature Flag or Setting
1317
+ in an **ordered** collection, which means the order of the returned rules is matching to the
1318
+ evaluation order. You can read more about these rules [here](https://configcat.com/docs/targeting/targeting-overview/).`,
1319
+ inputSchema: {
1320
+ configId: z.string().uuid().describe("The identifier of the Config."),
1321
+ environmentId: z.string().uuid().describe("The identifier of the Environment."),
1322
+ },
1323
+ method: "get",
1324
+ pathTemplate: "/v1/configs/{configId}/environments/{environmentId}/values",
1325
+ executionParameters: [{ "name": "configId", "in": "path" }, { "name": "environmentId", "in": "path" }],
1326
+ }],
1327
+ ["post-setting-values", {
1328
+ name: "post-setting-values",
1329
+ description: `This endpoint replaces the values of a specified Config's Feature Flags or Settings identified by the \`configId\` parameter
1330
+ in a specified Environment identified by the \`environmentId\` parameter.
1331
+
1332
+ Only the \`value\`, \`rolloutRules\` and \`percentageRules\` attributes are modifiable by this endpoint.
1333
+
1334
+ **Important:** As this endpoint is doing a complete replace, it's important to set every other attribute that you don't
1335
+ want to change in its original state. Not listing one means it will reset.
1336
+
1337
+ For example: We have the following resource.
1338
+ \`\`\`json
1339
+ {
1340
+ "settingValues": [
1341
+ {
1342
+ "rolloutPercentageItems": [
1343
+ {
1344
+ "percentage": 30,
1345
+ "value": true
1346
+ },
1347
+ {
1348
+ "percentage": 70,
1349
+ "value": false
1350
+ }
1351
+ ],
1352
+ "rolloutRules": [],
1353
+ "value": false,
1354
+ "settingId": 1
1355
+ }
1356
+ ]
1357
+ }
1358
+ \`\`\`
1359
+ If we send a replace request body as below:
1360
+ \`\`\`json
1361
+ {
1362
+ "settingValues": [
1363
+ {
1364
+ "value": true,
1365
+ "settingId": 1
1366
+ }
1367
+ ]
1368
+ }
1369
+ \`\`\`
1370
+ Then besides that the default value is set to \`true\`, all the Percentage Rules are deleted.
1371
+ So we get a response like this:
1372
+ \`\`\`json
1373
+ {
1374
+ "settingValues": [
1375
+ {
1376
+ "rolloutPercentageItems": [],
1377
+ "rolloutRules": [],
1378
+ "value": true,
1379
+ "setting":
1380
+ {
1381
+ "settingId": 1
1382
+ }
1383
+ }
1384
+ ]
1385
+ }
1386
+ \`\`\`
1387
+
1388
+ The \`rolloutRules\` property describes two types of rules:
1389
+
1390
+ - **Targeting rules**: When you want to add or update a targeting rule, the \`comparator\`, \`comparisonAttribute\`, and \`comparisonValue\` members are required.
1391
+ - **Segment rules**: When you want to add add or update a segment rule, the \`segmentId\` which identifies the desired segment and the \`segmentComparator\` members are required.`,
1392
+ inputSchema: {
1393
+ configId: z.string().uuid().describe("The identifier of the Config."),
1394
+ environmentId: z.string().uuid().describe("The identifier of the Environment."),
1395
+ reason: z.string().optional().describe("The reason note for the Audit Log if the Product's \"Config changes require a reason\" preference is turned on."),
1396
+ requestBody: z.object({
1397
+ settingValues: z.array(z.object({
1398
+ rolloutRules: z.array(z.object({
1399
+ comparisonAttribute: z.string().min(0).max(1000).nullable().optional().describe("The user attribute to compare."),
1400
+ comparator: z.enum(["isOneOf", "isNotOneOf", "contains", "doesNotContain", "semVerIsOneOf", "semVerIsNotOneOf", "semVerLess", "semVerLessOrEquals", "semVerGreater", "semVerGreaterOrEquals", "numberEquals", "numberDoesNotEqual", "numberLess", "numberLessOrEquals", "numberGreater", "numberGreaterOrEquals", "sensitiveIsOneOf", "sensitiveIsNotOneOf"]).nullable().optional().describe("The comparison operator the evaluation process must use when it compares the given user attribute's value with the comparison value."),
1401
+ comparisonValue: z.string().nullable().optional().describe("The value to compare against."),
1402
+ value: z.union([z.boolean(), z.string(), z.number()]).describe("The value to serve when the comparison matches. It must respect the setting type. In some generated clients for strictly typed languages you may use double/float properties to handle integer values."),
1403
+ segmentComparator: z.enum(["isIn", "isNotIn"]).nullable().optional().describe("The segment comparison operator used during the evaluation process."),
1404
+ segmentId: z.string().uuid().nullable().optional().describe("The segment to compare against."),
1405
+ })).optional().describe("The targeting rule collection."),
1406
+ rolloutPercentageItems: z.array(z.object({
1407
+ percentage: z.number().int().describe("The percentage value for the rule."),
1408
+ value: z.union([z.boolean(), z.string(), z.number()]).describe("The value to serve when the user falls in the percentage rule. It must respect the setting type. In some generated clients for strictly typed languages you may use double/float properties to handle integer values."),
1409
+ })).optional().describe("The percentage rule collection."),
1410
+ value: z.union([z.boolean(), z.string(), z.number()]).describe("The value to serve. It must respect the setting type. In some generated clients for strictly typed languages you may use double/float properties to handle integer values."),
1411
+ settingId: z.number().int().optional().describe("The identifier of the Setting."),
1412
+ })).describe("The values to update."),
1413
+ }),
1414
+ },
1415
+ method: "post",
1416
+ pathTemplate: "/v1/configs/{configId}/environments/{environmentId}/values",
1417
+ executionParameters: [{ "name": "configId", "in": "path" }, { "name": "environmentId", "in": "path" }, { "name": "reason", "in": "query" }],
1418
+ }],
1419
+ ["get-setting-values-v2", {
1420
+ name: "get-setting-values-v2",
1421
+ description: `This endpoint returns all Feature Flag and Setting values of a Config identified by the \`configId\` parameter
1422
+ in a specified Environment identified by the \`environmentId\` parameter.
1423
+
1424
+ The most important fields in the response are the \`defaultValue\`, \`targetingRules\`.
1425
+ The \`defaultValue\` represents what the clients will get when the evaluation requests of our SDKs
1426
+ are not matching to any of the defined Targeting Rules, or when there are no additional rules to evaluate.
1427
+
1428
+ The \`targetingRules\` represents the current
1429
+ Targeting Rule configuration of the actual Feature Flag or Setting
1430
+ in an **ordered** collection, which means the order of the returned rules is matching to the
1431
+ evaluation order. You can read more about these rules [here](https://configcat.com/docs/targeting/targeting-overview/).
1432
+
1433
+ The \`percentageEvaluationAttribute\` represents the custom [User Object](https://configcat.com/docs/targeting/user-object/) attribute that must be used for [percentage evaluation](https://configcat.com/docs/targeting/percentage-options/) of the Feature Flag or Setting.`,
1434
+ inputSchema: {
1435
+ configId: z.string().uuid().describe("The identifier of the Config."),
1436
+ environmentId: z.string().uuid().describe("The identifier of the Environment."),
1437
+ },
1438
+ method: "get",
1439
+ pathTemplate: "/v2/configs/{configId}/environments/{environmentId}/values",
1440
+ executionParameters: [{ "name": "configId", "in": "path" }, { "name": "environmentId", "in": "path" }],
1441
+ }],
1442
+ ["post-setting-values-v2", {
1443
+ name: "post-setting-values-v2",
1444
+ description: `This endpoint batch updates the Feature Flags and Settings of a Config identified by the \`configId\` parameter
1445
+ in a specified Environment identified by the \`environmentId\` parameter.
1446
+
1447
+ Only those Feature Flags and Settings are updated which are part of the request, all the others are left untouched.
1448
+
1449
+ **Important:** As this endpoint is doing a complete replace on those Feature Flags and Settings, which are set in the request.
1450
+ It's important to set every other field that you don't want to change in its original state. Not listing a field means that it will reset.
1451
+
1452
+ For example: We have the following resource of a Feature Flag.
1453
+ \`\`\`json
1454
+ {
1455
+ "settingFormulas": [
1456
+ {
1457
+ "defaultValue": {
1458
+ "boolValue": false
1459
+ },
1460
+ "targetingRules": [
1461
+ {
1462
+ "conditions": [
1463
+ {
1464
+ "userCondition": {
1465
+ "comparisonAttribute": "Email",
1466
+ "comparator": "sensitiveTextEquals",
1467
+ "comparisonValue": {
1468
+ "stringValue": "test@example.com"
1469
+ }
1470
+ }
1471
+ }
1472
+ ],
1473
+ "percentageOptions": [],
1474
+ "value": {
1475
+ "boolValue": true
1476
+ }
1477
+ }
1478
+ ],
1479
+ "settingId": 1
1480
+ }
1481
+ ]
1482
+ }
1483
+ \`\`\`
1484
+ If we send a batch replace request body as below:
1485
+ \`\`\`json
1486
+ {
1487
+ "updateFormulas": [
1488
+ {
1489
+ "defaultValue": {
1490
+ "boolValue": false
1491
+ },
1492
+ "settingId": 1
1493
+ }
1494
+ ]
1495
+ }
1496
+ \`\`\`
1497
+ Then besides that the default value is set to \`true\`, all Targeting Rules of the related Feature Flag are deleted.
1498
+ So we get a response like this:
1499
+ \`\`\`json
1500
+ {
1501
+ "settingFormulas": [
1502
+ {
1503
+ "defaultValue": {
1504
+ "boolValue": false
1505
+ },
1506
+ "targetingRules": [],
1507
+ "setting":
1508
+ {
1509
+ "settingId": 1
1510
+ }
1511
+ }
1512
+ ]
1513
+ }
1514
+ \`\`\``,
1515
+ inputSchema: {
1516
+ configId: z.string().uuid(),
1517
+ environmentId: z.string().uuid(),
1518
+ reason: z.string().optional(),
1519
+ requestBody: z.object({
1520
+ updateFormulas: z.array(z.object({
1521
+ defaultValue: z.object({
1522
+ boolValue: z.boolean().nullable().optional().describe("The served value in case of a boolean Feature Flag."),
1523
+ stringValue: z.string().nullable().optional().describe("The served value in case of a text Setting."),
1524
+ intValue: z.number().int().nullable().optional().describe("The served value in case of a whole number Setting."),
1525
+ doubleValue: z.number().nullable().optional().describe("The served value in case of a decimal number Setting."),
1526
+ }).describe("Represents the value of a Feature Flag or Setting."),
1527
+ targetingRules: z.array(z.object({
1528
+ conditions: z.array(z.object({
1529
+ userCondition: z.object({
1530
+ comparisonAttribute: z.string().min(1).max(1000).describe("The User Object attribute that the condition is based on. Can be \"User ID\", \"Email\", \"Country\" or any custom attribute."),
1531
+ comparator: z.enum(["isOneOf", "isNotOneOf", "containsAnyOf", "doesNotContainAnyOf", "semVerIsOneOf", "semVerIsNotOneOf", "semVerLess", "semVerLessOrEquals", "semVerGreater", "semVerGreaterOrEquals", "numberEquals", "numberDoesNotEqual", "numberLess", "numberLessOrEquals", "numberGreater", "numberGreaterOrEquals", "sensitiveIsOneOf", "sensitiveIsNotOneOf", "dateTimeBefore", "dateTimeAfter", "sensitiveTextEquals", "sensitiveTextDoesNotEqual", "sensitiveTextStartsWithAnyOf", "sensitiveTextNotStartsWithAnyOf", "sensitiveTextEndsWithAnyOf", "sensitiveTextNotEndsWithAnyOf", "sensitiveArrayContainsAnyOf", "sensitiveArrayDoesNotContainAnyOf", "textEquals", "textDoesNotEqual", "textStartsWithAnyOf", "textNotStartsWithAnyOf", "textEndsWithAnyOf", "textNotEndsWithAnyOf", "arrayContainsAnyOf", "arrayDoesNotContainAnyOf"]).describe("The comparison operator which defines the relation between the comparison attribute and the comparison value."),
1532
+ comparisonValue: z.object({
1533
+ stringValue: z.string().nullable().optional().describe("The string representation of the comparison value."),
1534
+ doubleValue: z.number().nullable().optional().describe("The number representation of the comparison value."),
1535
+ listValue: z.array(z.object({
1536
+ value: z.string().describe("The actual comparison value."),
1537
+ hint: z.string().min(0).max(1500).nullable().optional().describe("An optional hint for the comparison value."),
1538
+ })).nullable().optional().describe("The list representation of the comparison value."),
1539
+ }).describe("The value that the user object's attribute is compared to."),
1540
+ }).nullable().optional().describe("Describes a condition that is based on user attributes."),
1541
+ segmentCondition: z.object({
1542
+ segmentId: z.string().uuid().describe("The segment's identifier."),
1543
+ comparator: z.enum(["isIn", "isNotIn"]).describe("The segment comparison operator used during the evaluation process."),
1544
+ }).nullable().optional().describe("Describes a condition that is based on a segment."),
1545
+ prerequisiteFlagCondition: z.object({
1546
+ prerequisiteSettingId: z.number().int().describe("the prerequisite flag's identifier"),
1547
+ comparator: z.enum(["equals", "doesNotEqual"]).describe("Prerequisite flag comparison operator used during the evaluation process."),
1548
+ prerequisiteComparisonValue: z.object({
1549
+ boolValue: z.boolean().nullable().optional().describe("The served value in case of a boolean Feature Flag."),
1550
+ stringValue: z.string().nullable().optional().describe("The served value in case of a text Setting."),
1551
+ intValue: z.number().int().nullable().optional().describe("The served value in case of a whole number Setting."),
1552
+ doubleValue: z.number().nullable().optional().describe("The served value in case of a decimal number Setting."),
1553
+ }).describe("Represents the value of a Feature Flag or Setting."),
1554
+ }).nullable().optional(),
1555
+ })).nullable().optional(),
1556
+ percentageOptions: z.array(z.object({
1557
+ percentage: z.number().int().describe("A number between 0 and 100 that represents a randomly allocated fraction of the users."),
1558
+ value: z.object({
1559
+ boolValue: z.boolean().nullable().optional().describe("The served value in case of a boolean Feature Flag."),
1560
+ stringValue: z.string().nullable().optional().describe("The served value in case of a text Setting."),
1561
+ intValue: z.number().int().nullable().optional().describe("The served value in case of a whole number Setting."),
1562
+ doubleValue: z.number().nullable().optional().describe("The served value in case of a decimal number Setting."),
1563
+ }).describe("Represents the value of a Feature Flag or Setting."),
1564
+ })).nullable().optional().describe("The percentage options from where the evaluation process will choose a value based on the flag's percentage evaluation attribute."),
1565
+ value: z.object({
1566
+ boolValue: z.boolean().nullable().optional().describe("The served value in case of a boolean Feature Flag."),
1567
+ stringValue: z.string().nullable().optional().describe("The served value in case of a text Setting."),
1568
+ intValue: z.number().int().nullable().optional().describe("The served value in case of a whole number Setting."),
1569
+ doubleValue: z.number().nullable().optional().describe("The served value in case of a decimal number Setting."),
1570
+ }).nullable().optional().describe("Represents the value of a Feature Flag or Setting."),
1571
+ })).nullable().optional().describe("The targeting rules of the Feature Flag or Setting."),
1572
+ 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."),
1573
+ settingId: z.number().int().describe("The identifier of the feature flag or setting."),
1574
+ })).describe("Evaluation descriptors of each updated Feature Flag and Setting."),
1575
+ }),
1576
+ },
1577
+ method: "post",
1578
+ pathTemplate: "/v2/configs/{configId}/environments/{environmentId}/values",
1579
+ executionParameters: [{ "name": "configId", "in": "path" }, { "name": "environmentId", "in": "path" }, { "name": "reason", "in": "query" }],
1580
+ }],
1581
+ ["get-tag", {
1582
+ name: "get-tag",
1583
+ description: `This endpoint returns the metadata of a Tag
1584
+ identified by the \`tagId\`.`,
1585
+ inputSchema: {
1586
+ tagId: z.number().int().describe("The identifier of the Tag."),
1587
+ },
1588
+ method: "get",
1589
+ pathTemplate: "/v1/tags/{tagId}",
1590
+ executionParameters: [{ "name": "tagId", "in": "path" }],
1591
+ }],
1592
+ ["update-tag", {
1593
+ name: "update-tag",
1594
+ description: "This endpoint updates a Tag identified by the `tagId` parameter.",
1595
+ inputSchema: {
1596
+ tagId: z.number().int(),
1597
+ requestBody: z.object({
1598
+ name: z.string().min(0).max(255).nullable().optional().describe("The name of the Tag."),
1599
+ color: z.string().min(0).max(255).nullable().optional().describe("Color of the Tag. Possible values: `panther`, `whale`, `salmon`, `lizard`, `canary`, `koala`, or any HTML color code."),
1600
+ }),
1601
+ },
1602
+ method: "put",
1603
+ pathTemplate: "/v1/tags/{tagId}",
1604
+ executionParameters: [{ "name": "tagId", "in": "path" }],
1605
+ }],
1606
+ ["delete-tag", {
1607
+ name: "delete-tag",
1608
+ description: "This endpoint deletes a Tag identified by the `tagId` parameter. To remove a Tag from a Feature Flag or Setting use the [Update Flag](#operation/update-setting) endpoint.",
1609
+ inputSchema: {
1610
+ tagId: z.number().int().describe("The identifier of the Tag."),
1611
+ },
1612
+ method: "delete",
1613
+ pathTemplate: "/v1/tags/{tagId}",
1614
+ executionParameters: [{ "name": "tagId", "in": "path" }],
1615
+ }],
1616
+ ["get-webhook", {
1617
+ name: "get-webhook",
1618
+ description: `This endpoint returns the metadata of a Webhook
1619
+ identified by the \`webhookId\`.`,
1620
+ inputSchema: {
1621
+ webhookId: z.number().int().describe("The identifier of the Webhook."),
1622
+ },
1623
+ method: "get",
1624
+ pathTemplate: "/v1/webhooks/{webhookId}",
1625
+ executionParameters: [{ "name": "webhookId", "in": "path" }],
1626
+ }],
1627
+ ["replace-webhook", {
1628
+ name: "replace-webhook",
1629
+ description: `This endpoint replaces the whole value of a Webhook identified by the \`webhookId\` parameter.
1630
+
1631
+ **Important:** As this endpoint is doing a complete replace, it's important to set every other attribute that you don't
1632
+ want to change in its original state. Not listing one means it will reset.`,
1633
+ inputSchema: {
1634
+ webhookId: z.number().int().describe("The identifier of the Webhook."),
1635
+ requestBody: z.object({
1636
+ url: z.string().min(7).max(1000).describe("The URL of the Webhook."),
1637
+ content: z.string().min(0).max(15000).nullable().optional().describe("The HTTP body content."),
1638
+ httpMethod: z.enum(["get", "post"]).nullable().optional(),
1639
+ webHookHeaders: z.array(z.object({
1640
+ key: z.string().min(1).max(255),
1641
+ value: z.string().min(1).max(1000),
1642
+ isSecure: z.boolean().optional().describe("Indicates whether the header value is sensitive."),
1643
+ })).nullable().optional().describe("List of HTTP headers."),
1644
+ }),
1645
+ },
1646
+ method: "put",
1647
+ pathTemplate: "/v1/webhooks/{webhookId}",
1648
+ executionParameters: [{ "name": "webhookId", "in": "path" }],
1649
+ }],
1650
+ ["delete-webhook", {
1651
+ name: "delete-webhook",
1652
+ description: "This endpoint removes a Webhook identified by the `webhookId` parameter.",
1653
+ inputSchema: {
1654
+ webhookId: z.number().int().describe("The identifier of the Webhook."),
1655
+ },
1656
+ method: "delete",
1657
+ pathTemplate: "/v1/webhooks/{webhookId}",
1658
+ executionParameters: [{ "name": "webhookId", "in": "path" }],
1659
+ }],
1660
+ ["update-webhook", {
1661
+ name: "update-webhook",
1662
+ description: `This endpoint updates a Webhook identified by the \`webhookId\` parameter with a collection of [JSON Patch](https://jsonpatch.com) operations.
1663
+
1664
+ The advantage of using JSON Patch is that you can describe individual update operations on a resource without touching attributes that you don't want to change.
1665
+
1666
+ For example: We have the following resource.
1667
+ \`\`\`json
1668
+ {
1669
+ "webhookId": 6,
1670
+ "url": "https://example.com/hook",
1671
+ "httpMethod": "post",
1672
+ "content": "null",
1673
+ "webHookHeaders": []
1674
+ }
1675
+ \`\`\`
1676
+ If we send an update request body as below (it changes the \`content\` field and adds a new HTTP header):
1677
+ \`\`\`json
1678
+ [
1679
+ {
1680
+ "op": "replace",
1681
+ "path": "/content",
1682
+ "value": "Some webhook content."
1683
+ },
1684
+ {
1685
+ "op": "add",
1686
+ "path": "/webHookHeaders/-",
1687
+ "value": {
1688
+ "key": "X-Custom-Header",
1689
+ "value": "Custom header value"
1690
+ }
1691
+ }
1692
+ ]
1693
+ \`\`\`
1694
+ Only the \`content\` and \`webHookHeaders\` are updated and all the other attributes remain unchanged.
1695
+ So we get a response like this:
1696
+ \`\`\`json
1697
+ {
1698
+ "webhookId": 6,
1699
+ "url": "https://example.com/hook",
1700
+ "httpMethod": "post",
1701
+ "content": "Some webhook content.",
1702
+ "webHookHeaders": [
1703
+ {
1704
+ "key": "X-Custom-Header",
1705
+ "value": "Custom header value",
1706
+ "isSecure": false
1707
+ }
1708
+ ]
1709
+ }
1710
+ \`\`\``,
1711
+ inputSchema: {
1712
+ webhookId: z.number().int().describe("The identifier of the Webhook."),
1713
+ requestBody: z.array(z.object({
1714
+ op: z.enum(["unknown", "add", "remove", "replace", "move", "copy", "test"]).describe("The operation type."),
1715
+ path: z.string().min(1).describe("The source path."),
1716
+ from: z.string().nullable().optional().describe("The target path."),
1717
+ value: z.any().optional().describe("The discrete value."),
1718
+ })),
1719
+ },
1720
+ method: "patch",
1721
+ pathTemplate: "/v1/webhooks/{webhookId}",
1722
+ executionParameters: [{ "name": "webhookId", "in": "path" }],
1723
+ }],
1724
+ ["get-webhook-signing-keys", {
1725
+ name: "get-webhook-signing-keys",
1726
+ description: `This endpoint returns the signing keys of a Webhook
1727
+ identified by the \`webhookId\`.
1728
+
1729
+ Signing keys are used for ensuring the Webhook requests you receive are actually sent by ConfigCat.
1730
+
1731
+ <a href="https://configcat.com/docs/advanced/notifications-webhooks/#verifying-webhook-requests" target="_blank" rel="noopener noreferrer">Here</a> you can read more about Webhook request verification.`,
1732
+ inputSchema: {
1733
+ webhookId: z.number().int().describe("The identifier of the Webhook."),
1734
+ },
1735
+ method: "get",
1736
+ pathTemplate: "/v1/webhooks/{webhookId}/keys",
1737
+ executionParameters: [{ "name": "webhookId", "in": "path" }],
1738
+ }],
1739
+ ["create-product", {
1740
+ name: "create-product",
1741
+ description: `This endpoint creates a new Product in a specified Organization
1742
+ identified by the \`organizationId\` parameter, which can be obtained from the [List Organizations](#operation/list-organizations) endpoint.`,
1743
+ inputSchema: {
1744
+ organizationId: z.string().uuid().describe("The identifier of the Organization."),
1745
+ requestBody: z.object({
1746
+ name: z.string().min(1).max(1000).describe("The name of the Product."),
1747
+ description: z.string().min(0).max(1000).nullable().optional().describe("The description of the Product."),
1748
+ order: z.number().int().nullable().optional().describe("The order of the Product represented on the ConfigCat Dashboard. Determined from an ascending sequence of integers."),
1749
+ }),
1750
+ },
1751
+ method: "post",
1752
+ pathTemplate: "/v1/organizations/{organizationId}/products",
1753
+ executionParameters: [{ "name": "organizationId", "in": "path" }],
1754
+ }],
1755
+ ["create-webhook", {
1756
+ name: "create-webhook",
1757
+ description: `This endpoint creates a new Webhook in a specified Product
1758
+ identified by the \`productId\` parameter, which can be obtained from the [List Products](#operation/list-products) endpoint.`,
1759
+ inputSchema: {
1760
+ configId: z.string().uuid().describe("The identifier of the Config."),
1761
+ environmentId: z.string().uuid().describe("The identifier of the Environment."),
1762
+ requestBody: z.object({
1763
+ url: z.string().min(7).max(1000).describe("The URL of the Webhook."),
1764
+ content: z.string().min(0).max(15000).nullable().optional().describe("The HTTP body content."),
1765
+ httpMethod: z.enum(["get", "post"]).nullable().optional(),
1766
+ webHookHeaders: z.array(z.object({
1767
+ key: z.string().min(1).max(255),
1768
+ value: z.string().min(1).max(1000),
1769
+ isSecure: z.boolean().optional().describe("Indicates whether the header value is sensitive."),
1770
+ })).nullable().optional().describe("List of HTTP headers."),
1771
+ }),
1772
+ },
1773
+ method: "post",
1774
+ pathTemplate: "/v1/configs/{configId}/environments/{environmentId}/webhooks",
1775
+ executionParameters: [{ "name": "configId", "in": "path" }, { "name": "environmentId", "in": "path" }],
1776
+ }],
1777
+ ["invite-member", {
1778
+ name: "invite-member",
1779
+ description: "This endpoint invites a Member into the given Product identified by the `productId` parameter.",
1780
+ inputSchema: {
1781
+ productId: z.string().uuid().describe("The identifier of the Product."),
1782
+ requestBody: z.object({
1783
+ emails: z.array(z.string()).describe("List of email addresses to invite."),
1784
+ permissionGroupId: z.number().int().describe("Identifier of the Permission Group to where the invited users should be added."),
1785
+ }),
1786
+ },
1787
+ method: "post",
1788
+ pathTemplate: "/v1/products/{productId}/members/invite",
1789
+ executionParameters: [{ "name": "productId", "in": "path" }],
1790
+ }],
1791
+ ["update-member-permissions", {
1792
+ name: "update-member-permissions",
1793
+ description: `This endpoint updates the permissions of a Member identified by the \`userId\`.
1794
+ This endpoint can also be used to move a Member between Permission Groups within a Product.
1795
+ Only a single Permission Group can be set per Product.`,
1796
+ inputSchema: {
1797
+ organizationId: z.string().uuid().describe("The identifier of the Organization."),
1798
+ userId: z.string().describe("The identifier of the Member."),
1799
+ requestBody: z.object({
1800
+ permissionGroupIds: z.array(z.number().int()).nullable().optional().describe("List of Permission Group identifiers to where the Member should be added."),
1801
+ isAdmin: z.boolean().nullable().optional().describe("Indicates that the member must be Organization Admin."),
1802
+ isBillingManager: z.boolean().nullable().optional().describe("Indicates that the member must be Billing Manager."),
1803
+ removeFromPermissionGroupsWhereIdNotSet: z.boolean().optional().describe("When `true`, the member will be removed from those Permission Groups that are not listed in the `permissionGroupIds` field."),
1804
+ }),
1805
+ },
1806
+ method: "post",
1807
+ pathTemplate: "/v1/organizations/{organizationId}/members/{userId}",
1808
+ executionParameters: [{ "name": "organizationId", "in": "path" }, { "name": "userId", "in": "path" }],
1809
+ }],
1810
+ ["delete-organization-member", {
1811
+ name: "delete-organization-member",
1812
+ description: `This endpoint removes a Member identified by the \`userId\` from the
1813
+ given Organization identified by the \`organizationId\` parameter.`,
1814
+ inputSchema: {
1815
+ organizationId: z.string().uuid().describe("The identifier of the Organization."),
1816
+ userId: z.string().describe("The identifier of the Member."),
1817
+ },
1818
+ method: "delete",
1819
+ pathTemplate: "/v1/organizations/{organizationId}/members/{userId}",
1820
+ executionParameters: [{ "name": "organizationId", "in": "path" }, { "name": "userId", "in": "path" }],
1821
+ }],
1822
+ ["delete-invitation", {
1823
+ name: "delete-invitation",
1824
+ description: "This endpoint removes an Invitation identified by the `invitationId` parameter.",
1825
+ inputSchema: {
1826
+ invitationId: z.string().uuid().describe("The identifier of the Invitation."),
1827
+ },
1828
+ method: "delete",
1829
+ pathTemplate: "/v1/invitations/{invitationId}",
1830
+ executionParameters: [{ "name": "invitationId", "in": "path" }],
1831
+ }],
1832
+ ["delete-product-member", {
1833
+ name: "delete-product-member",
1834
+ description: `This endpoint removes a Member identified by the \`userId\` from the
1835
+ given Product identified by the \`productId\` parameter.`,
1836
+ inputSchema: {
1837
+ productId: z.string().uuid().describe("The identifier of the Product."),
1838
+ userId: z.string().describe("The identifier of the Member."),
1839
+ },
1840
+ method: "delete",
1841
+ pathTemplate: "/v1/products/{productId}/members/{userId}",
1842
+ executionParameters: [{ "name": "productId", "in": "path" }, { "name": "userId", "in": "path" }],
1843
+ }],
1844
+ ]);
1845
+ /**
1846
+ * Registers the ConfigCat API tools with the given server and HTTP client.
1847
+ *
1848
+ * @param server The server instance to register the tools with.
1849
+ * @param http The HTTP client instance to use for API requests.
1850
+ */
1851
+ export function registerConfigCatAPITools(server, http) {
1852
+ for (const [toolName, toolDefinition] of toolDefinitionMap.entries()) {
1853
+ server.tool(toolName, toolDefinition.description, toolDefinition.inputSchema, async (toolArgs) => {
1854
+ return await executeApiTool(http, toolName, toolDefinition, toolArgs ?? {});
1855
+ });
1856
+ }
1857
+ }
1858
+ /**
1859
+ * Executes an API tool with the provided arguments
1860
+ *
1861
+ * @param toolName Name of the tool to execute
1862
+ * @param definition Tool definition
1863
+ * @param toolArgs Arguments provided by the user
1864
+ * @returns Call tool result
1865
+ */
1866
+ async function executeApiTool(http, toolName, definition, toolArgs) {
1867
+ try {
1868
+ // Validate arguments against the input schema
1869
+ let validatedArgs;
1870
+ try {
1871
+ const zodSchema = z.object(definition.inputSchema);
1872
+ const argsToParse = (typeof toolArgs === "object" && toolArgs !== null) ? toolArgs : {};
1873
+ validatedArgs = zodSchema.parse(argsToParse);
1874
+ }
1875
+ catch (error) {
1876
+ if (error instanceof ZodError) {
1877
+ const validationErrorMessage = `Invalid arguments for tool '${toolName}': ${error.errors.map(e => `${e.path.join(".")} (${e.code}): ${e.message}`).join(", ")}`;
1878
+ return { content: [{ type: "text", text: validationErrorMessage }] };
1879
+ }
1880
+ else {
1881
+ const errorMessage = error instanceof Error ? error.message : String(error);
1882
+ return { content: [{ type: "text", text: `Internal error during validation setup: ${errorMessage}` }] };
1883
+ }
1884
+ }
1885
+ // Prepare URL, query parameters, headers, and request body
1886
+ let urlPath = definition.pathTemplate;
1887
+ const queryParams = {};
1888
+ const headers = {};
1889
+ let requestBodyData;
1890
+ // Apply parameters to the URL path, query, or headers
1891
+ definition.executionParameters.forEach((param) => {
1892
+ const value = validatedArgs[param.name];
1893
+ if (typeof value !== "undefined" && value !== null) {
1894
+ if (param.in === "path") {
1895
+ const stringValue = typeof value === "string" ? value : JSON.stringify(value);
1896
+ urlPath = urlPath.replace(`{${param.name}}`, encodeURIComponent(stringValue));
1897
+ }
1898
+ else if (param.in === "query") {
1899
+ queryParams[param.name] = value;
1900
+ }
1901
+ else if (param.in === "header") {
1902
+ const stringValue = typeof value === "string" ? value : JSON.stringify(value);
1903
+ headers[param.name.toLowerCase()] = stringValue;
1904
+ }
1905
+ }
1906
+ });
1907
+ // Ensure all path parameters are resolved
1908
+ if (urlPath.includes("{")) {
1909
+ throw new Error(`Failed to resolve path parameters: ${urlPath}`);
1910
+ }
1911
+ // Handle request body if needed
1912
+ if (typeof validatedArgs["requestBody"] !== "undefined") {
1913
+ requestBodyData = validatedArgs["requestBody"];
1914
+ }
1915
+ const method = definition.method.toUpperCase();
1916
+ // Log request info to stderr (doesn't affect MCP output)
1917
+ console.error(`Executing tool "${toolName}": ${method} ${urlPath}`);
1918
+ // Execute the request
1919
+ const response = await http.request(urlPath, {
1920
+ method: method,
1921
+ headers: headers,
1922
+ ...(typeof requestBodyData !== "undefined" && { body: JSON.stringify(requestBodyData) }),
1923
+ });
1924
+ let responseText = "";
1925
+ const ct = response.headers.get("content-type") ?? "";
1926
+ if (ct.includes("application/json")) {
1927
+ responseText = `API Response (Status: ${response.status}):\n${JSON.stringify(await response.json(), null, 2)}`;
1928
+ }
1929
+ else {
1930
+ responseText = await response.text();
1931
+ if (!responseText) {
1932
+ responseText = `(Status: ${response.status} - No body content)`;
1933
+ }
1934
+ }
1935
+ // Return formatted response
1936
+ return {
1937
+ content: [
1938
+ {
1939
+ type: "text",
1940
+ text: responseText,
1941
+ },
1942
+ ],
1943
+ };
1944
+ }
1945
+ catch (error) {
1946
+ // Handle errors during execution
1947
+ let errorMessage;
1948
+ // Handle standard errors
1949
+ if (error instanceof Error) {
1950
+ errorMessage = error.message;
1951
+ }
1952
+ else {
1953
+ // Handle unexpected error types
1954
+ errorMessage = "Unexpected error: " + String(error);
1955
+ }
1956
+ if (errorMessage.includes("HTTP 401 Unauthorized")) {
1957
+ errorMessage = " Invalid API credentials. Please check your CONFIGCAT_API_USER and CONFIGCAT_API_PASS environment variables. You can create your credentials on the <a target=\"_blank\" href=\"https://app.configcat.com/my-account/public-api-credentials\">Public API credentials management page</a>.";
1958
+ }
1959
+ // Log error to stderr
1960
+ console.error(`Error during execution of tool '${toolName}':`, errorMessage);
1961
+ // Return error message to client
1962
+ return { content: [{ type: "text", text: errorMessage }] };
1963
+ }
1964
+ }
1965
+ //# sourceMappingURL=configcat-api.js.map