Skip to content

Releases: canopy-labs/featureflip-mcp

v0.7.0

Choose a tag to compare

@jhoward321 jhoward321 released this 05 Nov 03:35

Added

  • Critical environments. manage_environment takes require_change_reason and require_confirmation on create and update (omit either on update to leave it unchanged), and list_environments returns both. An environment with require_change_reason needs a reason on every write to it. The write tools take an optional reason, sent as X-Intent-Reason and recorded in the audit log: manage_environment, toggle_flag, update_flag_environment_config, update_targeting, manage_targeting_rule, manage_segment, manage_variation, delete_flag, archive_flag and restore_flag. A write the API refuses with change_reason_required now tells the agent to retry with reason. Needs the API's critical environments (#4639). (#4994)
  • update_flag and manage_sdk_key take reason too. The API requires one when a clientSideVisible change touches a project with a critical environment, and when revoking a critical environment's SDK key (#4999, #5000). (#5028)
  • manage_webhook takes provider: "Datadog" (Events API change events) or provider: "Grafana" (annotations) on create. Both need a write-only credential, a Datadog API key or a Grafana service account token, which is stored encrypted and never returned. On update, omit credential to keep the stored one; changing the url of a Datadog or Grafana subscription needs it again. rotate_secret is refused on these subscriptions, which authenticate with the credential instead. Needs the API's Datadog and Grafana destinations (#4650). (#4979)

Changed

  • Turning a critical setting off through manage_environment needs an Admin or Owner token as well as a reason (#4998). (#5028)

v0.6.0

Choose a tag to compare

@jhoward321 jhoward321 released this 03 Nov 04:22

Added

  • manage_webhook takes an optional provider on create: GenericHttp (the default) or Slack, so an agent can send flag changes to a Slack channel. Needs the API's Slack destination (#4649). (#4664)

Changed

  • manage_webhook refuses a Slack incoming webhook URL (https://hooks.slack.com/services/...) on a GenericHttp subscription, at create or update. Slack rejects the generic JSON payload, so that subscription would fail every delivery until auto-disable paused it. It also refuses provider on any action except create, because a subscription's provider can't change, and refuses rotate_secret on a Slack subscription, whose signing secret is never used. (#4664)

v0.5.0

Choose a tag to compare

@jhoward321 jhoward321 released this 30 Oct 11:59

Added

  • manage_targeting_rule and update_targeting take an optional bucketBy on a rule: the context attribute its percentage rollout hashes on, such as anonymous_id or accountId. It defaults to user_id. A visitor whose context lacks the attribute skips the rule, even at 100%. A manage_targeting_rule update that leaves it out keeps the rule's current value, except that a fixed rule has none: one made a rollout that way gets user_id (#4607). flag_evaluations now returns rollout.bucketBy, and rollout.unreached when a live rollout rule got no evaluations while 100 or more reached the flag's rules. (#4224)

v0.4.0

Choose a tag to compare

@jhoward321 jhoward321 released this 27 Oct 12:34

Added

  • flag_evaluations reports what a flag served in one environment over the last 7, 30 or 90 days. It returns the total evaluations, the split by variation, and which rule (or the fallthrough, off, a prerequisite or an error) served what. A percentage-rollout rule also returns its configured weights and a sample-ratio check, and rollout.flagged is true when the served split is statistically off them. These are evaluation counts, not unique users. Zero means no SDK reported an evaluation, not necessarily that there was no traffic. Needs the API's new GET .../flags/{flag}/environments/{env}/evaluations. (#4225)

v0.3.0

Choose a tag to compare

@jhoward321 jhoward321 released this 15 Oct 23:25

Added

  • update_flag, update_targeting and a manage_segment update now return the etag of what they wrote, taken from the write's own response. An agent can pass it as ifMatch on its next write without reading the resource again. Before this, a second conditional write needed a fresh read first, or it failed with a 412. The ETag is never fetched with a follow-up read, which could pick up someone else's later write. When the API sends no ETag, the field is left out. (#3842)

Fixed

  • A manage_targeting_rule update that leaves out conditionGroups no longer fails with a TypeError when one of the rule's current groups has conditions: null. The API contract allows null there. The group is now carried over with an empty list. (#3842)

v0.2.0

Choose a tag to compare

@jhoward321 jhoward321 released this 14 Oct 23:18

Added

  • set_default_flag_lifetime sets or removes a project's default flag lifetime. preview: true reports how many flags would newly be, or stop being, past expiry, without changing anything. (#3794)
  • list_sdk_keys and manage_sdk_key (create, rename, revoke). Creating a key returns the full key once, so an agent setting up an SDK can write it into an .env file. The list shows only the last four characters.
  • manage_segment (create, update, delete). update_targeting could already reference a segment that nothing in the MCP server could create. A segment created without conditions is sent with an empty list, which the API requires.
  • manage_project and manage_environment (create, update). Neither can delete.
  • manage_targeting_rule adds, updates, removes or reorders one rule without replacing the whole list. A rule added here or through update_targeting without conditionGroups (segment-only or rollout-only) is sent with an empty list, which the API requires.
  • Optimistic concurrency. get_flag, get_targeting and get_segment return an etag, and update_flag, update_targeting and a manage_segment update take it back as ifMatch. manage_segment refuses ifMatch on create and delete, which the API can't make conditional, instead of dropping it and writing unconditionally. (#3808) The write then fails with a 412 if the resource changed after the agent read it, instead of overwriting the other change. Tools that read before writing (update_flag, manage_webhook, manage_segment, manage_environment, manage_targeting_rule) also send the ETag from their own read.

Changed

  • A write carrying If-Match is no longer retried after a 502 or 504. If the first attempt landed, the retry would fail with a 412 and blame someone else for the agent's own change. A 503 is still retried.
  • An ifMatch passed without its surrounding quotes (abc instead of "abc") is quoted before it is sent. Otherwise every conditional write would fail with a 412 that looks like a concurrent change.

v0.1.13

Choose a tag to compare

@jhoward321 jhoward321 released this 13 Oct 03:00

Added

  • Every tool declares an outputSchema and returns structuredContent alongside the JSON text. Clients can type-check a result instead of parsing prose. Tools that pass an API response through take their schema from the public API spec, so it matches the API contract. The schema allows extra fields and nulls, so a field the API adds later can't make an older server version fail a call.
  • find_stale_flags counts a project's default flag lifetime. Each result now carries effectiveExpiresAtUtc, the date in effect from the flag or its project's default, and expirySource (explicit, project-default, or null). A flag with no date of its own can still be reported as past expiry. Against an API that doesn't report project defaults yet, effectiveExpiresAtUtc falls back to the flag's own date. (#3194)

Changed

  • Every tool parameter now has a description. 54 of 113 had only a name and a type, mostly project, flag, environment, limit and cursor, along with fields like create_flag's type and update_targeting's rules. Agents now see what each parameter expects.

v0.1.12

Choose a tag to compare

@jhoward321 jhoward321 released this 12 Oct 11:48

Added

  • Each release now carries featureflip-mcp-<version>.mcpb, an MCP Bundle with the server and its dependencies inside. Claude Desktop installs it in one click and asks for the API token in its own settings, so there is no JSON config to write. Needs Node.js 20.19 or later. (#2588)

v0.1.11

Choose a tag to compare

@jhoward321 jhoward321 released this 11 Oct 13:09

Added

  • set_flag_permanent marks a flag permanent, for a kill switch or ops toggle that is meant to stay, or makes it temporary again with permanent: false. create_flag takes an optional isPermanent as well. Permanent flags are left out of find_stale_flags and list_removal_candidates. Marking is refused with PERMANENT_FLAG_HAS_EXPIRY while the flag has an expiry date, so clear the date first; making a flag temporary always works. (#3193, #3671)

Changed

  • set_flag_expiry documents its PERMANENT_FLAG_HAS_EXPIRY refusal on a permanent flag.
  • @modelcontextprotocol/server 2.1.0 → 2.3.1.

v0.1.10

Choose a tag to compare

@jhoward321 jhoward321 released this 03 Oct 13:34

Added

  • list_removal_candidates lists the flags the server is confident can be removed from code, the same list the flag cleanup GitHub Action works from. Each item has key, reason, status, treatment (which branch to keep) and blockedBy. staleness is dead (the default) or stale. (#3458)
  • find_stale_flags reports blockedBy for each flag: the live flags that still list it as a prerequisite and have to be removed and archived first. It is [] when nothing depends on the flag, and null when the server didn't classify the flag as a removal candidate, which means unknown rather than unblocked. If the lookup fails, the stale report still comes back, with every blockedBy set to null and a blockedByNote saying why. Against an API that predates blockedBy, every value is null. (#3458)

Changed

  • find_stale_flags, list_removal_candidates and archive_flag tell the agent to remove dependents first. archive_flag refuses a flag that another live flag still lists as a prerequisite (FLAG_HAS_DEPENDENTS), and the agent now hears that before trying.