# LaunchDarkly MCP
> LaunchDarkly-hosted MCP for feature management, AgentControl configuration, observability, and metrics workflows.
Canonical: https://www.mcpfolio.com/servers/launchdarkly-official-mcp
Last updated: 2026-10-28
## Catalog record

- Publisher: LaunchDarkly (official)
- Categories: productivity

## Website

https://launchdarkly.com/docs/fed-docs/home/getting-started/mcp

## Transports

Streamable HTTP

## Authentication

OAuth authorization and LaunchDarkly account permissions.

## Tools

- **unrestrict-agentcontrol-model-configs**: Remove AI model configs from the restricted list so that variations can select them again. keys are model config keys (for example ["OpenAI.gpt-4o"]), not ids. To see restricted keys, call list-agentcontrol-model-configs with restricted=true.
- **restrict-agentcontrol-model-configs**: Restrict AI model configs so that variations cannot select them. keys are model config keys from list-agentcontrol-model-configs (for example ["OpenAI.gpt-4o"]), not ids. Returns the restricted keys and per-key errors. For 'key is already in use', move the variations to another model with update-agentcontrol-config-variation, then retry. For 'unknown model config key', check list-agentcontrol-model-configs. Undo with unrestrict-agentcontrol-model-configs.
- **delete-agentcontrol-model-config**: Permanently delete a custom AI model config. Requires confirm=true. modelConfigKey is the key, not the id. Global models cannot be deleted: call restrict-agentcontrol-model-configs instead. If the API returns 'model config is still in use', move those variations to another modelConfigKey with update-agentcontrol-config-variation, then retry.
- **update-agentcontrol-model-config**: Update a custom AI model config. modelConfigKey is the key from list-agentcontrol-model-configs (for example OpenAI.gpt-image-2), not the id. Send at least one field. Only sent fields change, and params, customParams, and tags replace the current values. Formats match create-agentcontrol-model-config. provider and id cannot change: call create-agentcontrol-model-config with a new key instead. Global models (global=true) cannot be updated.
- **create-agentcontrol-model-config**: Create a custom AI model config for a model that is not in the global catalog. Call list-agentcontrol-model-configs first, and use a global model if one exists. Required: key, name, id. key uses letters, numbers, ., _, and - (for example gpt-image-2-20260916-uzw1la), not a global key. id is the provider's model ID (for example gpt-image-2). provider matches the key's prefix, if any (for example OpenAI). Costs are USD per token (for example 0.000005). params and customParams are freeform JSON objects (for example {"temperature": 0.7}). Set maintainerId or maintainerTeamKey, not both. Next, pass key as modelConfigKey and id as modelName to create-agentcontrol-config-variation.
- **get-agentcontrol-model-config**: Get one AI model config. modelConfigKey is the key from list-agentcontrol-model-configs (for example OpenAI.gpt-4o), not the id. Optional version is an integer from an earlier read (for example 2). Omit it for the latest. Global models accept only version 0 or 1. On a 403, omit version.
- **list-agentcontrol-model-configs**: List the AI model configs in a project: global catalog models (global=true) and custom models (global=false). Pass an item's key (for example OpenAI.gpt-4o) as modelConfigKey and its id (for example gpt-4o) as modelName to create-agentcontrol-config-variation. Optional restricted: true returns only restricted models, false returns only unrestricted models. Omit it for all. Costs are USD per token.
- **delete-factory-repo-settings**: Deprecated: use delete-release-autopilot-repo-settings instead. Unmap a GitHub repository from Release Autopilot settings (removes project mapping and overrides). Idempotent: an already-unmapped repo still returns success. Pass repo as owner/name or githubRepoId. Requires permission to update Release Autopilot repo settings on the mapped project.
- **update-factory-repo-settings**: Deprecated: use update-release-autopilot-repo-settings instead. Map a GitHub repository to a LaunchDarkly project and optionally override auto-flagging or auto-releasing. Pass repo as owner/name (preferred) or githubRepoId. projectKey is required on the first map. An omitted automation inherits the account setting. A repo cannot enable a capability the account has off. Requires permission to update Release Autopilot repo settings on the mapped project. Do not send autoCleanup.
- **get-factory-repo-settings**: Deprecated: use get-release-autopilot-repo-settings instead. Get Release Autopilot settings for one GitHub repository (effective auto-flagging / auto-releasing). Pass repo as owner/name, or githubRepoId. 404 means the repo is not mapped yet.
- **list-factory-github-repos**: Deprecated: use list-release-autopilot-github-repos instead. List GitHub repositories on this account's LaunchDarkly GitHub App install, with display name (usually owner/name) and numeric githubRepoId. Use this before mapping a repo. This is not the list of already-mapped repos (that is list-release-autopilot-repo-settings). Optional projectKey: any project works; the install is account-wide (same as the settings UI). When githubConnectUrl is present, give that link to the user and retry after they finish. Requires Observability GraphQL (O11Y_GRAPHQL_ENDPOINT) like other Vega GitHub tools.
- **list-factory-repo-settings**: Deprecated: use list-release-autopilot-repo-settings instead. List Release Autopilot settings for GitHub repositories already mapped to a LaunchDarkly project. Unmapped install repos are omitted — use list-release-autopilot-github-repos for those. Each automation is the effective value (account &#43; repo override). githubRepoId is numeric.
- **update-factory-settings**: Deprecated: use update-release-autopilot-settings instead. Update account-wide Release Autopilot settings (auto-flagging and auto-releasing). Send only what changed. approvalRequired is only valid on auto-flagging. Requires permission to update account Release Autopilot settings. Do not send autoCleanup. Requires LD-API-Version beta (sent automatically).
- **get-factory-settings**: Deprecated: use get-release-autopilot-settings instead. Get account-wide Release Autopilot settings: whether auto-flagging and auto-releasing are on, and whether auto-flagging pull requests need approval. These are the master gate — a mapped repository cannot enable a capability the account has off. Requires LD-API-Version beta (sent automatically). Do not use autoCleanup; it is not part of Release Autopilot settings yet.
- **list-agent-skill-references**: List the AgentControl Config variations that attach an agent skill, with the skill version each one is pinned to. Use before updating or deleting a skill.
- **list-agent-skill-versions**: List the versions of an agent skill, newest first. Returns each version's number, name, description, tags, and creation time.
- **delete-agent-skill**: Permanently delete an agent skill and all of its versions. THIS IS IRREVERSIBLE. LaunchDarkly rejects the delete while any variation still attaches the skill; use list-agent-skill-references to find and detach them first. Requires confirm=true to execute.
- **update-agent-skill**: Update an agent skill's markdown, name, description, tags, or maintainer. Only provided fields are updated. Variations stay pinned to the version they attached; use list-agent-skill-references to find them and update-agentcontrol-config-variation to move them to the new version.
- **create-agent-skill**: Create an agent skill from SKILL.md content. Provide a unique key, a display name, and the verbatim markdown. The skill starts at version 1. Attach it to a variation with create-agentcontrol-config-variation or update-agentcontrol-config-variation by passing skills: [{key, version}].
- **get-agent-skill**: Get the latest version of an agent skill by key, including its full SKILL.md markdown, name, description, tags, and version number.
- **list-agent-skills**: List agent skills in a project. Agent skills are versioned SKILL.md documents that AgentControl Config variations attach by {key, version}. Returns key, name, description, latest version, and tags; use get-agent-skill to read a skill's markdown. Use query to search by key, name, or description.
- **delete-release-autopilot-repo-settings**: Unmap a GitHub repository from Release Autopilot settings (removes project mapping and overrides). Idempotent: an already-unmapped repo still returns success. Pass repo as owner/name or githubRepoId. Requires permission to update Release Autopilot repo settings on the mapped project.
- **update-release-autopilot-repo-settings**: Map a GitHub repository to a LaunchDarkly project and optionally override auto-flagging or auto-releasing. Pass repo as owner/name (preferred) or githubRepoId. projectKey is required on the first map. An omitted automation inherits the account setting. A repo cannot enable a capability the account has off. Requires permission to update Release Autopilot repo settings on the mapped project. Do not send autoCleanup.
- **get-release-autopilot-repo-settings**: Get Release Autopilot settings for one GitHub repository (effective auto-flagging / auto-releasing). Pass repo as owner/name, or githubRepoId. 404 means the repo is not mapped yet.
- **list-release-autopilot-github-repos**: List GitHub repositories on this account's LaunchDarkly GitHub App install, with display name (usually owner/name) and numeric githubRepoId. Use this before mapping a repo. This is not the list of already-mapped repos (that is list-release-autopilot-repo-settings). Optional projectKey: any project works; the install is account-wide (same as the settings UI). When githubConnectUrl is present, give that link to the user and retry after they finish. Requires Observability GraphQL (O11Y_GRAPHQL_ENDPOINT) like other Vega GitHub tools.
- **list-release-autopilot-repo-settings**: List Release Autopilot settings for GitHub repositories already mapped to a LaunchDarkly project. Unmapped install repos are omitted — use list-release-autopilot-github-repos for those. Each automation is the effective value (account &#43; repo override). githubRepoId is numeric.
- **update-release-autopilot-settings**: Update account-wide Release Autopilot settings (auto-flagging and auto-releasing). Send only what changed. approvalRequired is only valid on auto-flagging. Requires permission to update account Release Autopilot settings. Do not send autoCleanup. Requires LD-API-Version beta (sent automatically).
- **get-release-autopilot-settings**: Get account-wide Release Autopilot settings: whether auto-flagging and auto-releasing are on, and whether auto-flagging pull requests need approval. These are the master gate — a mapped repository cannot enable a capability the account has off. Requires LD-API-Version beta (sent automatically). Do not use autoCleanup; it is not part of Release Autopilot settings yet.
- **get-resource-views**: List the views a flag, segment, or AgentControl Config is linked to. Views are an Enterprise feature. Flags and AgentControl Configs are identified by key; segments additionally require `environmentId` because segments are environment-scoped.
- **list-view-resources**: List the resources of one type linked to a view. Views are an Enterprise feature. Returns resource keys with link timestamps (and environment info for segments). Use query for a case-insensitive search on resource keys.

Sorting: use `sort` with `linkedAt` (default) or `name`.

Pagination: responses include `totalCount` and `pageInfo.offset`. To get the next page, set `offset` to the current offset &#43; limit.
- **link-view-resources**: Link flags, segments, or AgentControl Configs to a view. Views are an Enterprise feature.

IDENTIFYING RESOURCES:
- flags / aiConfigs: pass `keys`
- segments: pass `segmentIdentifiers` ({environmentId, segmentKey} pairs — segments are environment-scoped)
- any type: pass `filter` to link everything matching a list-endpoint filter expression (flags use comma-separated field:value filters, segments use queryfilter syntax; `environmentId` is required with a segments filter). Keys and filter combine as a union.

Large key lists are batched automatically at 20 keys per API request. The response aggregates successCount/failureCount across batches and lists any resources that failed to link.
- **update-view**: Update a view's name, description, maintainer, or tags. Views are an Enterprise feature. Include only the fields to change — provided values replace the existing ones (tags are replaced wholesale, not merged). Only one of maintainerId or maintainerTeamKey can be specified. The view key cannot be changed.
- **create-view**: Create a new view in a project. Views are an Enterprise feature. The view is empty after creation — use link-view-resources to link flags, segments, or AgentControl Configs to it, or pass viewKeys when creating those resources. The key is converted to lowercase by the API, so use the lowercase form to reference the view afterward.

MAINTAINER: set maintainerTeamKey or maintainerId to assign an owner; only one of the two can be specified. Prefer maintainerTeamKey when a suitable team exists.
- **get-view**: Get a single view by key. Views are an Enterprise feature. Returns name, description, tags, maintainer, and linked-resource counts (flags, segments, AgentControl Configs). Use list-view-resources to enumerate the linked resources themselves.
- **list-views**: List views in a project. Views are an Enterprise feature. Returns a paginated list with key, name, description, tags, maintainer, and (when includeResourceSummary is set) linked-resource counts. Use query to search by name, tags to filter by tag.

Sorting: use `sort` with `key`, `name`, or `updatedAt` (default `updatedAt`, most recent first).

Pagination: responses include `totalCount` and `pageInfo.offset`. To get the next page, set `offset` to the current offset &#43; limit.
- **get-flag-unique-context-exposures**: Get unique-context exposure counts (distinct-context cardinality) for a flag in an environment. Returns how many distinct users/accounts/etc. were actually exposed to the flag over a time window, broken down by context kind.

CRITICAL DISTINCTION: unique exposures are NOT evaluation counts. One context evaluated 10,000 times counts as 1 exposure (not 10,000). This ~1000x difference is critical for guarded rollout sizing. The guarded-release UI gates on this figure. For total SDK call counts use get-flag-evaluation-summaries.

from/to accept ISO 8601 strings or Unix millisecond timestamp strings (default: last 30 days).
- **get-session-timestamp-event-chunk-url**: Get a signed download URL for the rrweb event chunk covering a specific timestamp within a session.
Picks the chunk whose start is at or before the timestamp — useful to jump straight to the moment an error or interaction happened without listing all chunks first.
The URL is valid for ~15 minutes and points to Brotli-compressed rrweb events JSON.

REQUIRED INPUTS:
- projectKey: The LaunchDarkly project key (e.g., "default").
- sessionSecureId: The secure ID of the session. REQUIRED.
- timestamp: Timestamp of interest in ISO format (e.g., "2024-01-15T10:00:00Z"). REQUIRED.

Here's an example of a valid input:
{"projectKey": "default", "sessionSecureId": "abc123def456", "timestamp": "2024-01-15T10:00:00Z"}
- **get-session-event-chunk-url**: Get a signed download URL for one rrweb event chunk of a session.
The URL is valid for ~15 minutes and points to Brotli-compressed JSON — an array of raw rrweb events (DOM snapshots, mutations, interactions). Decompress with Brotli before parsing.

REQUIRED INPUTS:
- projectKey: The LaunchDarkly project key (e.g., "default").
- sessionSecureId: The secure ID of the session. REQUIRED.
- index: The chunk_index of the chunk to download (from get-session-event-chunks). REQUIRED.

Chunk payloads can be large; prefer query-timeline-events for a cheap chronological overview and only fetch raw chunks when you need actual DOM/interaction detail.

Here's an example of a valid input:
{"projectKey": "default", "sessionSecureId": "abc123def456", "index": 0}
- **get-session-event-chunks**: List the rrweb event chunks recorded for a session.
Session replay events are stored in chunks; this returns one entry per chunk with chunk_index and the chunk's start timestamp (epoch millis).
Use it to see how a session's recording is segmented, then fetch a specific chunk's raw contents with get-session-event-chunk-url.

REQUIRED INPUTS:
- projectKey: The LaunchDarkly project key (e.g., "default").
- sessionSecureId: The secure ID of the session to list event chunks for. REQUIRED.

The session's chunked field (from query-sessions) tells you whether chunks exist — unchunked (very short or old) sessions return an empty list.
For a cheap chronological overview of a session prefer query-timeline-events; only fetch raw chunks when you need actual DOM/interaction detail.

Here's an example of a valid input:
{"projectKey": "default", "sessionSecureId": "abc123def456"}
- **check-flag-rollout-complete**: Check whether a feature flag is fully rolled out to a single deterministic variation across all traffic-bearing environments. This detects the important stale case that inactive detection misses: a flag at 100% rollout is still evaluated on every request (never looks inactive), but its code branch is dead and it is prime for removal.

ALGORITHM: For each environment, checks if serving is deterministic (targeting off → offVariation, or targeting on with no rules/targets/prerequisites/rollout → simple fallthrough variation). Traffic-bearing environments are those with a recent lastRequested timestamp. A flag is fully rolled out when all traffic-bearing envs converge on the same variation AND a stability gate is met (at least one env is 'launched' or the flag is older than stabilityDays).

Returns isFullyRolledOut, consensusVariation (value &#43; name when fully rolled out), per-environment results, and blockers explaining any failure to be fully rolled out.
- **get-values**: Discover the observed values for ONE attribute key, ranked by frequency.

The companion to get-keys: that tells you a key exists, this tells you what to compare it against. Use it whenever a key=value filter returns 0 rows but you believe the key is right; the value vocabulary is usually the problem.

Two things this is especially good for:
- Service names. service_name values often carry environment prefixes (production-, staging-) but not uniformly. Don't guess the prefix; enumerate.
- Confirming a guess is wrong. If a search for a service found nothing, {"key": "service_name", "search": "checkout"} shows what actually exists instead of widening the time range pointlessly.

A long value list means the key is high-cardinality (e.g. trace_id) and is not useful to filter or group on; pick a coarser key.

INPUTS:
- projectKey (required): The LaunchDarkly project key (e.g., "default").
- productType (required): One of "logs", "traces", "sessions", "errors", "metrics", "paevents", "events". Use "paevents" for product-analytics events; "events" is the legacy session_events source.
- key (required): The attribute key whose values to list (e.g., "service_name")
- startDate (required): ISO format start date (e.g., "2024-01-15T10:00:00Z")
- endDate (optional): ISO format end date (defaults to current time)
- search (optional): Substring filter over values. Substring, not fuzzy; search a short stem
- limit (optional, default 30, max 100): Maximum number of values to return

RETURNS:
- values: Array of { value, count }, most frequent first
- product_type, key, value_count
- _hint: Present when no values were found

Example:
{"projectKey": "default", "productType": "traces", "key": "service_name", "startDate": "2024-01-15T10:00:00Z"}
- **query-service-map**: Query the service dependency map (service map) for a project.
Returns the directed call graph between services, derived from trace data over the given time window.

REQUIRED INPUTS:
- projectKey: The LaunchDarkly project key (e.g., "default").
- startDate: Start date in ISO format (e.g., "2024-01-15T10:00:00Z"). REQUIRED.

OPTIONAL INPUTS:
- endDate: End date in ISO format (e.g., "2024-01-15T11:00:00Z"). If not provided, uses current time.

DATE FORMAT:
- Use ISO format: "2024-01-15T10:00:00Z" or "2024-01-15T10:00:00-08:00"
- Dates should be reasonable and within your data retention period
- Always specify timezone if not using Z (UTC)

RETURNS:
- services: Sorted list of every service name (graph nodes), including standalone services with no observed dependencies.
- dependencies: Directed edges as { source, target } pairs, where `source` calls `target`.
- service_count / dependency_count: Convenience counts.

Examples:
1. Specific time window: {"projectKey": "default", "startDate": "2024-01-15T10:00:00Z", "endDate": "2024-01-15T11:00:00Z"}
2. From specific time to now: {"projectKey": "default", "startDate": "2024-01-15T10:00:00Z"}
- **delete-alert**: Permanently delete an observability alert. THIS IS IRREVERSIBLE. Requires confirm=true to execute. Use get-alert first to verify you are deleting the right alert.

INPUTS:
- projectKey (required): The LaunchDarkly project key (e.g., "default").
- alertId (required): The numeric ID of the alert to delete
- confirm (required): Must be true to execute the deletion

RETURNS:
- deleted: Boolean indicating success
- alert_id: ID of the deleted alert
- **toggle-alert**: Enable or disable an observability alert without changing its configuration.

Use this to silence a noisy alert during an incident or maintenance window, and to turn it back on afterwards. The alert's query, threshold, and destinations are untouched.

INPUTS:
- projectKey (required): The LaunchDarkly project key (e.g., "default").
- alertId (required): The numeric ID of the alert (from list-alerts)
- enabled (required): true to enable the alert, false to disable it

RETURNS:
- alert_id: ID of the alert
- enabled: The new state

Example - silence alert 42:
{"projectKey": "default", "alertId": 42, "enabled": false}
- **update-alert**: Update an existing observability alert. Only the fields you provide are changed; everything else is preserved.

Common uses: adjust the threshold after tuning, refine the filter query, rename the alert, or change notification destinations.
To enable/disable an alert, use toggle-alert instead.

INPUTS:
- projectKey (required): The LaunchDarkly project key (e.g., "default").
- alertId (required): The numeric ID of the alert to update (from list-alerts)
- name (optional): New name for the alert
- productType (optional): Data source - one of Logs, Traces, Errors, Sessions, Metrics, Events
- functionType (optional): Aggregator - one of Count, CountDistinct, CountDistinctKey, Min, Avg, P50, P75, P90, P95, P99, Max, Sum
- functionColumn (optional): Field to aggregate ("" to clear)
- query (optional): Filter query string ("" to clear)
- groupBy (optional): Array of dimension keys to alert per-group ([] to clear)
- thresholdValue (optional): New threshold to compare against
- thresholdWindow (optional): Evaluation window in seconds
- thresholdCooldown (optional): Seconds between re-notifications while alerting
- evaluationDelaySeconds (optional): Seconds to wait before evaluating each window
- thresholdType (optional): "Constant" or "Anomaly"
- thresholdCondition (optional): "Above", "Below", or "Outside"
- messageContent (optional): Custom notification message ("" to clear)
- destinations (optional): REPLACES the full destination list when provided. Each entry:
  - destinationType: One of Slack, Discord, MicrosoftTeams, Webhook, Email
  - typeId: Destination identifier (Slack channel ID, email address, webhook URL)
  - typeName: Human-readable name
- autoInvestigationEnabled (optional): when true, each firing starts an automatic AI investigation and posts the diagnosis to the alert's destinations
- investigationCooldownSeconds (optional, default 86400): minimum gap between automatic investigations. Keep at or above thresholdCooldown so a chatty alert doesn't re-investigate the same condition
- investigationPermissionMode (optional, default "read"): "read" investigates and reports; "read-write" additionally lets the investigation open a PR
- investigationRepositories (optional): repos the investigation may read. Without these it cannot correlate a firing against a recent deploy
- investigationPrompt (optional): extra standing instructions prepended to each investigation

RETURNS:
- alert_updated: Boolean indicating success
- alert_id, alert_url, and the updated configuration

Example - raise the threshold on alert 42 to 250:
{"projectKey": "default", "alertId": 42, "thresholdValue": 250}

Example - enable automatic AI investigation on alert 42:
{"projectKey": "default", "alertId": 42, "autoInvestigationEnabled": true, "investigationPermissionMode": "read", "investigationRepositories": ["my-org/my-service"]}
- **create-alert**: Create a new observability alert that fires when a metric crosses a threshold.

IMPORTANT: Before creating a new alert:
1. Use list-alerts to check if a similar alert already exists
2. Use get-keys to discover available data dimensions for the product type
3. Use query-aggregations to verify data exists and pick a sensible threshold

INPUTS:
- projectKey (required): The LaunchDarkly project key (e.g., "default").
- name (required): Name for the alert (e.g., "High API Error Rate")
- productType (required): Data source - one of Logs, Traces, Errors, Sessions, Metrics, Events
- functionType (required): Aggregator to monitor - one of Count, CountDistinct, CountDistinctKey, Min, Avg, P50, P75, P90, P95, P99, Max, Sum. Sessions and Errors alerts always use Count; any other value is ignored for them
- functionColumn (required unless functionType is Count): Field to aggregate (e.g., "duration" for P90 latency). Ignored for Sessions and Errors
- query (optional): Filter query string using search syntax (e.g., "service_name=api level=error")
- groupBy (optional): Array of dimension keys to alert per-group (e.g., ["service_name"] fires separately per service). Sessions alerts can't be grouped; Errors alerts always group by ["event"]
- thresholdValue (optional): The threshold to compare against. Required for Constant threshold alerts.
- thresholdWindow (optional, default 3600): Evaluation window in seconds (e.g., 300 = look at the last 5 minutes)
- thresholdCooldown (optional, default 1800): Seconds to wait before re-notifying while still alerting
- evaluationDelaySeconds (optional, default 0): Seconds to wait before evaluating each window, so late-arriving data is counted
- thresholdType (optional, default "Constant"): "Constant" compares against thresholdValue; "Anomaly" detects deviations automatically
- thresholdCondition (optional, default "Above"): "Above", "Below", or "Outside" (Anomaly only)
- messageContent (optional): Custom text included in alert notifications
- destinations (optional): Array of notification destinations, each with:
  - destinationType: One of Slack, Discord, MicrosoftTeams, Webhook, Email
  - typeId: Destination identifier (Slack channel ID, email address, webhook URL)
  - typeName: Human-readable name (Slack channel name, email address)
- autoInvestigationEnabled (optional): when true, each firing starts an automatic AI investigation and posts the diagnosis to the alert's destinations
- investigationCooldownSeconds (optional, default 86400): minimum gap between automatic investigations. Keep at or above thresholdCooldown so a chatty alert doesn't re-investigate the same condition
- investigationPermissionMode (optional, default "read"): "read" investigates and reports; "read-write" additionally lets the investigation open a PR
- investigationRepositories (optional): repos the investigation may read. Without these it cannot correlate a firing against a recent deploy
- investigationPrompt (optional): extra standing instructions prepended to each investigation

RETURNS:
- alert_created: Boolean indicating success
- alert_id: ID of the created alert
- alert_url: URL to view the alert
- notes: Present when an input was overridden by the product-type rules above

Example - alert when error count in the last 5 minutes exceeds 100:
{"projectKey": "default", "name": "High Error Volume", "productType": "Errors", "functionType": "Count", "thresholdValue": 100, "thresholdWindow": 300}

Example - P90 API latency above 2s, notified in Slack:
{"projectKey": "default", "name": "Slow API", "productType": "Traces", "functionType": "P90", "functionColumn": "duration", "query": "service_name=api", "thresholdValue": 2000, "thresholdWindow": 300, "destinations": [{"destinationType": "Slack", "typeId": "C0123456789", "typeName": "#alerts"}]}
- **get-alert-firing-history**: Show when an alert actually fired, and what state it is in now.

This is the tool that answers "is this alert doing anything?". list-alerts cannot: disabled=false only means the alert is being evaluated, and updated_at is the last config edit, not the last firing. Use this to find stale alerts worth retiring, to check whether a threshold is reachable, and to confirm an alert still works after you retune it.

INPUTS:
- projectKey (required): The LaunchDarkly project key (e.g., "default").
- alertId (required): The numeric ID of the alert (from list-alerts)
- lookbackDays (optional, default 30): How far back to count firings. Must be positive.
- limit (optional, default 20, max 100): Max individual firing rows to return, newest first

RETURNS:
- firing_count: Total firings in the window. May exceed the rows returned — check truncated
- last_fired_at: Timestamp of the most recent firing, or null if it never fired in the window
- firings: Newest-first rows with timestamp, state, group_by_key, and investigation_conversation_id when an automatic investigation ran for that firing
- current_state: Latest state per group (any state, unwindowed). This is how you tell an alert firing RIGHT NOW from one that fired and resolved. States: Normal, Pending, Alerting, AlertingSilently, NoData, Error

Only Alerting transitions are counted, so firing_count is a count of real firings rather than of every state change.

Retention is not a constraint: the backing table has no TTL, so 30-, 60-, and 90-day windows are all equally valid. Pick the one that fits the question.

A current_state of NoData is a finding worth reporting — the alert's query matches nothing, so it can no longer fire regardless of threshold. That usually means the underlying service was renamed or stopped emitting.

Example usage:
{"projectKey": "default", "alertId": 42, "lookbackDays": 90}
- **get-alert**: Get detailed information about a specific observability alert.

Use this tool to understand the configuration of an existing alert.

INPUTS:
- projectKey (required): The LaunchDarkly project key (e.g., "default").
- alertId (required): The numeric ID of the alert (from list-alerts)

RETURNS:
- id, name, product_type, function_type, function_column, query, group_by_keys
- disabled: Whether the alert is currently disabled
- threshold_value, threshold_window, threshold_cooldown, threshold_type, threshold_condition
- message_content: Custom notification message, if set
- destinations: Where notifications are sent (Slack, Email, Webhook, ...)
- alert_url: URL to view the alert

Example usage:
{"projectKey": "default", "alertId": 42}
- **list-alerts**: List existing observability alerts for the project.

Use this tool to see what alerts already exist before creating new ones.

INPUTS:
- projectKey (required): The LaunchDarkly project key (e.g., "default").
- search (optional): Filter alerts by name (case-insensitive substring match)

RETURNS:
- alerts: Array of alert objects with id, name, product_type, function_type, query, threshold configuration, disabled, destinations, the auto-investigation settings (auto_investigation_enabled, investigation_cooldown, permission_mode, investigation_repositories), and alert_url
- total_count: Total number of matching alerts

This tool does NOT tell you whether an alert ever fired. disabled=false only means it is being evaluated, and updated_at is the last config edit, not the last firing. Use get-alert-firing-history to judge whether an alert is stale or load-bearing.

Example usage:
{"projectKey": "default", "search": "error"}
- **delete-dashboard**: Permanently delete a dashboard (visualization) and all of its graphs. THIS IS IRREVERSIBLE. Requires confirm=true to execute. Use get-dashboard first to verify you are deleting the right dashboard.

INPUTS:
- projectKey (required): The LaunchDarkly project key (e.g., "default").
- dashboardId (required): The numeric ID of the dashboard to delete (from list-dashboards)
- confirm (required): Must be true to execute the deletion

RETURNS:
- deleted: Boolean indicating success
- dashboard_id: ID of the deleted dashboard
- **list-ai-tool-versions**: List the versions of one AI tool in a project, newest first. Returns each version's key, description, schema, version, tags, and customParameters. Use to pick a specific version to pass in the tools array ({key, version}) with create-agentcontrol-config-variation or update-agentcontrol-config-variation. Pagination: responses include `totalCount`. To get the next page, set `offset` to the current offset &#43; limit.
- **vent**: Report a missing capability, bug, parameter gap, or unclear error encountered while using LaunchDarkly MCP tools. This feedback is collected and triaged to improve the toolset. Use this when a tool is missing, returns an unexpected error, or lacks a needed parameter.
- **get-doc**: Fetch the full markdown content of a LaunchDarkly documentation page.

Pass a URL returned by `search-docs`, or any `https://launchdarkly.com/docs/` URL.

The LaunchDarkly docs site serves clean markdown when the URL path ends with `.md` (e.g. `https://launchdarkly.com/docs/home/flags/create.md`). This tool appends `.md` automatically if not already present.

Responses are capped at 75 KB. When `truncated` is true, fetch the next logical section directly or narrow your search query.

Only `https://launchdarkly.com/docs/` URLs are accepted.
- **search-docs**: Search LaunchDarkly documentation to retrieve authoritative reference material for flags, targeting rules, experiments, segments, AgentControl configs, SDKs, API fields, rollouts, metrics, and more.

Returns a ranked list of matching doc sections with their title, URL, description, and category. Use `get-doc` to fetch the full markdown content for any result.

Each result URL is a stable ID: append `.md` to the URL to read the page as markdown (e.g. `https://launchdarkly.com/docs/home/flags/create.md`).

Examples:
- query: `targeting rules clauses` — finds flag targeting configuration docs
- query: `experiment audience allocation` — finds experiment setup docs
- query: `AgentControl variation rollout` — finds AgentControl config docs
- query: `contexts anonymous evaluation` — finds context evaluation docs

Note: this searches the published docs index only — it does not search the REST API reference (available at https://launchdarkly.com/docs/api).
- **get-context-instances**: Get all stored instances of a specific context by kind and key. Returns every recorded occurrence of the context, including its full attribute set (e.g., merchantCountryCode, disbursementRail) and which SDK/application reported each instance.

Use search-contexts to find a context key, then use this tool to inspect its full attribute history across all SDK applications.

Pagination: responses include `totalCount` and `continuationToken`. Pass `continuationToken` from the previous response to get the next page.
- **search-contexts**: Search for stored LaunchDarkly contexts in an environment by kind, key, or attribute value. Returns context records including their stored attributes (e.g., merchantCountryCode, disbursementRail) and when the context was last seen.

Convenience param:
- `kind`: filter to a specific context kind (e.g. `Merchant`, `user`, `organization`). Emitted as the filter clause `kind equals ""`.

Raw filter syntax (passed in `filter`) uses `field operator value` clauses. Operators: `equals`, `notEquals`, `anyOf`, `startsWith`, `exists`, `before`, `after`; `contains` and `notContains` are not supported.
Combine clauses with `,` (AND) or `|` (OR); group with `()`.
Supported fields: `kind`, `key`, `kindKey`, `name`, `applicationId`, `q` (fuzzy), and `.` for context attributes.
Examples:
- `kind equals "Merchant"` — contexts of a specific kind
- `Merchant.merchantCountryCode equals "US"` — Merchant contexts whose attribute matches
- `key startsWith "merchant-"` — contexts whose key has a prefix
- `applicationId equals "GoSDK/1.2"` — contexts reported by a specific SDK/application

Example combining both params: set `kind=Merchant` and `filter=Merchant.disbursementRail equals "PIX"` to find Merchant contexts on the PIX rail.

Note: the contexts API cannot filter by which flag a context evaluated; there is no `flagEvaluated` field. Filter by kind, key, applicationId, or attribute values instead.

Ordering is fixed by the API; there is no sort parameter.

Pagination: responses include `totalCount` and `continuationToken`. Pass `continuationToken` from the previous response to get the next page.
- **get-service-connections-usage**: Get a time series of service connection minutes from your LaunchDarkly account. Use this for capacity planning, cost analysis, and before/after deploy comparisons (e.g. compare daily incremental minutes around a deploy date).

TIME RANGE: Pass `from` and `to` as Unix millisecond timestamp strings. Both default to the current month. Maximum range is 365 days.

AGGREGATION TYPES:
- 'month_to_date' (default): cumulative minutes from the start of the month to each data point
- 'incremental': delta minutes for each granularity period — use this for deploy comparisons

GRANULARITY:
- 'daily' (default): one data point per day
- 'hourly': one data point per hour (useful for same-day deploy impact)
- 'monthly': one data point per month (only with aggregationType='month_to_date')

FILTERING: Pass `projectKey`, `environmentKey`, `connectionType`, `sdkName`, `sdkVersion`, or `sdkType` arrays to narrow results. When filtering by `environmentKey`, exactly one `projectKey` must also be provided.

GROUPING: Pass `groupBy` array to split results by dimension. Valid values: projectId, environmentId, connectionType, relayVersion, sdkName, sdkVersion, sdkType.

EXAMPLE — compare May 21 vs Jun 29 deploys:
  aggregationType='incremental', granularity='daily',   from='', to='', environmentKey=['production']
- **match-release-policies**: Resolve which release policies would govern a flag in a given environment — a read-only dry-run of the server-side policy matching logic. Does not create or modify anything.

Two modes:
- `flagKey` (existing flag): calls the server-side release-settings endpoint, which returns the authoritative resolved policy for that flag&#43;environment.
- `flagTags` (pre-creation preview): performs client-side matching against all project release policies using the proposed tag set — useful before the flag exists.

If both are supplied, `flagKey` wins and the server-side path is used.

Returns:
- `matchingPolicies` — all policies whose scope matches (sorted by rank ascending, with default rank -1 last); for the flagKey path this contains just the server-resolved winning policy if one exists
- `winningPolicy` — the resolved match, or null
- `winningReleaseMethod` — release method of the winning policy, or null
- `autoAttachedMetricKeys` / `autoAttachedMetricGroupKeys` — metrics that would auto-attach
- `warnings` — missing or incomplete policy configuration that must be shown in generated comments; if present, do not state the release plan as a clean policy rollout
- `criteria` — echo of the inputs used

Use cases:
1. After flag creation: explain which policy governs the flag in this environment
2. Before flag creation: preview which policy would apply given proposed tags
- **create-automated-rollout-config**: Record an automated rollout config in LaunchDarkly for a feature-flagged change.

Use this only for AutomatedRollout requests. The guarding feature flag must already exist in LaunchDarkly. Works for both an existing PR the user points you at and a PR you just filed.

PER-ENVIRONMENT RELEASE TYPES:
- "override" (default): Pins the exact rollout inline via the optional `override` object. With no `override` object it is an immediate release — the flag turns on once it begins evaluating, the same trigger as guarded and progressive releases, just with no stages to ramp through.
- "policy": Waits until the PR is merged and the flag begins evaluating, then resolves the environment's configured release policy and performs the appropriate release according to that policy. Do not pass an `override` object with "policy". The response includes `warnings` if a policy environment has no matching policy or the winning policy is missing stages/metrics; render those warnings in generated comments and do not state the release as a clean policy rollout. Do not add tags automatically to make a policy match.

APPLICATION GATE:
- Inspect the repository's LaunchDarkly SDK configuration for stable SDK application ids already reported by affected runtime applications. When present, pass those exact values in requiredApplicationKeys so unrelated evaluations from tests, jobs, or other applications do not trigger the release. If no application id is already instrumented, omit this field; do not add application metadata solely to configure the rollout. The rollout API calls this value an application key; it must exactly match the SDK-reported id and is not a LaunchDarkly application object id.
- Never guess an id. For a change spanning multiple instrumented runtime applications, include every relevant application id; release waits until all listed applications have evaluated the flag.

OVERRIDE METHODS (the `override.releaseMethod` field, only for releaseType "override"):
- "immediate": Turn the flag on. Omit stages/metrics/rollback. Equivalent to omitting `override`.
- "progressive": Ramp the true variation through `stages`. Requires a non-empty `stages` array.
- "guarded": Measured rollout through `stages`, gated on metrics, with optional auto-rollback. Requires `stages` plus at least one of `metricKeys` / `metricGroupKeys`.

STAGES: Each stage is { allocation, durationMillis }. allocation is basis points (100000 = 100%), must be positive and strictly increasing across stages; guarded caps every stage (including the last) at 50000 (50%) — a guarded rollout auto-promotes to 100% after its last monitored stage completes without regression, so don't add a 100000 stage yourself. Progressive has no such cap and typically ends with an explicit 100000 stage to reach full rollout. durationMillis is each stage's monitoring window in milliseconds and must be > 0 for every stage without exception, including the last one in the array — a zero or omitted duration there is rejected, even though nothing ramps after it.

INPUTS:
- projectKey (required): LaunchDarkly project key (e.g., "default").
- flagKey (required): Key of the guarding feature flag (must already exist).
- requiredApplicationKeys (optional): Existing SDK-reported application ids (called application keys by the rollout API) that must evaluate the flag before release. Omit when the repository has no application id instrumentation.
- executionMode (optional): "parallel" (legacy behavior) starts environments independently. "sequential" releases environments in array order.
- environments (required): Ordered per-environment rollout plan. Array of { environmentKey, releaseType?, override?, triggerType?, waitBeforeReleaseMillis? } objects. `triggerType` is "flag_eval" (the default) to start after the flag is observed evaluating, or "webhook" to wait for a CI/CD deploy signal. `waitBeforeReleaseMillis` is a non-negative delay after the preceding environment finishes and only applies to sequential configs; it is dropped from the first sequential environment, which has nothing to wait after. `override` is only allowed with releaseType "override" and is { releaseMethod, rolloutContextKindKey?, stages?, metricKeys?, metricGroupKeys?, rollbackOnRegression? }.
- repoFullName (optional): GitHub repo as "owner/repo".
- prNumber (optional): PR number.
- prUrl (optional): Full PR URL.
- startingVariationId (optional): For a multi-variate flag, the id of the variation the flag rolls out from. If omitted, a boolean flag assumes the false variation.
- endingVariationId (optional): For a multi-variate flag, the id of the variation the flag rolls out to. If omitted, a boolean flag assumes the true variation. A multi-variate flag requires both startingVariationId and endingVariationId to be set; setting only one is rejected.

RETURNS:
- created: Boolean indicating success.
- config_id: Identifier of the created rollout config.
- flag_key: Echoed flag key.
- required_application_keys: Normalized application ids required by the evaluation gate, when supplied.
- environments: Normalized per-environment plan that was sent.

- warnings: Advisory warnings for policy environments with missing or incomplete release policies.
- On failure: created=false with an error. retryable=false means retrying the same call will not help (the flag isn't in this project, or a conflicting config exists).

Example (immediate in staging, guarded in production):
{"projectKey": "default", "flagKey": "new-checkout-flow", "requiredApplicationKeys": ["checkout-web"], "environments": [{"environmentKey": "staging", "releaseType": "override"}, {"environmentKey": "production", "releaseType": "override", "override": {"releaseMethod": "guarded", "stages": [{"allocation": 10000, "durationMillis": 3600000}, {"allocation": 50000, "durationMillis": 3600000}], "metricKeys": ["checkout-error-rate"], "rollbackOnRegression": true}}], "repoFullName": "launchdarkly/gonfalon", "prNumber": 12345}
- **list-projects**: List LaunchDarkly projects in the account. Use to discover project keys before calling project-scoped tools. Filtering: use `query` to search by project name or key (case-insensitive), `tags` to filter by tag (all must match). Sorting: use `sort` with `name` or `-name`. Pagination: responses include `totalCount` and `pageInfo.offset`. To get the next page, set `offset` to the current offset &#43; limit.
- **query-change-history**: Query the audit log to find what changed in a LaunchDarkly account. Returns a chronological list of changes (newest first) with who made each change and what they did.

USE THIS TOOL WHEN:
- The user asks "what changed recently?" or "what happened in the last X hours/days?"
- Investigating whether a flag change could have caused an incident
- Looking for changes made by a specific person or to a specific environment

OPTIONAL INPUTS:
- projectKey: The LaunchDarkly project key (e.g., "default"). Scopes results to a single project. Omit to query across all projects (useful for account-level changes like member invites or project creation).
- env: Environment key (e.g., "staging", "production"). Narrows results to changes affecting that environment.
- resourceKind: Filter by resource type. Common values: "flag", "segment", "env", "project", "metric", "experiment", "aiconfig", "member", "role", "team", "integration", "webhook", "release-pipeline", "release-policy". Environment-scoped kinds (flag, segment, experiment, holdout, destination, aiconfig) automatically include the env segment. Account-level kinds (member, role, team, webhook, integration) do not require a projectKey.
  IMPORTANT: Always include resourceKind for best results. Without it, only changes to the project or environment resource itself are returned — not changes to child resources like flags or segments within it. For broad queries (e.g. "what changed recently?"), omit both projectKey and resourceKind to get all changes, or specify resourceKind: "flag" to see all flag changes in a project.
- resourceKey: Specific resource key (e.g., a flag key). Requires resourceKind to be set.
- tags: Array of tag strings to scope results (AND logic — resource must have ALL listed tags). Tags are supported on all resource types. Example: ["mobile", "v2"] narrows to resources tagged with both "mobile" AND "v2".
- query: Full-text search across resource names (e.g., "dark-mode", "checkout").
- startDate: Start of time window in ISO 8601 format (e.g., "2024-06-10T00:00:00Z"). If omitted, no lower time bound is applied — the API returns the N most recent entries.
- endDate: End of time window in ISO 8601 format. If omitted, no upper time bound is applied (effectively "now").
- limit: Number of entries to return (1-20). Defaults to 20.

EXAMPLES:
1. All flag changes in staging: {"projectKey": "default", "env": "staging", "resourceKind": "flag"}
2. Flag changes in last 7 days: {"projectKey": "default", "resourceKind": "flag", "startDate": "2024-06-04T00:00:00Z"}
3. Changes to a specific flag: {"projectKey": "default", "resourceKind": "flag", "resourceKey": "dark-mode"}
4. Metric changes: {"projectKey": "default", "resourceKind": "metric"}
5. Member/team changes (account-level): {"resourceKind": "member"}
6. All recent changes (any resource): {}
7. Flag changes filtered by tags: {"projectKey": "default", "resourceKind": "flag", "tags": ["mobile"]}

PAGINATION:
When hasMore is true, the response includes a nextBefore timestamp. To fetch the next page, call again with endDate set to the nextBefore value (keep all other filters the same).
- **update-segment-targets**: Add or remove individual context keys from a segment's included or excluded lists. Included targets always match the segment. Excluded targets never match, even if rules would include them. Supported kinds: addIncludedTargets, removeIncludedTargets, addExcludedTargets, removeExcludedTargets. Each instruction requires contextKind and values. If the environment requires approval, the response includes requiresApproval: true and the attempted instructions; call `create-approval-request` with segmentKey, env, and the returned instructions to submit it for review.
- **update-segment-rules**: Add, remove, or modify attribute-based targeting rules on a segment. Rules evaluate context attributes to determine segment membership. Clauses within a rule are ANDed; multiple rules use OR logic. Supported kinds: addRule, removeRule, addClauses, removeClauses, updateClause, addValuesToClause, removeValuesFromClause, reorderRules, updateRuleDescription, updateRuleRolloutAndContextKind. If the environment requires approval, the response includes requiresApproval: true and the attempted instructions; call `create-approval-request` with segmentKey, env, and the returned instructions to submit it for review.
- **get-segment**: Get detailed configuration for a single segment in an environment. Returns rules, included targets, excluded targets, tags, and creation date. Use to verify segment state after creation or updates.
- **create-segment**: Create a new segment in a project environment. The segment is empty after creation — use update-segment-rules to add targeting rules or update-segment-targets to add individual context keys. Segment keys are immutable after creation: choose carefully. Pass viewKeys to link the new segment to one or more views at creation time (Views are an Enterprise feature).
- **list-segments**: List segments in a project environment. Returns a paginated list with rule counts and target counts. Use query to search by name or key, tags to filter by tag, or view to only include segments linked to a view (Views are an Enterprise feature). Always list first to avoid creating duplicates.

Sorting: use `sort` with `creationDate`, `name`, or `lastModified`; prefix with `-` for descending. Defaults to `-creationDate`.

Pagination: responses include `totalCount` and `pageInfo.offset`. To get the next page, set `offset` to the current offset &#43; limit.
- **delete-prompt-snippet**: Permanently delete a prompt snippet. THIS IS IRREVERSIBLE. Any AgentControl Config variations referencing this snippet will lose their reference. Requires confirm=true to execute.
- **update-prompt-snippet**: Update an existing prompt snippet. Creates a new version of the snippet. All fields are optional — only provided fields are updated.
- **create-prompt-snippet**: Create a new prompt snippet. A snippet is a reusable text block that can be referenced in AgentControl Config variation prompts using {{snippet-key}} syntax. Provide a unique key, display name, and the text content.
- **get-prompt-snippet**: Get a specific prompt snippet by key. Returns the snippet's name, text content, tags, version, and creation time.
- **list-prompt-snippets**: List prompt snippets in a project. Prompt snippets are reusable text blocks that can be referenced inside AgentControl Config variation prompts to keep common instructions consistent. Returns key, name, text, version, and tags.
- **update-playground**: Update an LLM playground's name, variants, or archived status. All fields are optional.
- **create-playground**: Create a new LLM playground. A playground lets you compare AgentControl Config variations side-by-side. Provide a name and variants — each variant references an evaluation definition (by evaluationId) and a display position.
- **get-playground**: Get details about a specific LLM playground, including its variants (evaluation definitions and their positions).
- **list-playgrounds**: List LLM playgrounds in a project. Returns playground names, variant counts, and timestamps. Supports search by name and pagination.
- **get-evaluation-run-summary**: Get the progress and results of an evaluation run. runId comes from run-evaluation. Works while the run is in progress. Returns statusCounts (the run is done when pending is 0), criterionSummaries (per-criterion scores), and latency and token stats.
- **run-evaluation**: Start a run of an AI evaluation. evaluationId comes from create-evaluation or list-evaluations, and the evaluation must use only deepeval criteria. Provide exactly one target: datasetId (from list-datasets; the dataset must finish processing) or playgroundId (from list-playgrounds). rowSelectionMode is "all" (the default), "top" (the first rows), or "random" (a sample). top and random also need rowSelectionUnit "count" with a positive integer (e.g. 50), or "percent" with a fraction in (0, 1] (e.g. 0.25). Returns the run with id, state (PENDING, GENERATED, EVALUATED, COMPLETE, CANCELLED, TEMPORARY_ERROR, or PERMANENT_ERROR; read statusReason on an error), evaluatedAt, rowCount, and selectedRowCount. Pass id as runId to get-evaluation-run-summary for progress and results.
- **create-evaluation**: Create an AI evaluation: a saved prompt, a generation model, and scoring criteria. It does not reference an AgentControl Config. Do not send configKey, datasetId, or variationKeys; pass datasetId or playgroundId to run-evaluation instead. Required: name, generationProvider (e.g. "OpenAI"), and generationModel as Provider.model-id (e.g. "OpenAI.gpt-4o", the same format as a variation's modelConfigKey). Optional: messages, an array of {role, content} where role is "system", "user", or "assistant" and content can use {{placeholders}}; variables, a freeform object of placeholder values, e.g. {"city":"Paris"}; promptSnippets, an object of snippet text keyed by name, required when messages use {{snippet.}}; parameters, freeform model parameters, e.g. {"temperature":0.2}; evaluationProvider and evaluationModel, the judge model, in the same formats. criteria is an array of {criterionType, kind?, options?}, e.g. [{"criterionType":"accuracy","options":{"expected_output":"Sunny"}},{"criterionType":"toxicity"}]. Deepeval criterionType values: accuracy, likeness, misinformation, answer_relevancy, bias, toxicity. kind "deepeval" (the default) is the only kind that run-evaluation scores. "judge" and "scorer" are for SDK-driven runs only. They need successDirection and options.threshold (0 to 1); judge also needs judgeKey (a judge AgentControl Config key). Pass the returned id as evaluationId to run-evaluation.
- **get-evaluation**: Get one AI evaluation by evaluationId (from list-evaluations or create-evaluation). Returns its models, messages, variables, parameters, criteria, and version. version increases on each change, and each run records the version that it used.
- **list-evaluations**: List AI evaluations in a project with id, version, name, models, messages, criteria, and totalCount. search matches the name. limit defaults to 25; offset defaults to 0. Pass an id as evaluationId to get-evaluation or run-evaluation.
- **delete-dataset**: Permanently delete an offline dataset and its associated metadata. THIS IS IRREVERSIBLE. Requires confirm=true to execute.
- **create-dataset**: Create an offline dataset for AI evaluation. key must be unique in the project (e.g. support-tickets-v1); name is a display name (e.g. Support tickets). format is csv or jsonl. filename is optional (e.g. support-tickets.csv). sizeBytes is the file size in bytes. Returns id, key, name, status (pending), uploadUrl, uploadMethod (PUT), uploadHeaders, and uploadExpiresAt. Next, send the file with an HTTP PUT to uploadUrl, with the uploadHeaders, before uploadExpiresAt. Then call get-dataset until status is ready, and pass id as datasetId to run-evaluation. Set empty=true to create a ready dataset with no rows and no upload URL.
- **get-dataset**: Get one offline dataset by id with key, name, filename, format, status, rowCount, and createdAt. datasetId is the UUID id from list-datasets or create-dataset (e.g. af697107-584b-4b8c-8c05-d42c6e4f1a1a). After an upload, call this until status is ready (or failed), then pass the id to run-evaluation.
- **list-datasets**: List offline datasets in a project with id, key, name, filename, format, status (pending, ready, or failed), rowCount, and createdAt. page starts at 1 (the default); pageSize defaults to 50 and allows 1 to 200. The response has totalCount, page, and pageSize; when page * pageSize < totalCount, call again with page &#43; 1 (e.g. page 2) to get more. Pass a ready dataset's id as datasetId to get-dataset or run-evaluation.
- **stop-guarded-rollout**: Stop an active guarded rollout on a flag's default rule (fallthrough). This immediately halts the progressive rollout and locks the flag to its current state. If the environment requires approval, the response includes requiresApproval: true and the attempted instructions; call `create-approval-request` with the returned instructions to submit it for review.
- **start-guarded-rollout**: Start a guarded rollout on a flag's default rule (fallthrough). A guarded rollout progressively increases traffic to the test variation through a series of stages while monitoring metrics for regressions. Each stage specifies a rolloutWeight (percentage in thousandths, e.g. 10000 = 10%) and a monitoring window in milliseconds. Metrics define what to monitor and whether to notify or rollback on regression. Requires the flag to be on and not already have an active guarded rollout. If the environment requires approval, the response includes requiresApproval: true and the attempted instructions; call `create-approval-request` with the returned instructions to submit it for review.
- **get-experiment-metric-results**: Get detailed statistical results for a single metric on an experiment iteration. Returns, per treatment: sample sizes (analyzedUnitCount, trafficCount, conversionCount), the observed mean and standard deviation, and a `statistics` block with the lift versus control (relativeDifferences: estimate plus lower/upper interval bounds and, for frequentist experiments, a per-comparison pValue), the overall pValue, Bayesian probabilities (probabilityToBeBest, probabilityToBeatBaseline, expectedLoss), and an isSignificant flag. Reads from LaunchDarkly's internal analysis API. Defaults to the current iteration and the latest analysis; pass iterationId to target a previous iteration. Use disableMultipleComparisonCorrection / disableSequentialTesting to see uncorrected numbers. Use get-experiment-results for a cross-metric overview, or get-experiment to discover metric keys.
- **get-experiment-results**: Get an overall results summary for an experiment, across every metric on the current iteration. Discovers the iteration's metrics, then fetches each metric's analysis from LaunchDarkly's internal results API and returns a compact per-metric summary: which treatment is leading (isBest) — the arm with the highest probability to beat the baseline for Bayesian experiments, or the lowest p-value versus control for frequentist (note: not significance-gated, so a treatment can be flagged leading even when nothing is significant) — each treatment's lift versus control, whether it's statistically significant, and sample sizes. Pass iterationId to summarize a previous iteration. For the full per-treatment statistics (intervals, p-values, Bayesian probabilities) on one metric, use get-experiment-metric-results.
- **stop-experiment-iteration**: Stop the currently running iteration of an experiment. Data collection ends and the iteration moves to the `stopped` status. A winning treatment is required to stop: pass `winningTreatmentId` (the `_id` of one of the iteration's treatments, available from get-experiment) and an optional `winningReason` explaining the call. If the experiment was inconclusive, declare the baseline/control treatment as the winner.
- **save-and-start-experiment-iteration**: Stop the current running iteration, create a new draft iteration with the provided field updates applied, and start it — the API-recommended way to mutate treatments, metrics, methodology, or other fields that are locked while an iteration is running. Provide `changeJustification` to record why a new iteration is needed. Field inputs are the same as `update-experiment`; updates are checked against the new iteration's not_started mutability rules. Fields not allowed in not_started are returned under `skipped` rather than being sent.
- **start-experiment-iteration**: Start an experiment iteration. This begins data collection for the experiment's current draft iteration and starts allocating live end-user traffic across its treatments. The experiment's flag must be toggled on, a randomization unit must be set, and at least one treatment must have a non-zero allocation percent.

Requires explicit user confirmation. Only call this when the user has asked to start the experiment — never as an automatic follow-up to create-experiment or update-experiment. If the user has not confirmed, show them the experiment's `designUrl` and ask whether the design looks right before starting.
- **update-experiment**: Update fields on an experiment or its current iteration. Which fields are mutable depends on the current iteration's status (not_started, running, stopped). This tool first reads the experiment's mutableFieldsByStatus, applies only the updates that are allowed for the current status via the updateExperimentFields semantic patch, and returns any rejected fields under `skipped` with the reason. If no provided field is mutable, the response includes `currentStatus` and `allowedFields` so you can retry with valid inputs.

Scalar fields: name, description, maintainerId, tags (string[]), hypothesis, attributes (slicing dimensions, string[]), methodology (bayesian|frequentist|export_only), analysisConfig, randomizationUnit, canReshuffleTraffic, primarySingleMetricKey, primaryFunnelKey, dataSource (launchdarkly|snowflake|databricks), holdoutId, covariateId.

Structural fields (typically only mutable while iteration status is not_started; call get-experiment first to see current values):
- metrics: array of { key, isGroup? }. Replaces the iteration's metric list.
- treatments: array of { name, baseline, allocationPercent, parameters: [{ flagKey, variationId }] }. Exactly one treatment must have baseline=true; allocationPercents should sum to 100.
- flags: object keyed by flag key with { ruleId, flagConfigVersion, notInExperimentVariationId? }. Use for the initial flag/rule attachment on a not_started iteration.
- flagSettings: same shape as flags but only updates ruleId / flagConfigVersion / notInExperimentVariationId on already-attached flags (used on stopped iterations to rebind without changing flag keys).
- **create-experiment**: Create a new experiment on a flag or AgentControl Config. An experiment measures the impact of different variations on specified metrics. You must provide the initial iteration definition including a hypothesis, metrics, treatments, and flag configuration. One treatment must be marked as the baseline. Use `methodology` to pick the results-analysis approach (`frequentist` default, `bayesian`, or `export_only` for data-export-only mode). Use `analysisConfig` to set thresholds and multiple-comparison correction. Use `iteration.attributes` to declare slicing dimensions and `iteration.covariateId` to enable stratified sampling.

The experiment is created as a DRAFT: it collects no data and affects no end users until an iteration is started. Do NOT call start-experiment-iteration in the same turn as this tool. Summarize the created design for the user, show them the returned `designUrl`, and wait for their explicit confirmation before starting the experiment.
- **get-experiment**: Get detailed information about a specific experiment, including its treatments, metrics, and current iteration status.
- **list-experiments**: List experiments in a project, optionally filtered by environment. Returns key, name, description, and current iteration status for each experiment.

Filtering:
- `flagKey`: filter experiments by the flag key they are attached to
- `status`: filter by experiment status (e.g. `running`, `stopped`, `not_started`)

Pagination: responses include `totalCount`. To get the next page, set `offset` to the current offset &#43; limit.
- **delete-ai-tool**: Permanently delete an AI tool definition. THIS IS IRREVERSIBLE. Any AgentControl Config variations referencing this tool will lose the attachment. Requires confirm=true to execute.
- **update-ai-tool**: Update an AI tool definition's description, schema, tags, or customParameters. All fields are optional: only provided fields are updated. The schema should be a raw JSON Schema object with type, properties, and required fields. Tags are replaced wholesale, not merged. Returns the tool with its version.
- **toggle-agentcontrol-config**: Not supported: always fails with 400. AgentControl Config targeting cannot be toggled; the API rejects turnFlagOn/turnFlagOff. To serve a variation, call update-agentcontrol-config-rollout with a variationKey from get-agentcontrol-config-targeting.
- **get-keys**: Discover available data keys/dimensions for a product type.

Use this tool BEFORE creating dashboards to understand what data fields are available for filtering and grouping.

INPUTS:
- projectKey (required): The LaunchDarkly project key (e.g., "default").
- productType (required): One of "logs", "traces", "sessions", "errors", "metrics", "paevents", "events". Use "paevents" for product-analytics events (keys like type, key, view_name); "events" is the legacy session_events source.
- startDate (required): ISO format start date (e.g., "2024-01-15T10:00:00Z")
- endDate (optional): ISO format end date (defaults to current time)
- search (optional): Filter keys by name
- limit (optional, default 25): Maximum number of keys to return

RETURNS:
- keys: Array of key objects with name, type and count (occurrences in the window, highest first). Compare counts to tell a real key from a near-miss typo (e.g. service_name with millions of hits vs serviceName with two).
- product_type: The queried product type
- key_count: Number of keys returned

Use the returned keys in:
- create-graph groupBy parameter
- Query filters

Example usage:
{"productType": "errors", "startDate": "2024-01-15T10:00:00Z"}
- **preview-graph**: Preview a chart/graph inline WITHOUT saving it to a dashboard.
Always use this tool first when a user asks to create or visualize a chart.
Returns both the graph configuration and the queried metrics data so the user can see the chart rendered inline. After showing the preview, ask the user if they want to save it to a dashboard (using create-graph).

REQUIRED INPUTS:
- projectKey: The LaunchDarkly project key (e.g., "default").
- title: Chart title.
- type: Chart type — "Line chart", "Bar chart", or "Table".
- productType: Data source — one of "Logs", "Traces", "Sessions", "Errors", "PAEvents", "Events", "Metrics" (case-insensitive aliases accepted). Prefer "PAEvents" over the legacy "Events" source for product-analytics events.
- expressions: Array of aggregations, each with { aggregator, column }. e.g. [{"aggregator": "Count", "column": ""}] for a raw count, or [{"aggregator": "P90", "column": "duration"}] for a percentile. Valid aggregators: Count, CountDistinct, CountDistinctKey, Min, Avg, P50, P75, P90, P95, P99, Max, Sum.

OPTIONAL INPUTS:
- query: Filter string using search syntax, e.g. "level=error" or "service_name=api".
- groupBy: Array of dimension keys, e.g. ["level"] or ["service_name", "level"]. Use get-keys to discover available keys.
- bucketCount: Number of time buckets (default 12).
- startDate: ISO start date. If neither startDate nor endDate is provided, defaults to the last 24 hours.
- endDate: ISO end date. Defaults to now when startDate is provided without endDate.
- display: Display style for bar charts, e.g. "Stacked" or "Grouped".

RETURNS:
- title, type, product_type, query, expressions, group_by, display: echoed graph configuration.
- metrics: time-series buckets queried for the preview.
- _hint: reminder that the UI renders the chart directly — do not emit markdown image syntax.

Example — logs by level as a stacked bar chart:
{"projectKey": "default", "title": "Logs by Level", "type": "Bar chart", "productType": "Logs", "expressions": [{"aggregator": "Count", "column": ""}], "groupBy": ["level"], "display": "Stacked"}
- **delete-graph**: Permanently remove a single chart/graph from its dashboard. THIS IS IRREVERSIBLE. The dashboard itself is untouched. Requires confirm=true to execute. Use get-dashboard first to verify you are deleting the right graph.

INPUTS:
- projectKey (required): The LaunchDarkly project key (e.g., "default").
- graphId (required): The numeric ID of the graph to delete (from get-dashboard)
- confirm (required): Must be true to execute the deletion

RETURNS:
- deleted: Boolean indicating success
- graph_id: ID of the deleted graph
- **update-graph**: Update an existing chart/graph on a dashboard. Only the fields you provide are changed; everything else is preserved.

INPUTS:
- projectKey (required): The LaunchDarkly project key (e.g., "default").
- dashboardId (required): ID of the dashboard the graph belongs to
- graphId (required): ID of the graph to update (from get-dashboard)
- title (optional): Chart title
- type (optional): "Line chart", "Bar chart / histogram", or "Table"
- productType (optional): "Logs", "Traces", "Errors", "Sessions", "Metrics", "PAEvents", or "Events" (case-insensitive aliases accepted; see create-graph)
- query (optional): Filter query string ("" to clear). Must use the product type's grammar (see create-graph)
- expressions (optional): REPLACES the aggregation list. Each entry: {aggregator: one of Count, CountDistinct, CountDistinctKey, Min, Avg, P50, P75, P90, P95, P99, Max, Sum, column}
- groupBy (optional): Dimension keys to group by ([] to clear grouping)
- groupByLimit (optional): Max series to render when grouped (see create-graph)
- limitAggregator, limitColumn (optional): Ranking for groupByLimit (see create-graph)
- bucketBy, bucketCount (optional): Time-bucketing field and count
- display (optional): "Line", "Stacked", "Stacked area"
- environments, services (optional): Filter the chart to specific LD environments/services
- comparisonMode (optional): Period-over-period comparison mode
- showExemplars (optional): Overlay representative data points on the chart
- formulas (optional): Calculated expressions, each {formula, label?, unit?} (e.g. {"formula": "A / B * 100", "unit": "%"})

RETURNS:
- graph_updated: Boolean indicating success
- graph_id, dashboard_id, dashboard_url, and the final chart configuration

Example - widen the time buckets and rename:
{"projectKey": "default", "dashboardId": 12345, "graphId": 678, "title": "Error Rate (hourly)", "bucketCount": 24}
- **create-graph**: Add a chart/graph to an existing dashboard.

IMPORTANT: Before creating a graph:
1. Use get-keys to discover available data dimensions
2. Use the data query tools (query-logs, query-traces, query-aggregations, query-error-groups, query-sessions) to verify data exists

INPUTS:
- projectKey (required): The LaunchDarkly project key (e.g., "default").
- dashboardId (required): ID of the dashboard to add the graph to
- title (required): Chart title (e.g., "Error Rate by Service")
- type (required): Chart type - one of:
  - "Line chart": For time-series trends (errors over time, latency trends)
  - "Bar chart / histogram": For comparisons (errors by service, requests by endpoint)
  - "Table": For detailed breakdowns with multiple dimensions
- productType (required): Data source - one of:
  - "Logs": Log entries
  - "Traces": Distributed traces/spans
  - "Errors": Error groups
  - "Sessions": User sessions
  - "Metrics": Custom metrics
  - "PAEvents": Product analytics events (preferred event source; the one the graph editor UI shows). Filter custom events with `type="track" key=""`, page/screen views with `type="*_view" view_name=""`
  - "Events": Legacy session events. Filter with `event=""`. Prefer PAEvents for new graphs
- expressions (required): Array of aggregations, each with:
  - aggregator: One of Count, CountDistinct, CountDistinctKey, Min, Avg, P50, P75, P90, P95, P99, Max, Sum
  - column: Field to aggregate (empty string "" for Count, field name for others)
- query (optional): Filter query string using search syntax
- groupBy (optional): Array of dimension keys to group by
- groupByLimit (optional, default 10): Maximum number of series to render when groupBy is set. High-cardinality dimensions (URLs, click selectors, account IDs) can produce hundreds of series and make the dashboard UI unresponsive — keep this small. Ignored when groupBy is empty.
- limitAggregator (optional): Which aggregator to rank groups by when applying groupByLimit. Defaults to the first expression's aggregator (Count for Count and CountDistinctKey).
- limitColumn (optional): Column used alongside limitAggregator when ranking groups (e.g. "duration" for P90 latency ranking). Defaults to the first expression's column. Ignored for Count.
- bucketBy (optional, default "Timestamp"): Field to bucket by for time-series
- bucketCount (optional, default 12): Number of time buckets
- display (optional): Display style - "Line", "Stacked", "Stacked area"
- heatmapSecureSessionId (optional, Heatmap only): secure_id of a session that visited the target page
- heatmapSessionTimestamp (optional, Heatmap only): ISO timestamp of that session's navigation to the page

CHART TYPE SELECTION GUIDE:
- Use "Line chart" for: Error rates over time, latency percentiles, request volume trends
- Use "Bar chart / histogram" for: Top errors by type, requests by endpoint, errors by browser
- Use "Table" for: Detailed error listings, session breakdowns, trace details

AGGREGATOR SELECTION GUIDE:
- Count: Total number of events (most common)
- CountDistinct: Unique values (users, sessions, trace IDs)
- Avg/P50/P75/P90/P95/P99: Latency and duration metrics (P75 for Web Vitals, P95 for Datadog-style SLOs)
- Sum: Aggregate numeric totals

Example - Error count over time:
{"dashboardId": 12345, "title": "Error Count", "type": "Line chart", "productType": "Errors", "expressions": [{"aggregator": "Count", "column": ""}], "bucketCount": 24}

Example - Top 10 errors by service:
{"dashboardId": 12345, "title": "Errors by Service", "type": "Bar chart / histogram", "productType": "Errors", "expressions": [{"aggregator": "Count", "column": ""}], "groupBy": ["service_name"], "groupByLimit": 10}
- **update-dashboard**: Update an existing dashboard. Only the fields you provide are changed; everything else is preserved. Use create-graph/update-graph to add or edit charts.

INPUTS:
- projectKey (required): The LaunchDarkly project key (e.g., "default").
- dashboardId (required): The numeric ID of the dashboard (from list-dashboards)
- name (optional): New dashboard name
- timePreset (optional): New default time range, e.g. "last_24_hours", "last_7_days"
- graphIds (optional): Reorder (or hide) graphs — the full ordered list of graph IDs to display. Any existing graph omitted from this list disappears from the dashboard grid (it still exists; re-add its ID to show it again). Get current IDs from get-dashboard.
- variables (optional): REPLACES the full list of dashboard template variables. Each entry:
  - key, defaultValues (array), suggestionType (one of None, Value, Key), field (optional)

RETURNS:
- dashboard_updated: Boolean indicating success
- dashboard_id, dashboard_url, name, time_preset, graph_ids (final state)

Example - reorder graphs 10 and 11, dropping graph 12 from view:
{"projectKey": "default", "dashboardId": 12345, "graphIds": [11, 10]}
- **create-dashboard**: Create a new empty dashboard (visualization) for organizing charts.

IMPORTANT: Before creating a new dashboard:
1. Use list-dashboards to check if a similar dashboard already exists
2. Use get-keys to discover available data dimensions for the product types you want to chart

INPUTS:
- projectKey (required): The LaunchDarkly project key (e.g., "default").
- name (required): Name for the dashboard (e.g., "Frontend Errors Overview")
- timePreset (optional, default "last_24_hours"): Default time range. Use format like "last_24_hours", "last_7_days", "last_30_days"

RETURNS:
- dashboard_created: Boolean indicating success
- dashboard_id: ID of the created dashboard
- dashboard_url: URL to view the dashboard
- name: Dashboard name

After creating a dashboard, use create-graph to add charts to it.

Example usage:
{"name": "API Performance Dashboard", "timePreset": "last_7_days"}
- **get-dashboard**: Get detailed information about a specific dashboard including all its graphs.

Use this tool to understand the configuration of an existing dashboard.

INPUTS:
- projectKey (required): The LaunchDarkly project key (e.g., "default").
- dashboardId (required): The numeric ID of the dashboard

RETURNS:
- id: Dashboard ID
- name: Dashboard name
- kind: "Standard" (graph grid) or "Brief" (analytical report)
- time_preset: Default time range
- dashboard_url: URL to view the dashboard
- graphs: Array of graph configurations with type, title, expressions, etc.
- graph_count: Number of graphs in the dashboard

Example usage:
{"projectKey": "default", "dashboardId": 12345}
- **list-dashboards**: List existing dashboards (visualizations) for the project.

Use this tool to see what dashboards already exist before creating new ones.

INPUTS:
- projectKey (required): The LaunchDarkly project key (e.g., "default").
- search (optional): Filter dashboards by name
- limit (optional, default 10): Maximum number of dashboards to return

RETURNS:
- dashboards: Array of dashboard objects with id, name, kind ("Standard" graph grid or "Brief" analytical report), graph_count, updated_at, dashboard_url
- total_count: Total number of matching dashboards

Example usage:
{"projectKey": "default", "search": "frontend"}
- **query-flag-evaluations**: Query flag evaluations for a session.
Retrieve flag evaluation events for a specific session to understand which feature flags were evaluated during that session.

The tool always scopes results to the given session via secure_session_id and to feature flag events via events.name=feature_flag. Any additional filters (e.g. service_name) can be supplied via the optional query input.

REQUIRED INPUTS:
- projectKey: The LaunchDarkly project key (e.g., "default").
- sessionSecureId: The secure ID of the session to get flag evaluations for. REQUIRED.
- startDate: Start date in ISO format (e.g., "2024-01-15T10:00:00Z"). REQUIRED.

OPTIONAL INPUTS:
- endDate: End date in ISO format (e.g., "2024-01-15T11:00:00Z"). If not provided, uses current time.
- query: Additional filters appended to the session/feature-flag scope (e.g. "service_name=gonfalon-web"). Defaults to empty string.
- direction: SortDirection (must be the string "ASC" or "DESC"). Defaults to "DESC".
- limit: Number of flag evaluation entries to return. Do not use a value greater than 100. Defaults to 50.

DATE FORMAT:
- Use ISO format: "2024-01-15T10:00:00Z" or "2024-01-15T10:00:00-08:00"
- Dates should be reasonable and within your data retention period
- Always specify timezone if not using Z (UTC)

The tool returns flag evaluation events containing timestamp, flag name, and evaluation attributes that occurred during the session.
These events provide insights into which feature flags were evaluated and their values during the user session.
When doing this, you should specify the startDate as the created_at attribute of the session and the endDate as the startDate plus three hours.

Examples:
1. Specific time window: {"sessionSecureId": "abc123def456", "startDate": "2024-01-15T10:00:00Z", "endDate": "2024-01-15T11:00:00Z"}
2. From specific time to now: {"sessionSecureId": "abc123def456", "startDate": "2024-01-15T10:00:00Z"}
3. Extended search: {"sessionSecureId": "abc123def456", "startDate": "2024-01-15T10:00:00Z", "limit": 100}
4. Scoped to a service: {"sessionSecureId": "abc123def456", "startDate": "2024-01-15T10:00:00Z", "query": "service_name=gonfalon-web"}
- **query-timeline-events**: Query timeline indicator events for a session.
Retrieve timeline indicator events for a specific session to understand what happened during that session.
Keep in mind that this will not include flag evaluation events, you must use the query-flag-evaluations tool to retrieve those.

REQUIRED INPUTS:
- sessionSecureId: The secure ID of the session to get timeline events for. REQUIRED.

The tool returns timeline indicator events containing timestamp, type, and event data that occurred during the session.
These events provide insights into user interactions, page views, clicks, and other important activities during the session.

Here's an example of a valid input:
{"sessionSecureId": "abc123def456"}
- **query-sessions**: Query project sessions.
Retrieve sessions for a given project with explicit date range parameters.

REQUIRED INPUTS:
- projectKey: The LaunchDarkly project key (e.g., "default").
- startDate: Start date in ISO format (e.g., "2024-01-15T10:00:00Z"). REQUIRED.

OPTIONAL INPUTS:
- endDate: End date in ISO format (e.g., "2024-01-15T11:00:00Z"). If not provided, uses current time.
- query: Search query string (e.g., "identifier='user@example.com' AND has_errors=true"). Defaults to empty string to get all sessions.
- count: Number of session entries to return. Do not use a value greater than 50. Defaults to 10.
- sortField: Field to sort by (e.g., "created_at", "length"). Defaults to "created_at".
- sortDesc: Boolean for descending sort. Defaults to true.
- page: Page number for pagination. Defaults to 1.

DATE FORMAT:
- Use ISO format: "2024-01-15T10:00:00Z" or "2024-01-15T10:00:00-08:00"
- Dates should be reasonable and within your data retention period
- Always specify timezone if not using Z (UTC)

The tool returns sessions containing session information, user details, and core attributes.

RELATIONSHIP SEARCH (span / no_span / log / no_log with AND, OR, THEN):
Session-level filters (e.g. visited-url=*/a* visited-url=*/b*) only check that each matched, in ANY order and not necessarily on the same event. To ask how events in a session relate (order, absence, co-occurrence, alternatives), wrap each event in a block and join the blocks with AND, OR, or THEN:
- span(A) / no_span(A): a span (page view, click, network request, track event, flag evaluation, backend span) matching A did / did not happen in the session.
- log(A) / no_log(A): a log matching A was / was not recorded during the session (log keys inside: level, message, source, service_name; a bare word searches the message). Log and span blocks are interchangeable everywhere below.
- span(A) span(B) (or AND): both happened, any order (they may match the same event).
- span(A) OR log(B): either happened. (span(A) THEN span(B)) OR (span(C) THEN span(D)) works.
- span(A) THEN span(B): A, and strictly later B. Chains can be longer: span(A) THEN span(B) THEN span(C).
- span(A) THEN no_span(B): A happened and B never happened after it (funnel drop-off). no_span(...)/no_log(...) may only be the LAST step of a chain.
- span(A) no_span(B): A happened and B never happened anywhere in the session. A THEN chain must start with span(...) or log(...).
Prefer OR INSIDE one block when the alternatives are the same kind of event (one scan instead of two joins): span(span_name="click" event.text=("Pay Now" OR "Buy Now")). Use OR BETWEEN blocks for different kinds of events, e.g. span(http.status_code>=500) OR log(level=error).
Put every condition on the SAME event inside ONE span(...). Inside span(...) use span keys, NOT session keys (session keys silently match nothing there):
- visited-url -> view_name="/checkout" (page path or mobile screen name) or url.full=*/checkout*
- clickTextContent -> span_name="click" event.text="Pay Now"; clickSelector -> span_name="click" event.id / event.classname / event.xpath; clickTarget -> span_name="click" event.tag
- event (track event name) -> span_name="track" key="order_completed"
- Other span keys: http.method, http.url, http.status_code, duration, has_errors, service_name, feature_flag.key, feature_flag.result.value.
Session keys (country, browser_name, identifier, email, length, has_rage_clicks, first_time, ...) stay OUTSIDE blocks: country=US span(A) THEN span(B).
Rules: precedence is THEN, then AND, then OR; THEN only joins blocks (never plain filters); no NOT in front of a block (use no_span / no_log); no nested blocks; no group after THEN (expand span(A) THEN (span(B) OR span(C)) into (span(A) THEN span(B)) OR (span(A) THEN span(C)), or merge B and C into one block); OR between a block and a plain filter is rejected, so write country=US (span(A) OR span(B)). There is no WITHIN (time bound) or count operator.
Examples:
- span(view_name="/pricing") THEN span(view_name="/checkout")
- span(span_name="click" event.text="Pay Now") THEN log(level=error message=*payment*)
- span(view_name="/checkout") THEN span(span_name="click" event.text="Pay Now") THEN no_span(span_name="track" key="order_completed")
- span(view_name="/pricing") no_span(span_name="click" event.text="Contact Sales")
- span(http.url=*/api/pay* http.status_code>=500) OR log(level=error message=*payment*)

Examples:
1. Specific time window: {"startDate": "2024-01-15T10:00:00Z", "endDate": "2024-01-15T11:00:00Z"}
2. From specific time to now: {"startDate": "2024-01-15T10:00:00Z"}
3. Filtered sessions: {"startDate": "2024-01-15T10:00:00Z", "query": "has_errors=true", "sortField": "length", "count": 20}
4. Sessions that visited /pricing and later /checkout: {"startDate": "2024-01-15T10:00:00Z", "query": "span(view_name=\"/pricing\") THEN span(view_name=\"/checkout\")"}
5. Getting a specific session (a wide time-window should be specified since we don't know when the session happened): {"startDate": "2024-01-15T10:00:00Z", "query": "secure_id=LWK4jxZch4GMmVYJ0rW3R6CNymSy", "count": 1}

QUERY SYNTAX:
The query is a filter only: no pipes, SELECT or aggregation (use groupBy/expressions for that). An empty query matches everything in the time range.
- Comparison: key=value. Operators: = (or :), !=, , >=, EXISTS, NOT EXISTS. , >= compare numerically.
- Exact = is case-sensitive. A * anywhere in the value makes it a case-insensitive CONTAINS match that can never be anchored (span_name=gorm.* also matches mygorm.Query). To anchor, use a regex: span_name=/^gorm\./. Regex works on = and != only.
- Quote values containing spaces or = > 500ms | service_name=api any_span(span_name=gorm.Query AND duration>1s) | visited-url=*checkout*


When you reference sessions fetched using this tool you MUST put session ids in an XML tag so that the UI can find them and turn them into links for the user. Here is an example of a sessionId in an XML tag: c6wX2TtznM6F0QByEiRBoQBFw1Bv
- **query-error-groups**: Query project error groups.
Retrieve error groups for a given project with explicit date range parameters.

REQUIRED INPUTS:
- projectKey: The LaunchDarkly project key (e.g., "default").
- startDate: Start date in ISO format (e.g., "2024-01-15T10:00:00Z"). REQUIRED.

OPTIONAL INPUTS:
- endDate: End date in ISO format (e.g., "2024-01-15T11:00:00Z"). If not provided, uses current time.
- query: Search query string (e.g., "error_type='RuntimeError' AND environment=production"). Defaults to empty string to get all error groups. Note: Do not attempt to use the 'event' attribute as part of the query. This is not a valid attribute and you should likely be using the exception.message attribute (see example 4 below)
- count: Number of error group entries to return. Do not use a value greater than 50. Defaults to 10.
- page: Page number for pagination. Defaults to 1.

DATE FORMAT:
- Use ISO format: "2024-01-15T10:00:00Z" or "2024-01-15T10:00:00-08:00"
- Dates should be reasonable and within your data retention period
- Always specify timezone if not using Z (UTC)

The tool returns error groups containing error information, frequency, stack traces, and core attributes.

Examples:
1. Specific time window: {"startDate": "2024-01-15T10:00:00Z", "endDate": "2024-01-15T11:00:00Z"}
2. From specific time to now: {"startDate": "2024-01-15T10:00:00Z"}
3. Filtered for a specific error type: {"startDate": "2024-01-15T10:00:00Z", "query": "error_type='RuntimeError'", "count": 20}
4. Filtered for a specific service and error message: {"startDate": "2024-01-15T10:00:00Z", "query": "exception.message=\"Cannot use 'in' operator*\" and service_name=gonfalon-web", "count": 20}

QUERY SYNTAX:
The query is a filter only: no pipes, SELECT or aggregation (use groupBy/expressions for that). An empty query matches everything in the time range.
- Comparison: key=value. Operators: = (or :), !=, , >=, EXISTS, NOT EXISTS. , >= compare numerically.
- Exact = is case-sensitive. A * anywhere in the value makes it a case-insensitive CONTAINS match that can never be anchored (span_name=gorm.* also matches mygorm.Query). To anchor, use a regex: span_name=/^gorm\./. Regex works on = and != only.
- Quote values containing spaces or = > 500ms | service_name=api any_span(span_name=gorm.Query AND duration>1s) | visited-url=*checkout*
- **query-aggregations**: Retrieve bucketed, aggregated values over time for a product type.
Returns time-series buckets (not raw events) suitable for charting trends, comparing groups, and computing sums/averages/percentiles.
Use this instead of query-logs/query-traces/query-sessions/query-error-groups when you want aggregated values over a window rather than individual records.

REQUIRED INPUTS:
- projectKey: The LaunchDarkly project key (e.g., "default").
- productType: Which product to aggregate over: "errors", "traces", "requests", "logs", "sessions", "metrics", "paevents", "events". "requests" is an alias for "traces". Use "metrics" for OpenTelemetry / custom metric data points, and "paevents" for product-analytics events (filter custom events with `type="track" key=""`). "events" is the legacy session_events source (filter with `event=""`) — prefer "paevents". REQUIRED.
- startDate: Start date in ISO format (e.g., "2024-01-15T10:00:00Z"). REQUIRED.

OPTIONAL INPUTS:
- endDate: End date in ISO format. If not provided, uses current time.
- query: Filter string (see QUERY SYNTAX below). Defaults to "" to aggregate all records.
- groupBy: Attribute key(s) to group by. Accepts a single key ("service_name") or an array of keys (["service_name", "level"]) for a composite group. Each bucket's `group` array holds the values in the same order.
- groupLimit: Max number of groups returned when groupBy is set (default 5, max 50). Groups are ranked by the first expression (e.g. the 5 services with the highest P90 duration). Ignored without groupBy.
- bucketCount: Number of equal time buckets to split the window into (default 10, max 300). Use 1 for a single total over the whole window.
- functionType &#43; column: Shorthand for a single aggregation. functionType is one of Count, CountDistinct, CountDistinctKey, Min, Avg, P50, P75, P90, P95, P99, Max, Sum; column is the attribute to aggregate (required for everything except Count). Equivalent to expressions: [{aggregator: functionType, column}].
- expressions: Full form — array of {aggregator, column} computed per bucket. Use this for several aggregations at once. Do not combine with functionType. If neither is given the tool returns a plain Count.

COLUMN GUIDE (what to aggregate):
- Count ignores column (pass "" or omit it). Every other aggregator REQUIRES a column; the call fails with a validation error rather than silently counting.
- traces/requests: "duration" (nanoseconds) or any numeric span attribute. sessions: "length", "active_length". metrics: "value" (the OTel data point value) — confirm with get-keys(productType: "metrics") and pick a Numeric key, since a wrong column name returns empty buckets instead of an error. logs/paevents/events/errors: a numeric attribute discovered via get-keys, or a string key with CountDistinct (e.g. CountDistinct of secure_session_id).

AGGREGATOR GUIDE:
- Count: number of records/data points per bucket.
- CountDistinct: unique values of column (e.g., unique user_ids).
- Sum/Avg/Min/Max: numeric aggregation of column.
- P50/P75/P90/P95/P99: percentiles of column (e.g., P99 latency).

GROUP RANKING:
- With groupBy, the top groupLimit groups are ranked by the first expression (e.g. highest P99), except Count and CountDistinctKey, which rank by record count.

RETURNS:
- metrics.buckets[]: {bucket_id, bucket_min, bucket_max, metric_value, metric_type, column, group}. metric_type and column echo the aggregation actually computed; if metric_type is "Count" while you asked for something else, the request was malformed — check `request`.
- request: the normalised aggregation the backend ran (product_type, query, group_by, group_limit, bucket_count, expressions). Use it to confirm your arguments were honoured.
- _hint: present only when groupBy produced nothing but empty groups.

QUERY SYNTAX:
The query is a filter only: no pipes, SELECT or aggregation (use groupBy/expressions for that). An empty query matches everything in the time range.
- Comparison: key=value. Operators: = (or :), !=, , >=, EXISTS, NOT EXISTS. , >= compare numerically.
- Exact = is case-sensitive. A * anywhere in the value makes it a case-insensitive CONTAINS match that can never be anchored (span_name=gorm.* also matches mygorm.Query). To anchor, use a regex: span_name=/^gorm\./. Regex works on = and != only.
- Quote values containing spaces or = > 500ms | service_name=api any_span(span_name=gorm.Query AND duration>1s) | visited-url=*checkout*

DATE FORMAT:
- Use ISO format: "2024-01-15T10:00:00Z" or "2024-01-15T10:00:00-08:00"; always specify a timezone if not using Z (UTC).

Examples:
1. Error counts for a window: {"productType": "errors", "startDate": "2024-01-15T10:00:00Z", "endDate": "2024-01-15T16:00:00Z"}
2. Top 20 services by request count, one total per service: {"productType": "requests", "startDate": "2024-01-15T10:00:00Z", "groupBy": "service_name", "groupLimit": 20, "bucketCount": 1}
3. P90 latency per service and span: {"productType": "traces", "startDate": "2024-01-15T10:00:00Z", "groupBy": ["service_name", "span_name"], "functionType": "P90", "column": "duration"}
4. Distinct sessions per day that logged a Slack message: {"productType": "logs", "startDate": "2024-01-01T00:00:00Z", "endDate": "2024-01-08T00:00:00Z", "query": "message=*[SLACK]*", "bucketCount": 7, "functionType": "CountDistinct", "column": "secure_session_id"}
5. OTel metrics, average value grouped by metric_name: {"productType": "metrics", "startDate": "2024-01-15T10:00:00Z", "groupBy": "metric_name", "expressions": [{"aggregator": "Avg", "column": "value"}]}
6. Several aggregations at once: {"productType": "traces", "startDate": "2024-01-15T10:00:00Z", "query": "service_name=api span_name!=healthz", "expressions": [{"aggregator": "Count", "column": ""}, {"aggregator": "P99", "column": "duration"}]}
- **query-traces**: Query project traces.
Retrieve traces for a given project with explicit date range parameters.

REQUIRED INPUTS:
- projectKey: The LaunchDarkly project key (e.g., "default").
- startDate: Start date in ISO format (e.g., "2024-01-15T10:00:00Z"). REQUIRED.

OPTIONAL INPUTS:
- endDate: End date in ISO format (e.g., "2024-01-15T11:00:00Z"). If not provided, uses current time.
- query: Search query string (e.g., "span_name=\"getUserData\" AND service_name=auth"). Defaults to empty string to get all traces.
- limit: Number of trace entries to return. Do not use a value greater than 50. Defaults to 20.
- direction: SortDirection (must be the string "ASC" or "DESC"). Defaults to "DESC".
- sortColumn: Column to sort by (e.g., "duration" to find slowest traces). Default sort is by timestamp.
- sortDirection: Sort direction for sortColumn: "ASC" or "DESC". Defaults to "DESC" if sortColumn is set.

DATE FORMAT:
- Use ISO format: "2024-01-15T10:00:00Z" or "2024-01-15T10:00:00-08:00"
- Dates should be reasonable and within your data retention period
- Always specify timezone if not using Z (UTC)
- Never query a date range of more than 24 hours. If you need to query more data than 24 hours, do not use this tool and instead use the query-aggregations tool.

The tool returns a paginated connection with trace entries containing timestamp, span details, and core attributes.
Keep in mind that you can query for the traces that occurred during a particular session by using secure_session_id in your query.
When doing this, you should specify the startDate as the created_at attribute of the session and the endDate as the startDate plus three hours.

To find the slowest traces, use sortColumn="duration" with sortDirection="DESC" instead of adding sort terms to the query string.
Span duration is in NANOSECONDS (e.g. 1500000000 = 1.5s). Convert before reporting latency, and use nanoseconds in duration filters (e.g. "duration>1000000000" for spans over 1s).

RELATIONSHIP SEARCH (span / no_span with AND, OR, THEN):
To ask how spans in the same trace relate, wrap each in span(...) and join the blocks with AND, OR, or THEN. Matches spans of traces that satisfy the expression.
- span(A) span(B) (or AND): the trace has both. span(A) OR span(B): either. Prefer OR inside one block for alternatives of the same span: span(http.status_code=(500 OR 502)).
- span(A) THEN span(B): a span matching A, and a span matching B that started strictly later in the same trace.
- span(A) THEN no_span(B): A happened and no span matching B started after it. no_span(...) may only be the LAST step; a chain must start with span(...).
- Put every condition on the same span inside one span(...), e.g. span(service_name=checkout span_name=reserve) THEN no_span(service_name=payments).
- any_span(...), child_span(...), parent_span(...), root_span(...) and any_session(...) cannot be THEN steps. No NOT in front of a block; no nested blocks. There is no WITHIN (time bound) operator.

Examples:
1. Specific time window: {"startDate": "2024-01-15T10:00:00Z", "endDate": "2024-01-15T11:00:00Z"}
2. From specific time to now: {"startDate": "2024-01-15T10:00:00Z"}
3. With query filter: {"startDate": "2024-01-15T10:00:00Z", "query": "span_name=\"getUserData\"", "limit": 20}
4. Exclude a span and match a wildcard: {"startDate": "2024-01-15T10:00:00Z", "query": "service_name=api span_name!=healthz http.url=*checkout*"}

QUERY SYNTAX:
The query is a filter only: no pipes, SELECT or aggregation (use groupBy/expressions for that). An empty query matches everything in the time range.
- Comparison: key=value. Operators: = (or :), !=, , >=, EXISTS, NOT EXISTS. , >= compare numerically.
- Exact = is case-sensitive. A * anywhere in the value makes it a case-insensitive CONTAINS match that can never be anchored (span_name=gorm.* also matches mygorm.Query). To anchor, use a regex: span_name=/^gorm\./. Regex works on = and != only.
- Quote values containing spaces or = > 500ms | service_name=api any_span(span_name=gorm.Query AND duration>1s) | visited-url=*checkout*
- **query-logs**: Query project logs.
Retrieve logs for a given project with explicit date range parameters.

REQUIRED INPUTS:
- projectKey: The LaunchDarkly project key (e.g., "default").
- startDate: Start date in ISO format (e.g., "2024-01-15T10:00:00Z"). REQUIRED.

OPTIONAL INPUTS:
- endDate: End date in ISO format (e.g., "2024-01-15T11:00:00Z"). If not provided, uses current time.
- query: Search query string (e.g., "message=\"error\" AND level=error"). Defaults to empty string to get all logs.
- limit: Number of log entries to return. Do not use a value greater than 50. Defaults to 20.
- direction: SortDirection (must be the string "ASC" or "DESC"). Defaults to "DESC".

DATE FORMAT:
- Use ISO format: "2024-01-15T10:00:00Z" or "2024-01-15T10:00:00-08:00"
- Dates should be reasonable and within your data retention period
- Always specify timezone if not using Z (UTC)

The tool returns a paginated connection with log entries containing timestamp, level, message and core attributes.
Keep in mind that you can query for the logs that occurred during a particular session by using secure_session_id in your query.
For instance, query="secure_session_id=1234567890" will return all logs that occurred during the session with secure_session_id=1234567890.
When doing this, you should specify the startDate as the created_at attribute of the session and the endDate as the startDate plus three hours.

Examples:
1. Specific time window: {"startDate": "2024-01-15T10:00:00Z", "endDate": "2024-01-15T11:00:00Z"}
2. From specific time to now: {"startDate": "2024-01-15T10:00:00Z"}
3. With query filter: {"startDate": "2024-01-15T10:00:00Z", "query": "level=error", "limit": 50}
4. Wildcard on the message, two terms ANDed: {"startDate": "2024-01-15T10:00:00Z", "query": "message=*[SLACK]* service_name=termag"}

QUERY SYNTAX:
The query is a filter only: no pipes, SELECT or aggregation (use groupBy/expressions for that). An empty query matches everything in the time range.
- Comparison: key=value. Operators: = (or :), !=, , >=, EXISTS, NOT EXISTS. , >= compare numerically.
- Exact = is case-sensitive. A * anywhere in the value makes it a case-insensitive CONTAINS match that can never be anchored (span_name=gorm.* also matches mygorm.Query). To anchor, use a regex: span_name=/^gorm\./. Regex works on = and != only.
- Quote values containing spaces or = > 500ms | service_name=api any_span(span_name=gorm.Query AND duration>1s) | visited-url=*checkout*
LOG SEARCH:
A bare term searches the log message (graphql request → message="*graphql request*"). Every other field is an attribute. Common autoinjected attributes: level, service_name, service_version, environment, source, secure_session_id, trace_id, span_id, code.filepath, code.function, host.name. secure_session_id EXISTS keeps only logs tied to a session.
- **get-sdk-active**: Check whether any SDKs have been active in a given environment. Returns true if any SDK has initialized or sent events in the environment. Use this to verify that an environment is actually in use before cleanup. Optionally filter by sdkName or sdkWrapperName to check a specific SDK.
- **get-environment**: Get a LaunchDarkly environment's client-side ID and mobile key. Use this to initialize a browser or mobile SDK.
- **get-project**: Get a LaunchDarkly project with its environments. Use to retrieve a project's environments or verify a project exists.
- **create-project**: Create a new LaunchDarkly project. Returns the project with its environments, including each environment's client-side ID and mobile key. Project keys must be lowercase with hyphens, starting with a letter. Production and Test environments are created by default.
- **list-release-policies**: List release policies for a project. Each policy defines preferred release methods and the metrics or metric groups that automatically attach to guarded rollouts when the policy's conditions match (e.g. specific environments or flag tags).

Call this BEFORE recommending metrics for a guarded rollout — some metrics may already be determined by an existing policy, and the user should know what will auto-attach before deciding what else to add.

Also useful when editing a release policy itself: shows the current state of all policies so you understand what's already configured project-wide.

If `warnings` is non-empty, render those warnings to the user and do not describe the affected environments as clean policy rollouts until the policy configuration is fixed.
- **list-metric-events**: List recent event keys received by a LaunchDarkly project — used to check which events are actively flowing before creating a metric. Returns up to 50 event keys with last-seen timestamps. If the event key you need isn't here, it may not be instrumented yet.

Use this BEFORE create-metric to:
1. Confirm the event key exists and is receiving data
2. Discover event keys when the user isn't sure what to use
3. Check the correct spelling of an event key

Supports fuzzy search via `query` to narrow results. Filter by `environmentKey` to check a specific environment.

If the desired event key is absent, surface a warning and ask whether the user wants to instrument the event first or proceed and wire it up later.
- **create-metric**: Create a new metric in a LaunchDarkly project.

KIND (optional, defaults to 'custom') — how the metric collects events:
- 'custom'   → event-driven; agent calls track(eventKey) in code. Requires `eventKey`.
- 'pageview' → fires automatically when a user visits a matching URL. Requires `urls`. No code change needed.
- 'click'    → fires automatically when a user clicks a CSS selector on a matching URL. Requires `urls` &#43; `selector`. No code change needed.

Prefer 'pageview' or 'click' when they fit the user's intent — they require no SDK instrumentation.

URLS (required for kind='pageview' or 'click') — array of URL match rules. The field name carrying the value depends on the matcher `kind`:
- { kind: 'substring',  substring: '/checkout' }  — URL contains this string (most common)
- { kind: 'exact',      url: 'https://example.com/checkout' } — URL must match exactly
- { kind: 'canonical',  url: 'https://example.com/checkout' } — matches the canonical URL
- { kind: 'regex',      pattern: '/checkout/.&#43;' } — full regex pattern

SELECTOR (required for kind='click') — CSS selector that triggers the event, e.g. '.checkout-btn', '#submit'.

EVENT KEY (required for kind='custom') — matches the string passed to track() in code.

MEASURE TYPE (required) — speak the user's language, not the API's:
- 'count'      → total number of times the event occurred (isNumeric: false, unitAggregationType: sum)
- 'occurrence' → whether each user triggered the event at all — conversion/binary (isNumeric: false, unitAggregationType: average)
- 'value'      → a numeric value attached to the event like latency or revenue (isNumeric: true)

SUCCESS CRITERIA (required):
- 'HigherThanBaseline' — more is better (conversion rate, revenue, engagement)
- 'LowerThanBaseline'  — less is better (latency, error rate, bounce rate)

VALUE AGGREGATION (optional, only for measureType='value'):
- 'average' (default) — mean value per user, e.g. average page load time
- 'sum'               — total value per user, e.g. total revenue

UNIT (optional) — human-readable label shown in the UI, e.g. 'ms', 'USD', 'requests'.

RANDOMIZATION UNITS (optional) — context kinds this metric can be randomized by in experiments. Defaults to ['user']. Override if the project uses different context kinds (e.g. ['member', 'account'] on catfood). If creation fails with 'randomization unit not found', call get-project or ask the user for their project's context kinds.

Common templates:
- Page visit:          kind=pageview, urls=[{kind:'substring', substring:'/checkout'}], measureType=occurrence, successCriteria=HigherThanBaseline
- Button click:        kind=click, urls=[{kind:'substring', substring:'/'}], selector='.checkout-btn', measureType=occurrence, successCriteria=HigherThanBaseline
- API latency:         measureType=value, valueAggregation=average, successCriteria=LowerThanBaseline, unit=ms
- Signup conversion:   measureType=occurrence, successCriteria=HigherThanBaseline
- Error count:         measureType=count, successCriteria=LowerThanBaseline
- **get-metric**: Get full details for a single LaunchDarkly metric: measureType, eventKey, successCriteria, unit, description, tags, creation date, and attached flag count. Use after create-metric to verify the result, or to inspect an existing metric before modifying it.
- **list-metrics**: List metrics in a LaunchDarkly project. Returns key, name, measureType (count/occurrence/value), eventKey, successCriteria, tags, and how many flags each metric is attached to.

Sorting: use `sort` with `createdAt` or `name`; prefix with `-` for descending (e.g. `-createdAt` for newest first).

Filtering (uses `field operator value` syntax internally — just pass the values below):
- `query`: fuzzy match on key/name
- `tags`: array of tags (all must match)
- `eventKind`: one of `custom`, `pageview`, `click`
- `isNumeric`: true = value metrics only
- `hasConnections`: true = attached to flags or experiments
- `maintainerIds`: array of member ID strings (use find-members to resolve)
- `maintainerTeamKey`: team key string
- `metricUsedIn`: one of `experiments`, `guarded_rollouts`, `any`, `none`
- `dataSourceKeys`: array of data source key strings

Use before creating a metric to check for duplicates and understand naming conventions.
- **delete-agent-graph**: Permanently delete an agent graph and all of its edges. THIS IS IRREVERSIBLE. Requires confirm=true to execute.
- **update-agent-graph**: Update an agent graph's metadata or structure. All fields are optional. If rootConfigKey or edges are provided, both must be present and will fully replace the existing graph structure. Pass name or description to update metadata only.
- **create-agent-graph**: Create a new agent graph in a project. An agent graph defines a directed graph of AgentControl Configs for multi-agent workflows. Provide a rootConfigKey and edges to define the graph structure, or create the graph with just metadata and add edges later via update-agent-graph. If rootConfigKey or edges are provided, both must be present.
- **get-agent-graph**: Get a specific agent graph by key, including its full edge structure. Each edge connects a source AgentControl Config to a target AgentControl Config with optional handoff data.
- **list-agent-graphs**: List all agent graphs in a project. Returns metadata for each graph including key, name, description, and root config key. Does not include edge data — use get-agent-graph to retrieve full graph structure.
- **invite-members**: Invite one or more people to the LaunchDarkly account by email. Each invitee receives an email invitation to join. Optionally assign a role (reader, writer, admin) — defaults to reader if not specified.
- **find-members**: Search for LaunchDarkly account members and return their IDs. Supports flexible matching:

- `query`: case-insensitive substring match across both email and display name (e.g. 'hartmann', 'anthony', 'hart' all work). Use this for fuzzy/partial lookups.
- `emails`: exact match on one or more full email addresses. Use when you have the precise email and want a guaranteed result.

Returns id, email, displayName, and role for each match. Pass the returned `id` values to tools like list-metrics as `maintainerIds`.
- **get-member-self**: Return the member ID, profile, and team memberships for the currently authenticated user. Use this whenever the user refers to themselves ('my metrics', 'created by me', 'assigned to me') to resolve their member ID before calling tools that require a maintainerId or similar identifier, or to resolve one of their team keys before calling tools that require a maintainerTeamKey. If the member belongs to more than one team, ask which one to use rather than guessing. If the server returns `token_expired`, re-authenticate the Launchdarkly MCP server connection in your MCP client and retry.
- **create-ai-tool**: Create a new AI tool definition in a project. The schema should be a raw JSON Schema object with type, properties, and required fields (e.g. {"type": "object", "properties": {...}}). Do NOT use the OpenAI function calling wrapper format. customParameters is optional application-level metadata that is not sent to the LLM. After creation, attach the tool to a variation using update-agentcontrol-config-variation with the returned version.
- **get-ai-tool**: Get a single AI tool definition including its full schema, version, tags, and customParameters. Use to inspect a tool's parameters before attaching it to an AgentControl Config variation. The returned version is the value to pass in the tools array ({key, version}) when you attach the tool with create-agentcontrol-config-variation or update-agentcontrol-config-variation.
- **list-ai-tools**: List AI tool definitions in a project. Returns each tool's key, description, schema, version, tags, and customParameters. Tools are attached to AgentControl Config variations to give models function-calling capabilities. The returned version is the value to pass in the tools array ({key, version}) when you attach the tool with create-agentcontrol-config-variation or update-agentcontrol-config-variation.
- **update-agentcontrol-config-targets**: Add or remove specific contexts in AgentControl Config individual targeting in one environment. Individual targets override all rules. Kinds: addTargets, removeTargets, clearTargets, replaceTargets. Each instruction and each replaceTargets 'targets' entry takes variationKey: a key from get-agentcontrol-config or a name from get-agentcontrol-config-targeting, e.g. { kind: 'addTargets', variationKey: 'v1-gpt4o', contextKind: 'user', values: ['user-key-1'] }. If approval is required, the response has requiresApproval: true; call create-agentcontrol-config-approval with the returned instructions.
- **update-agentcontrol-config-rollout**: Set the default (fallthrough) rule for an AgentControl Config in one environment. rolloutType 'variation' serves variationKey to all unmatched contexts. rolloutType 'percentage' splits traffic by weights that sum to 100, in any order, e.g. [{ variationKey: 'v1-gpt4o', percent: 80 }, { variationKey: 'v2-claude', percent: 20 }]. A variationKey is a key from get-agentcontrol-config or clone-agentcontrol-config-variation (created.key), or a name from get-agentcontrol-config-targeting. Returns the fallthrough that the API stored and previousFallthrough. If approval is required, the response has requiresApproval: true; call create-agentcontrol-config-approval with the returned instructions.
- **update-agentcontrol-config-targeting**: Change custom targeting rules for an AgentControl Config in one environment. Rules run top to bottom, and the first match wins. Kinds: addRule, removeRule, addClauses, removeClauses, reorderRules, replaceRules, updateRuleDescription, addValuesToClause, removeValuesFromClause, updateClause. Get ruleId and clauseId from get-agentcontrol-config-targeting. Each instruction or replaceRules rule takes variationId or variationKey (a variation key or name), e.g. { kind: 'addRule', variationKey: 'v1-gpt4o', clauses: [{ contextKind: 'user', attribute: 'tier', op: 'in', values: ['premium'], negate: false }] }. If approval is required, the response has requiresApproval: true; call create-agentcontrol-config-approval with the returned instructions.
- **get-agentcontrol-config-targeting**: Read the targeting configuration for an AgentControl Config in a specific environment. Returns variations (with their _id UUIDs and names), individual targets, custom rules, fallthrough (default rule), and off variation. The variation name returned here can be passed as 'variationKey' to update-agentcontrol-config-targeting, update-agentcontrol-config-rollout, and update-agentcontrol-config-targets. Alternatively, use get-agentcontrol-config to obtain the variation's slug key.

Targeting for a config is always on. The variation numbers in targets, rules, fallthrough, and offVariation are indexes into `variations`. To change what a config serves, use update-agentcontrol-config-rollout, update-agentcontrol-config-targeting, or update-agentcontrol-config-targets.
- **clone-agentcontrol-config-variation**: Copy an existing variation. Use update-agentcontrol-config-variation to change it in place. Requires projectKey, configKey, sourceVariationKey, new key, and name. Get sourceVariationKey (key e.g. v1-gpt4o, not _id, or name) from get-agentcontrol-config. Omitted values copy the source. parameters merges freeform JSON keys (e.g. {"temperature":0.7}). {} keeps source parameters. custom replaces its freeform object (e.g. {"endpoint":"https://model.example.com"}). {} clears custom. region: 'us-east-1'. '' clears it. outputFormat accepts JSON Schema, e.g. {"type":"object"}. modelConfigKey: list-agentcontrol-model-configs key (e.g. OpenAI.gpt-4o), not provider model ID. Changing it selects latest unless modelConfigVersion pins an existing version (e.g. 3). outputFormat, skills, and modelConfigVersion need account features. Disabled fields may be ignored or rejected. Agent mode uses instructions. Completion mode uses messages. Returns {configKey,source,created}. Next: update-agentcontrol-config-rollout with variationKey=created.key. Version 1; source unchanged.
- **delete-agentcontrol-config-variation**: Permanently delete an AgentControl Config variation. THIS IS IRREVERSIBLE. Requires confirm=true to execute.
- **update-agentcontrol-config-variation**: Requires projectKey, configKey, variationKey, and a change. Each update saves a new version (3→4). Get variationKey (e.g. v1-gpt4o, not _id) from get-agentcontrol-config. Agent: instructions. Completion: messages. state: archived archives, published restores. Use state instead of a published boolean. Omitted model fields stay. comment describes this version's change; omission clears it. parameters and custom replace whole freeform JSON objects, e.g. {"temperature":0.7} and {"endpoint":"https://model.example.com"}. {} clears them. region: 'us-east-1'; '' clears it. modelConfigKey: list-agentcontrol-model-configs key (e.g. OpenAI.gpt-4o), not provider model ID. Changing it defaults to latest unless modelConfigVersion pins an existing version (e.g. 3). outputFormat accepts JSON Schema, e.g. {"type":"object"}. outputFormat, skills, and modelConfigVersion need account features. Disabled fields may be ignored or rejected. Empty tools, skills, or judges arrays detach them.
- **create-agentcontrol-config-variation**: Create a variation in an existing config from create-agentcontrol-config. Requires projectKey, configKey, key, name, modelConfigKey (e.g. OpenAI.gpt-4o), and modelName (e.g. gpt-4o). Get modelConfigKey from list-agentcontrol-model-configs, not the provider model ID. Agent mode requires instructions. Completion mode requires messages. parameters and custom are freeform JSON, e.g. {"temperature":0.7} and {"endpoint":"https://model.example.com"}. region example: 'us-east-1'. outputFormat accepts JSON Schema, e.g. {"type":"object"}. modelConfigVersion pins an existing modelConfigKey version (positive integer, e.g. 3), not a variation version. Omission selects latest. custom defaults to {}. outputFormat, skills, and modelConfigVersion need account features. Disabled fields may be ignored or rejected. Create tools with create-ai-tool, find skills with list-agent-skills, and attach {key,version} entries. comment records the change reason. Verify with get-agentcontrol-config. variation.version is 1, or 2 if tools/skills/judges attached.
- **get-agentcontrol-config-health**: Health check for an AgentControl Config. Returns `health` (healthy, warning, unhealthy), `issues`, per-variation summaries, and four signals: `completeness` (models, prompts, tool references), `targetability` (per environment: targeting on and serving a non-disabled variation), `requestValidity` (outputFormat is valid JSON Schema and modelConfigKey resolves), and `recentInvocation` (per-environment generation successes and errors, last 7 days). Unhealthy when a variation has no model, no environment is targetable, a request validity check fails, or every generation errored in a targetable environment. No generation data is reported as no_data and never makes a config unhealthy. Pass env to check one environment.
- **get-agentcontrol-config-status-envs**: Check an AgentControl Config's lifecycle status across all environments. Returns per-environment state (active, inactive, new, launched) and whether targeting is on, plus a summary of which environments the config is active, inactive, or launched in. Useful for understanding where a config is currently being served before making changes.
- **setup-agentcontrol-config**: Create an AgentControl Config and its first variation in one step, then verify it. Prefer this over create-agentcontrol-config plus create-agentcontrol-config-variation. Returns the config detail with the variation. modelConfigKey comes from list-agentcontrol-model-configs (example: OpenAI.gpt-4o), not the provider model ID. tools takes {key, version} entries. evaluationMetricKey (format: $ld:ai:judge:) is required for judge mode. viewKeys links the config to views (Enterprise).

isInverted (judge mode only): true means a lower judge score is better, false means a higher score is better. Required for custom judges; built-in judge keys can omit it.

MAINTAINER (optional): send maintainerTeamKey (team key, not name) or maintainerId (member ID, example: 507f1f77bcf86cd799439011), not both. Both returns a 400 ("only one of maintainerId or maintainerTeamKey is allowed"). Get both values from get-member-self or find-members. If you omit both, the API can set the caller as the maintainer. The response has `maintainer` {name, email} or `maintainerTeam` {key, name}; the other is null.
- **delete-agentcontrol-config**: Permanently delete an AgentControl Config. THIS IS IRREVERSIBLE. Requires confirm=true to execute.
- **update-agentcontrol-config**: Update an AgentControl Config's name, description, tags, default variation, judge metric, judge success direction (isInverted), or maintainer. Send only the fields to change. For model, prompt, or parameter changes, use update-agentcontrol-config-variation. To remove a config permanently, use delete-agentcontrol-config.

defaultVariationKey (all modes): a variation key from get-agentcontrol-config, not the _id. New environments serve this variation. An unknown key returns a 404.

evaluationMetricKey (judge mode only): format $ld:ai:judge:, for example $ld:ai:judge:quality-v2. Other modes return a 400.

isInverted (judge mode only): true means a lower judge score is better, false means a higher score is better. Required for custom judges; built-in judge keys can omit it. Other modes return a 400.

MAINTAINER (all modes): send maintainerTeamKey or maintainerId, not both. maintainerId is a member ID (example: 507f1f77bcf86cd799439011) from get-member-self or find-members. Send an empty string to remove the maintainer.
- **create-agentcontrol-config**: Create an AgentControl Config shell in a project. Call create-agentcontrol-config-variation next to add a model and prompts. mode: agent (variations use instructions), completion (messages), or judge (messages; scores other configs' outputs). evaluationMetricKey (format: $ld:ai:judge:) is required for judge mode and rejected for other modes. viewKeys links the config to views (Enterprise).

isInverted (judge mode only): true means a lower judge score is better, false means a higher score is better. Required for custom judges; built-in judge keys can omit it.

MAINTAINER (optional): send maintainerTeamKey (team key, not name) or maintainerId (member ID, example: 507f1f77bcf86cd799439011), not both. Both returns a 400 ("only one of maintainerId or maintainerTeamKey is allowed"). Get both values from get-member-self or find-members. If you omit both, the API can set the caller as the maintainer. The response has `maintainer` {name, email} or `maintainerTeam` {key, name}; the other is null.
- **get-agentcontrol-config**: Requires projectKey, configKey. Find configKey with list-agentcontrol-configs. Returns variation keys (e.g. v1-gpt4o, not _id) for update-agentcontrol-config-variation or clone-agentcontrol-config-variation. region (e.g. us-east-1) and freeform JSON custom (e.g. {"endpoint":"https://model.example.com"}) appear directly on variations. modelConfigVersion pins model config version (e.g. 3), not variation version (updates add 1). outputFormat is JSON Schema. Absent fields remain absent. Judge configs: evaluationMetricKey, isInverted. Returns maintainer or maintainerTeam.
- **list-agentcontrol-configs**: Search AgentControl Configs in a project. Returns key, name, mode, tags, variation count, and `usedInGraphs` (graph keys that use the config; empty means orphaned, omitted means not loaded). Filters combine with AND: query, tags, view, modes (agent, completion, judge), maintainerId (example: 507f1f77bcf86cd799439011, from get-member-self or find-members), maintainerTeamKey. The two maintainer filters match either. sort: creationDate, lastModified, or name; prefix - for descending. Next page: offset &#43; limit.

An AgentControl Config is not a feature flag. Flag actions do not apply to configs. A config has no on/off switch. Use the AgentControl tools, not the flag tools, to read or change a config.
- **apply-agentcontrol-config-approval**: Apply an already-approved AgentControl Config approval request. This executes the changes that were approved by reviewers. Only works on requests with reviewStatus 'approved'. Does NOT approve requests: that must be done by a human reviewer. Equivalent to apply-approval-request but scoped semantically to AgentControl Configs.
- **list-agentcontrol-config-approvals**: List approval requests for an AgentControl Config. Shows status, review state, and who requested each change. Omit env (or pass '*') to list project-scoped variation approval requests; pass a specific env key to filter to targeting-change requests for that environment. Use to check on approval progress after creating a request.
- **create-agentcontrol-config-approval**: Create an approval request for an AgentControl Config change. Use this for variation-level edits (model, prompts, parameters, tools via instructions like updateAIConfigVariation, createAIConfigVariation, deleteAIConfigVariation) as well as targeting changes (see update-agentcontrol-config-targeting, update-agentcontrol-config-rollout, update-agentcontrol-config-targets). Omit env (or pass '*') for variation-level changes — they are project-scoped, not env-scoped. Pass a specific env key for targeting changes. The request is reviewed by approvers before taking effect. Requires at least one reviewer: notifyMemberIds and/or notifyTeamKeys. If the user named a person, resolve them with find-members and pass the returned id. If they did not name anyone, ask who should review before calling this tool. Does NOT approve the request: a human reviewer must do that. Once approved, use apply-approval-request to execute the change.
- **apply-approval-request**: Apply an already-approved flag or segment approval request. This executes the changes that were approved by reviewers. Pass flagKey for a flag or segmentKey for a segment, never both. Only works on requests with reviewStatus 'approved'. Does NOT approve requests: that must be done by a human reviewer. Use list-approval-requests to get the request id.
- **list-approval-requests**: List approval requests for a flag or a segment in an environment. Pass flagKey for a flag or segmentKey for a segment, never both. Shows status, review state, and who requested the change. Use to check on approval progress after creating a request.
- **create-approval-request**: Create an approval request for a flag or segment change in an environment that requires approvals. Pass flagKey for a flag or segmentKey for a segment, never both. Requires at least one reviewer: notifyMemberIds and/or notifyTeamKeys. If the user named a person, resolve them with find-members and pass the returned id. If they did not name anyone, ask who should review before calling this tool. Provide the same semantic patch instructions you would use for a direct change. Segment instructions are the kinds update-segment-rules and update-segment-targets accept. To add or remove values on an existing rule clause, use addValuesToClause or removeValuesFromClause with ruleId, clauseId (the `_id` values from get-flag) and values, or updateClause with ruleId, clauseId and clause; never removeClauses &#43; addClauses to change a clause's values. The request will be reviewed by approvers before taking effect. Does NOT approve the request: that must be done by a human reviewer.
- **check-removal-readiness**: Detailed safety check before removing a feature flag. Checks dependencies, code references, active targeting, expiring targets, and cross-environment status. Returns a readiness verdict: 'safe' (proceed), 'caution' (review warnings), or 'blocked' (must resolve blockers first). Always run this before archive-flag or delete-flag.

Also returns recommendedValue: the actual variation value to hardcode at call sites when the flag is safe to remove (e.g. true, false, 'blue', 11). Computed from the flag's current deterministic configuration. null when serving is non-deterministic (active rules, rollout splits, individual targets, or prerequisites). For cross-environment consensus on the recommended value, use check-flag-rollout-complete.
- **manage-expiring-targets**: List, add, update, or remove expiring targets on a flag. Expiring targets are automatically removed from targeting after a specified date. Dates are shown as ISO strings with days-until-expiry computed. Variation IDs are resolved to human-readable names.
- **delete-flag**: Permanently delete a feature flag. THIS IS IRREVERSIBLE. Requires confirm=true to execute. Always call check-removal-readiness first and only delete if it returns 'safe'. Prefer archive-flag (reversible) when possible.
- **archive-flag**: Archive a feature flag (reversible). This is a soft-delete that can be undone. Recommended as the first step before permanent deletion. Always run check-removal-readiness before archiving.
- **copy-flag-config**: Copy a flag's targeting configuration from one environment to another. Common use: promote from staging to production. Optionally select which aspects to copy: targeting, rules, offVariation, prerequisites, on state. If the target environment requires approval, the response includes requiresApproval: true and an approvalUrl; follow the approvalUrl to submit the copy request for review.
- **update-prerequisites**: Add or remove prerequisites for a flag in a specific environment. Prerequisites are other flags that must evaluate to specific variations before this flag is evaluated. Use addPrerequisite to migrate prerequisites onto a new flag, or removePrerequisite &#43; addPrerequisite to update dependent flags to point to a new key. If the environment requires approval, the response includes requiresApproval: true and the attempted instructions; call `create-approval-request` with the returned instructions to submit it for review.
- **update-individual-targets**: Add or remove specific users or contexts from individual flag targeting. Individual targets are the highest priority: they override all rules. Supported instruction kinds: addTargets, removeTargets, replaceTargets. To target non-user context kinds (e.g. organization), include contextKind on the instruction (e.g. { kind: 'addTargets', contextKind: 'organization', values: ['org-123'], variationId: '' }). Note: addContextTargets and removeContextTargets are NOT supported by the LD API; use addTargets/removeTargets with contextKind instead. Responses truncate long lists. If the environment requires approval, the response includes requiresApproval: true and the attempted instructions; call `create-approval-request` with the returned instructions to submit it for review.
- **update-targeting-rules**: Add, remove, or modify custom targeting rules for a flag in an environment. Rules evaluate top-to-bottom; first matching rule wins. Use get-flag to look up rule _ids, clause _ids, and variation _ids before constructing instructions.

Supported instruction kinds and required fields:
- addRule: clauses (required), variationId or rolloutWeights (one required).   Example — serve On to @launchdarkly.com users:   {"kind":"addRule","clauses":[{"contextKind":"user","attribute":"email","op":"endsWith","values":["@launchdarkly.com"]}],"variationId":""}
- removeRule: ruleId (required, from get-flag).
- updateRuleVariationOrRollout: ruleId and variationId or rolloutWeights.
- addClauses: ruleId and clauses (required).
- removeClauses: ruleId and clauseIds (required).
- addValuesToClause: ruleId, clauseId, and values (required). Adds values to an existing clause in place.   For "add X to the rule" use this, NOT removeClauses &#43; addClauses (which rewrites the whole clause and makes the change impossible to review).   Example: {"kind":"addValuesToClause","ruleId":"","clauseId":"","values":["beta_testers"]}
- removeValuesFromClause: ruleId, clauseId, and values (required). Removes values from an existing clause in place.
- updateClause: ruleId, clauseId, and clause (required). Replaces the whole clause; use only to change attribute, op, contextKind, or negate, not to add or remove values.   Example: {"kind":"updateClause","ruleId":"","clauseId":"","clause":{"contextKind":"user","attribute":"os","op":"semVerLessThan","values":["0.30.0"]}}
- reorderRules: ruleIds — complete ordered list of all rule _ids.
- **update-off-variation**: Set the variation a flag serves when its targeting is OFF, in one environment (env), several (envs), or every environment (allEnvs). One call repairs a whole flag: fallthroughVariationIndex also sets the default rule (what an ON flag serves when no rule matches), and updateFlagDefaults also sets the flag-level defaults that seed new environments (offVariation = variationIndex, onVariation = fallthroughVariationIndex). Each variationIndex is a 0-based position in the flag's variations; use get-flag to see them. For boolean flags, 0 = true, 1 = false by convention. Environments that already match are left alone. An environment that requires approval is reported as blocked with the instructions to pass to `create-approval-request`; the other environments still apply.
- **update-rollout**: Change the default rule (fallthrough) for a flag. Set a percentage rollout across variations or serve a single variation to all unmatched users. Weights must sum to 100. Use human-friendly percentages (e.g., 80 for 80%). If the environment requires approval, the response includes requiresApproval: true and the attempted instructions; call `create-approval-request` with the returned instructions to submit it for review.
- **toggle-flag**: Turn a feature flag's targeting on or off in a specific environment. Returns the previous and new state. If the environment requires approval, the response includes requiresApproval: true and the attempted instructions; call `create-approval-request` with the returned instructions to submit it for review.
- **update-flag-settings**: Update a flag's top-level settings: name, description, tags, temporary/permanent status, maintainer, default variations, or custom properties. Does NOT modify per-environment targeting, rollouts, or rules — use the dedicated environment-scoped tools instead:
- To turn a flag's targeting ON or OFF in a specific environment: use `toggle-flag`.
- To change what variation is served when targeting is off: use `update-off-variation`.
- To change the fallthrough (default) variation or a percentage rollout: use `update-rollout`.
- To add, remove, or modify targeting rules: use `update-targeting-rules`.

Supported instruction kinds: updateName, updateDescription, addTags, removeTags, markTemporary, markPermanent, updateMaintainerMember, updateMaintainerTeam, addCustomProperties, replaceCustomProperties, removeCustomProperties, updateDefaultVariation. updateMaintainerTeam takes the same Value shape as updateMaintainerMember but with a team key instead of a member id (e.g. { kind: 'updateMaintainerTeam', value: 'team-key' }). Only include a maintainer instruction when the user explicitly asked to change the maintainer — don't reassign it as a side effect of some other requested edit. addCustomProperties adds a new custom property: { kind, key, name, values[] }. replaceCustomProperties replaces an existing custom property's values: { kind, key, name, values[] }. removeCustomProperties removes specific values from a custom property: { kind, key, values[] }. updateDefaultVariation sets the flag-level default on/off variation for new environments. Fields: { kind: 'updateDefaultVariation', OnVariationValue?: , OffVariationValue?:  }. At least one of OnVariationValue or OffVariationValue must be provided. OnVariationValue and OffVariationValue are the actual variation values (e.g. true/false for boolean flags, or the string/number/JSON value for multivariate flags), NOT zero-based indices. Call get-flag first to retrieve current variation values. Example for a boolean flag: { kind: 'updateDefaultVariation', OnVariationValue: true, OffVariationValue: false }.
- **create-flag**: Create a new feature flag in a project. Defaults to a boolean temporary flag. After creation the flag is OFF in all environments: use toggle-flag to enable it. An OFF flag serves `defaults.offVariation` and an ON flag that matches no rule serves `defaults.onVariation`; boolean flags default to OFF serving false.

FLAG KINDS:
- 'boolean' (default): two variations — true/false. Do not pass a `variations` array.
- 'multivariate': custom variations such as strings, numbers, or JSON objects. REQUIRED: provide a `variations` array with at least 2 entries, each with a `value` field. The LaunchDarkly API ignores `kind: 'multivariate'` when no variations are supplied and silently creates a boolean flag instead, so this tool enforces the requirement early. Multivariate flags also REQUIRE `defaults` (LaunchDarkly would otherwise serve the second variation when off): set defaults.offVariation to the 0-based index of the value your code falls back to, so the flag behaves like the code while off and needs no approval to stay that way; defaults.onVariation is the index served when targeting is on. To change them later, call update-off-variation once with allEnvs, fallthroughVariationIndex and updateFlagDefaults.

To satisfy org guardrails that require custom properties (e.g. jira.issues, expiry.date), pass customProperties as a map of { key: { name, value[] } }.

MAINTAINER: set maintainerTeamKey or maintainerId to assign an owner at creation time. Prefer maintainerTeamKey over maintainerId when a suitable team exists — team ownership survives personnel changes better than an individual. Call get-member-self first to resolve the calling user's ID and team memberships; if they belong to more than one team, ask which one should be the maintainer instead of guessing. If the response has needsTeamMaintainer, the flag was not created because this project requires a team maintainer. Ask the user which of the returned teams should own the flag, then retry with maintainerTeamKey. Do not guess, even when only one team is returned. If that response has no teams, the caller belongs to none or the member lookup failed: tell the user why, ask which team should own the flag, and retry with maintainerTeamKey. Do not guess.

VIEWS: pass viewKeys to link the new flag to one or more views at creation time (Views are an Enterprise feature). On accounts without the Views entitlement the API silently ignores viewKeys rather than erroring, so verify the links with get-resource-views if view membership is load-bearing.
- **get-flag-status-across-envs**: Check a flag's lifecycle status across all environments. Returns per-environment state (active, inactive, new, launched) and a summary of which environments the flag is active, inactive, or launched in. Use before cleanup to verify the flag is inactive everywhere.
- **find-stale-flags**: Find feature flags that are candidates for cleanup. Returns a prioritized list of stale flags sorted by staleness (worst first). Categories: inactive_30d (no requests in period), launched_no_changes (fully rolled out, no recent changes), never_requested (created but never evaluated). Defaults to showing temporary flags inactive for 30&#43; days.

ENVIRONMENT OPTIONS (choose one):
- `env`: single environment key (required when useCriticalEnvs is not set)
- `useCriticalEnvs`: auto-discover critical environments from the project's environment config   and use the first critical env for staleness classification

EVALUATION COUNTS:
- `includeEvalCounts`: when true, attaches `evalCounts` (total SDK evaluations per env) to each stale flag   using the batched evaluationSummaries endpoint. NOTE: eval counts are total SDK calls, not unique contexts.
- `evalWindow`: evaluation window in days (default 30)

Optionally filter by maintainer to find stale flags owned by a specific member or team (use get-member-self or find-members to resolve maintainerId), or by `view` to scope the search to flags linked to a view (Views are an Enterprise feature).
- **get-flag-health**: Get combined health view for a single flag: lifecycle state, last-requested timestamp, targeting summary (rules count, targets count, on/off), age, and whether it's temporary. Use this to assess if a flag is stale or needs attention.
- **get-flag**: Get detailed configuration for a single feature flag scoped to a specific environment. Returns the full targeting tree including rules, individual targets, fallthrough, prerequisites, and variation details. Each rule and each clause carries an `_id`; pass them as ruleId and clauseId to update-targeting-rules (addValuesToClause, removeValuesFromClause, updateClause) or create-approval-request to edit a clause in place.
- **list-flags**: Search and browse feature flags in a project. Returns a paginated list scoped to a single environment.

Filtering:
- `query`: search by flag name or key (case-insensitive)
- `tags`: array of tags (all must match)
- `state`: lifecycle state — `live`, `deprecated`, or `archived`. Defaults to `live`
- `type`: `temporary` or `permanent`
- `maintainerId`: member ID of the flag maintainer (use get-member-self or find-members to resolve)
- `maintainerTeamKey`: team key of the maintaining team
- `sdkAvailability`: one of `client`, `mobile`, `anyClient`, `server`
- `view`: view key — only flags linked to this view (Views are an Enterprise feature)
Sorting: use `sort` with `creationDate` or `name`; prefix with `-` for descending. Defaults to `-creationDate`.

Pagination: responses include `totalCount` and `pageInfo`. `pageInfo.nextOffset` is the value to pass as `offset` on the next call, or `null` when you are on the last page.

## Sources

- [official_vendor_setup](https://launchdarkly.com/docs/fed-docs/home/getting-started/mcp)
- [official_documentation](https://mcp.launchdarkly.com/mcp/launchdarkly/install)

## Setup

Use the interactive setup panel on [the detail page](https://www.mcpfolio.com/servers/launchdarkly-official-mcp) to view instructions for each supported client.