@featureflip/mcp 0.1.8 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -41,8 +41,9 @@ claude mcp add featureflip -e FEATUREFLIP_TOKEN=ffp_your_token -- npx -y @featur
41
41
  ## Tools
42
42
 
43
43
  CRUD: `list_projects`, `list_environments`, `list_flags`, `get_flag`, `create_flag`, `update_flag`,
44
- `delete_flag`, `archive_flag`, `restore_flag`, `set_flag_expiry`, `toggle_flag`, `update_flag_environment_config`,
45
- `get_targeting`, `update_targeting`, `manage_variation`, `list_segments`, `get_segment`
44
+ `delete_flag`, `archive_flag`, `restore_flag`, `set_flag_expiry`, `set_flag_owner`, `toggle_flag`,
45
+ `update_flag_environment_config`, `get_targeting`, `update_targeting`, `manage_variation`, `list_segments`,
46
+ `get_segment`
46
47
 
47
48
  Webhooks (Admin token required): `list_webhooks`, `list_webhook_deliveries`, `manage_webhook`, `deliver_webhook`
48
49
 
package/dist/cli.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { a as e, i as t, n, o as r, s as i, t as a } from "./org-DZ1ge1Mx.js";
1
+ import { a as e, i as t, n, o as r, s as i, t as a } from "./org-8tn1Su68.js";
2
2
  import { serveStdio as o } from "@modelcontextprotocol/server/stdio";
3
3
  //#region src/unconfigured.ts
4
4
  var s = class extends i {
@@ -993,9 +993,11 @@ export interface paths {
993
993
  /**
994
994
  * Sets the flag's advisory expiry date.
995
995
  * @description Evaluation never changes when it passes — the flag is
996
- * reported stale so it can be cleaned up. Requires at least Member. The date must be in the
997
- * future (400 `EXPIRY_IN_PAST`) and the flag-expiration feature must be enabled
998
- * (400 `FEATURE_NOT_ENABLED`).
996
+ * reported stale so it can be cleaned up. Requires at least Member. `expiresAtUtc` takes a
997
+ * date (`2026-12-01`), which means the end of that day in UTC, the same as picking it in the
998
+ * dashboard, or a full ISO-8601 timestamp, which is stored exactly. It must be in the future
999
+ * (400 `EXPIRY_IN_PAST`), so today's date is accepted, and the flag-expiration feature must
1000
+ * be enabled (400 `FEATURE_NOT_ENABLED`).
999
1001
  */
1000
1002
  put: {
1001
1003
  parameters: {
@@ -1369,6 +1371,197 @@ export interface paths {
1369
1371
  patch?: never;
1370
1372
  trace?: never;
1371
1373
  };
1374
+ "/api/v1/orgs/{org}/projects/{project}/flags/{flag}/removal-pr": {
1375
+ parameters: {
1376
+ query?: never;
1377
+ header?: never;
1378
+ path?: never;
1379
+ cookie?: never;
1380
+ };
1381
+ get?: never;
1382
+ /**
1383
+ * Records the pull request that removes this flag from code, so the flag's owner is sent a link to it.
1384
+ * @description Called by the Featureflip Flag Cleanup Action. Requires at least Member. The URL
1385
+ * must be an https pull request URL (400 `validation_failed`).
1386
+ */
1387
+ put: {
1388
+ parameters: {
1389
+ query?: never;
1390
+ header?: never;
1391
+ path: {
1392
+ org: string;
1393
+ project: string;
1394
+ flag: string;
1395
+ };
1396
+ cookie?: never;
1397
+ };
1398
+ requestBody?: {
1399
+ content: {
1400
+ "application/json": components["schemas"]["PublicSetFlagRemovalPrRequest"];
1401
+ "text/json": components["schemas"]["PublicSetFlagRemovalPrRequest"];
1402
+ "application/*+json": components["schemas"]["PublicSetFlagRemovalPrRequest"];
1403
+ };
1404
+ };
1405
+ responses: {
1406
+ /** @description No Content */
1407
+ 204: {
1408
+ headers: {
1409
+ "X-RateLimit-Limit": components["headers"]["X-RateLimit-Limit"];
1410
+ "X-RateLimit-Remaining": components["headers"]["X-RateLimit-Remaining"];
1411
+ "X-RateLimit-Reset": components["headers"]["X-RateLimit-Reset"];
1412
+ [name: string]: unknown;
1413
+ };
1414
+ content?: never;
1415
+ };
1416
+ /** @description Bad Request */
1417
+ 400: {
1418
+ headers: {
1419
+ "X-RateLimit-Limit": components["headers"]["X-RateLimit-Limit"];
1420
+ "X-RateLimit-Remaining": components["headers"]["X-RateLimit-Remaining"];
1421
+ "X-RateLimit-Reset": components["headers"]["X-RateLimit-Reset"];
1422
+ [name: string]: unknown;
1423
+ };
1424
+ content: {
1425
+ "application/json": components["schemas"]["PublicApiErrorEnvelope"];
1426
+ };
1427
+ };
1428
+ /** @description Authentication is required, or the supplied API token is invalid or expired. */
1429
+ 401: {
1430
+ headers: {
1431
+ "X-RateLimit-Limit": components["headers"]["X-RateLimit-Limit"];
1432
+ "X-RateLimit-Remaining": components["headers"]["X-RateLimit-Remaining"];
1433
+ "X-RateLimit-Reset": components["headers"]["X-RateLimit-Reset"];
1434
+ [name: string]: unknown;
1435
+ };
1436
+ content: {
1437
+ "application/json": components["schemas"]["PublicApiErrorEnvelope"];
1438
+ };
1439
+ };
1440
+ /** @description Forbidden */
1441
+ 403: {
1442
+ headers: {
1443
+ "X-RateLimit-Limit": components["headers"]["X-RateLimit-Limit"];
1444
+ "X-RateLimit-Remaining": components["headers"]["X-RateLimit-Remaining"];
1445
+ "X-RateLimit-Reset": components["headers"]["X-RateLimit-Reset"];
1446
+ [name: string]: unknown;
1447
+ };
1448
+ content: {
1449
+ "application/json": components["schemas"]["PublicApiErrorEnvelope"];
1450
+ };
1451
+ };
1452
+ /** @description Not Found */
1453
+ 404: {
1454
+ headers: {
1455
+ "X-RateLimit-Limit": components["headers"]["X-RateLimit-Limit"];
1456
+ "X-RateLimit-Remaining": components["headers"]["X-RateLimit-Remaining"];
1457
+ "X-RateLimit-Reset": components["headers"]["X-RateLimit-Reset"];
1458
+ [name: string]: unknown;
1459
+ };
1460
+ content: {
1461
+ "application/json": components["schemas"]["PublicApiErrorEnvelope"];
1462
+ };
1463
+ };
1464
+ /** @description Rate limit exceeded. Retry after the interval indicated by the Retry-After header. */
1465
+ 429: {
1466
+ headers: {
1467
+ /** @description Number of seconds to wait before retrying the request. */
1468
+ "Retry-After"?: number;
1469
+ "X-RateLimit-Limit": components["headers"]["X-RateLimit-Limit"];
1470
+ "X-RateLimit-Remaining": components["headers"]["X-RateLimit-Remaining"];
1471
+ "X-RateLimit-Reset": components["headers"]["X-RateLimit-Reset"];
1472
+ [name: string]: unknown;
1473
+ };
1474
+ content: {
1475
+ "application/json": components["schemas"]["PublicApiErrorEnvelope"];
1476
+ };
1477
+ };
1478
+ };
1479
+ };
1480
+ post?: never;
1481
+ /**
1482
+ * Forgets the flag's removal pull request.
1483
+ * @description Requires at least Member.
1484
+ */
1485
+ delete: {
1486
+ parameters: {
1487
+ query?: never;
1488
+ header?: never;
1489
+ path: {
1490
+ org: string;
1491
+ project: string;
1492
+ flag: string;
1493
+ };
1494
+ cookie?: never;
1495
+ };
1496
+ requestBody?: never;
1497
+ responses: {
1498
+ /** @description No Content */
1499
+ 204: {
1500
+ headers: {
1501
+ "X-RateLimit-Limit": components["headers"]["X-RateLimit-Limit"];
1502
+ "X-RateLimit-Remaining": components["headers"]["X-RateLimit-Remaining"];
1503
+ "X-RateLimit-Reset": components["headers"]["X-RateLimit-Reset"];
1504
+ [name: string]: unknown;
1505
+ };
1506
+ content?: never;
1507
+ };
1508
+ /** @description Authentication is required, or the supplied API token is invalid or expired. */
1509
+ 401: {
1510
+ headers: {
1511
+ "X-RateLimit-Limit": components["headers"]["X-RateLimit-Limit"];
1512
+ "X-RateLimit-Remaining": components["headers"]["X-RateLimit-Remaining"];
1513
+ "X-RateLimit-Reset": components["headers"]["X-RateLimit-Reset"];
1514
+ [name: string]: unknown;
1515
+ };
1516
+ content: {
1517
+ "application/json": components["schemas"]["PublicApiErrorEnvelope"];
1518
+ };
1519
+ };
1520
+ /** @description Forbidden */
1521
+ 403: {
1522
+ headers: {
1523
+ "X-RateLimit-Limit": components["headers"]["X-RateLimit-Limit"];
1524
+ "X-RateLimit-Remaining": components["headers"]["X-RateLimit-Remaining"];
1525
+ "X-RateLimit-Reset": components["headers"]["X-RateLimit-Reset"];
1526
+ [name: string]: unknown;
1527
+ };
1528
+ content: {
1529
+ "application/json": components["schemas"]["PublicApiErrorEnvelope"];
1530
+ };
1531
+ };
1532
+ /** @description Not Found */
1533
+ 404: {
1534
+ headers: {
1535
+ "X-RateLimit-Limit": components["headers"]["X-RateLimit-Limit"];
1536
+ "X-RateLimit-Remaining": components["headers"]["X-RateLimit-Remaining"];
1537
+ "X-RateLimit-Reset": components["headers"]["X-RateLimit-Reset"];
1538
+ [name: string]: unknown;
1539
+ };
1540
+ content: {
1541
+ "application/json": components["schemas"]["PublicApiErrorEnvelope"];
1542
+ };
1543
+ };
1544
+ /** @description Rate limit exceeded. Retry after the interval indicated by the Retry-After header. */
1545
+ 429: {
1546
+ headers: {
1547
+ /** @description Number of seconds to wait before retrying the request. */
1548
+ "Retry-After"?: number;
1549
+ "X-RateLimit-Limit": components["headers"]["X-RateLimit-Limit"];
1550
+ "X-RateLimit-Remaining": components["headers"]["X-RateLimit-Remaining"];
1551
+ "X-RateLimit-Reset": components["headers"]["X-RateLimit-Reset"];
1552
+ [name: string]: unknown;
1553
+ };
1554
+ content: {
1555
+ "application/json": components["schemas"]["PublicApiErrorEnvelope"];
1556
+ };
1557
+ };
1558
+ };
1559
+ };
1560
+ options?: never;
1561
+ head?: never;
1562
+ patch?: never;
1563
+ trace?: never;
1564
+ };
1372
1565
  "/api/v1/orgs/{org}/projects/{project}/flags/{flag}/archive": {
1373
1566
  parameters: {
1374
1567
  query?: never;
@@ -5414,8 +5607,8 @@ export interface paths {
5414
5607
  /**
5415
5608
  * Queues a finished delivery (succeeded or dead-lettered) to be sent again, restarting its retry schedule.
5416
5609
  * @description Requires Admin. Refused with a 400 when the delivery is still pending, when
5417
- * the subscription is disabled, or when the delivery's event belongs to a project the
5418
- * subscription no longer covers.
5610
+ * the subscription is disabled, or when the subscription's current project, environment or
5611
+ * event-type filters no longer cover the delivery's event.
5419
5612
  */
5420
5613
  post: {
5421
5614
  parameters: {
@@ -5557,10 +5750,10 @@ export interface components {
5557
5750
  name?: string | null;
5558
5751
  slug?: string | null;
5559
5752
  /**
5560
- * @description Allowed values: Solo, Pro, Business, Enterprise.
5753
+ * @description Allowed values: Solo, Team, Pro, Business, Enterprise.
5561
5754
  * @enum {string|null}
5562
5755
  */
5563
- plan?: "Solo" | "Pro" | "Business" | "Enterprise" | null;
5756
+ plan?: "Solo" | "Team" | "Pro" | "Business" | "Enterprise" | null;
5564
5757
  isActive?: boolean;
5565
5758
  /** Format: date-time */
5566
5759
  createdAt?: string;
@@ -5648,9 +5841,13 @@ export interface components {
5648
5841
  * `docsUrl`/`retryAfter`, breaking the published spec. !:JsonPropertyName
5649
5842
  * always wins over the policy, so these are pinned explicitly rather than relying on the
5650
5843
  * property names already being lowercase for the single-word ones.
5651
- * `did_you_mean` and `next_actions` are ADDITIVE optional keys (null → omitted via
5652
- * the global `DefaultIgnoreCondition = WhenWritingNull`), so pre-existing error bodies
5653
- * are byte-for-byte unchanged when they're absent.
5844
+ * `did_you_mean`, `next_actions` and `connection_id` are ADDITIVE optional keys
5845
+ * (null → omitted via the global `DefaultIgnoreCondition = WhenWritingNull`), so
5846
+ * pre-existing error bodies are byte-for-byte unchanged when they're absent.
5847
+ *
5848
+ * `connection_id` is present only on the `sso_required` error: the organization
5849
+ * requires single sign-on, and this credential didn't come through its identity provider.
5850
+ * `connection_id` identifies which SSO connection to sign in with.
5654
5851
  * @example {
5655
5852
  * "error": "not_found",
5656
5853
  * "message": "Flag 'new-checkout-flw' was not found in project 'checkout'.",
@@ -5677,6 +5874,8 @@ export interface components {
5677
5874
  retry_after?: number | null;
5678
5875
  did_you_mean?: string[] | null;
5679
5876
  next_actions?: components["schemas"]["NextAction"][] | null;
5877
+ /** Format: uuid */
5878
+ connection_id?: string | null;
5680
5879
  };
5681
5880
  /** @description Request-side condition group, symmetric with PublicConditionGroupResponse. */
5682
5881
  PublicConditionGroupRequest: {
@@ -5756,7 +5955,8 @@ export interface components {
5756
5955
  * is passed through verbatim to Type, which itself takes a
5757
5956
  * bare string (Boolean/String/Number/Json) rather than the domain enum — invalid values surface
5758
5957
  * as the handler's own validation failure, not a controller-level 400. ExpiresAtUtc is
5759
- * optional and advisory; it must be in the future and requires the flag-expiration feature
5958
+ * optional and advisory; a bare date (`2026-12-01`) means the end of that day in UTC, and a full
5959
+ * timestamp is stored exactly. It must be in the future and requires the flag-expiration feature
5760
5960
  * (400 `EXPIRY_IN_PAST` / `FEATURE_NOT_ENABLED`). OwnerEmail optionally names
5761
5961
  * the owner (an active member, matched case-insensitively; requires the flag-ownership feature —
5762
5962
  * 400 `OWNER_NOT_MEMBER` / `FEATURE_NOT_ENABLED`). Omitted, the owner is the caller when
@@ -6111,6 +6311,7 @@ export interface components {
6111
6311
  /** Format: date-time */
6112
6312
  expiresAtUtc?: string | null;
6113
6313
  owner?: components["schemas"]["PublicFlagOwner"];
6314
+ removalPrUrl?: string | null;
6114
6315
  };
6115
6316
  /**
6116
6317
  * @description A page of results plus an opaque cursor for the next page, or null when this is the last
@@ -6234,6 +6435,7 @@ export interface components {
6234
6435
  /** Format: date-time */
6235
6436
  expiresAtUtc?: string | null;
6236
6437
  owner?: components["schemas"]["PublicFlagOwner"];
6438
+ removalPrUrl?: string | null;
6237
6439
  /** @description Capability hints: which operations the authenticated caller may perform on this resource, each with allowed + optional reason. Computed from the caller's role and the resource's state. Injected at runtime; safe to ignore. Present only on top-level resource responses — nested occurrences (e.g. a rule inside a targeting-config response) do not carry it. */
6238
6440
  _actions?: {
6239
6441
  [key: string]: components["schemas"]["ActionCapability"];
@@ -6406,7 +6608,8 @@ export interface components {
6406
6608
  * @description Request body for `PUT /api/v1/orgs/{org}/projects/{project}/flags/{flag}/expiry`. Expiry is a
6407
6609
  * dedicated sub-resource, deliberately NOT a field on PublicUpdateFeatureFlagRequest: that
6408
6610
  * PUT is a full replace, so a new nullable field there would let any client that doesn't know about
6409
- * expiry (the Terraform provider included) wipe it on every update.
6611
+ * expiry (the Terraform provider included) wipe it on every update. A bare date means the end of that
6612
+ * UTC day; a full timestamp is stored exactly.
6410
6613
  */
6411
6614
  PublicSetFlagExpiryRequest: {
6412
6615
  /** Format: date-time */
@@ -6421,6 +6624,15 @@ export interface components {
6421
6624
  PublicSetFlagOwnerRequest: {
6422
6625
  email?: string | null;
6423
6626
  };
6627
+ /**
6628
+ * @description Request body for `PUT /api/v1/orgs/{org}/projects/{project}/flags/{flag}/removal-pr`: the
6629
+ * pull request that removes this flag from code, as opened by the Featureflip Flag Cleanup Action.
6630
+ * A dedicated sub-resource for the same reason as expiry and owner. `url` must be an https
6631
+ * pull request URL (`https://{host}/{owner}/{repo}/pull/{number}`).
6632
+ */
6633
+ PublicSetFlagRemovalPrRequest: {
6634
+ url?: string | null;
6635
+ };
6424
6636
  /**
6425
6637
  * @description The full targeting configuration for a flag in a single environment, returned by
6426
6638
  * `GET .../targeting`. Maps 1:1 onto TargetingConfigurationDto — including
@@ -6696,6 +6908,10 @@ export interface components {
6696
6908
  /**
6697
6909
  * @description A webhook subscription. Never carries secret material: signing secrets are listed by id and
6698
6910
  * lifecycle only — the value itself is returned once, when it is created or rotated.
6911
+ * `overPlanLimit` is true when the organization has more subscriptions than its plan
6912
+ * allows, which happens after a downgrade. The oldest subscriptions up to the limit keep
6913
+ * delivering. The rest receive nothing and cannot be re-enabled, tested or redelivered to until
6914
+ * the plan is upgraded or older subscriptions are deleted.
6699
6915
  * @example {
6700
6916
  * "id": "0197b6a4-6f7a-7b8c-9d0e-1f2a3b4c5d6e",
6701
6917
  * "name": "Checkout flag changes to Slack relay",
@@ -6746,6 +6962,7 @@ export interface components {
6746
6962
  /** Format: date-time */
6747
6963
  updatedAt?: string;
6748
6964
  secrets?: components["schemas"]["PublicWebhookSecretResponse"][] | null;
6965
+ overPlanLimit?: boolean;
6749
6966
  /** @description Capability hints: which operations the authenticated caller may perform on this resource, each with allowed + optional reason. Computed from the caller's role and the resource's state. Injected at runtime; safe to ignore. Present only on top-level resource responses — nested occurrences (e.g. a rule inside a targeting-config response) do not carry it. */
6750
6967
  _actions?: {
6751
6968
  [key: string]: components["schemas"]["ActionCapability"];