@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.
- package/CONTRIBUTING.md +75 -0
- package/DEPLOY.md +19 -0
- package/LICENSE +21 -0
- package/README.md +230 -0
- package/build/http.d.ts +15 -0
- package/build/http.js +51 -0
- package/build/index.d.ts +3 -0
- package/build/index.js +27 -0
- package/build/tools/configcat-api.d.ts +10 -0
- package/build/tools/configcat-api.js +1965 -0
- package/build/tools/configcat-docs.d.ts +4 -0
- package/build/tools/configcat-docs.js +73 -0
- package/package.json +53 -0
|
@@ -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
|