Skip to main content
Glama

Costory: Your Finops MCP

update_alert

Update an existing cost alert. Look up alertId via search / list_alerts / get / create_alert. All fields except alertId (and slug) are optional — omit a field to keep the stored value. Most edits (name, description, tagIds, condition, dedup) need nothing else. tagIds replaces the full list: existing IDs from list_tags and/or { name, color? } for new tags; color defaults to #6366F1; missing tags are created. Omit keeps stored tags; [] clears them. Explorer (queries + period) and notification dest are wholesale groups: if you send any field in the group, send the full group, written from scratch exactly as for create_alert — the stored queries from get are not a valid input. Inside the explorer group, omit scopeId to keep the alert's saved scope (send null to clear it); it cannot be sent on its own. scopeId is the same id as list_teams, stored on the alert (read it from get) and not merged into the stored queries. Do not send aggBy: the stored grain is always Day. Setting condition on a legacy threshold alert that has no dedup config succeeds but the response may include warning: pass dedup too (or in a follow-up call) to avoid notifying on every firing evaluation. Sharing is not this tool — use get_object_permissions then set_object_permissions with resourceKind "costAlert". EXAMPLE: rename → { alertId, name: "New name" } EXAMPLE: dest switch to Slack → { alertId, notificationChannel: "SLACK", slackChannelId: "C01ABC" } EXAMPLE: condition change → { alertId, condition: "a > 2000" } EXAMPLE: narrow the monitored series (scope kept) → { alertId, queries: [{ type: "cost", name: "a", metricId: "cost", currency: "USD", filterCel: "cos_provider in ["AWS"]" }], datePreset: "TRAILING_90_DAYS" }

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
toNoExplicit window end (inclusive, YYYY-MM-DD). Use with from instead of datePreset.
fromNoExplicit window start (YYYY-MM-DD). Use with to instead of datePreset.
nameNoDisplay name for the alert.
slugNoOrganization slug. Omit to auto-detect from your account (fails if you belong to multiple orgs).
dedupNoDeduplication config controlling how often a still-firing group notifies. The window is per groupBy value; delivery stays one message listing newly eligible groups. Either CALENDAR (kind: CALENDAR, calendarUnit: WEEK | MONTH) = at most once per current ISO week / calendar month, or ROLLING (kind: ROLLING, windowDays: N) = at most once every N days.
emailsNoEmail addresses (required if EMAIL)
tagIdsNoReplaces the full tag list. Omit to keep stored tags; pass [] to clear. Pass existing tag IDs from `list_tags`, and/or new tag objects `{ name, color? }` (created in the org if missing; color defaults to #6366F1).
alertIdYesAlert ID from search, list_alerts, get, or create_alert.
queriesNoReplaces the monitored series wholesale, and `condition` references these `name`s. Same series objects as the `query` tool `queries` array (cost / metric / usage / externalMetric / formula / budget). Each requires `type` (never omit) and a `name` (prefer short ids like a/b/c); put human labels in `alias`. Write them from scratch: the stored `queries` returned by the `get` tool are a different, read-only shape.
scopeIdNoTeam scope id (list_teams), stored on the alert, not merged into query filters. A change still needs full queries plus period. Omit (with queries+period) to keep the saved scope; null clears it. Do not send scopeId alone.
conditionNoAlerts v3 firing rule: a single boolean expression over the query names (`name` field of each query). Supports arithmetic (+ - * /), comparisons (> >= < <= == !=), logical and/or/not, parentheses, and these window functions: rollingSum(a, N, UNIT) (trailing sum over the last N units, UNIT ∈ DAY|WEEK|MONTH, inclusive of today), weekToDateSum(a) (Monday-to-date), monthToDateSum(a) (1st-of-month-to-date), and timeShift(a, N, UNIT) (value shifted back N units; may wrap a window function). Examples: `a > 1000`, `rollingSum(a, 7, DAY) > 1000`, `(a - timeShift(a, 1, DAY)) / timeShift(a, 1, DAY) > 0.2`, `a > 10000 or rollingSum(a, 7, DAY) > 50000`.
datePresetNoOfficial date preset (same DatePreset as dashboards/reports, e.g. MTD, LAST_MONTH, TRAILING_30_DAYS). Prefer this over hand-computed from/to when a preset matches. Mutually exclusive with from/to.
descriptionNoAlert description.
slackChannelIdNoSlack target id (required if SLACK): a channel id (C…) to post to a channel, or a Slack user id (U…) to deliver a direct message to that user. Use list_available_destinations to discover both channels and the signed-in user's DM.
teamsChannelIdNoTeams channel ID (required if TEAMS)
notificationChannelNoNotification channel

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • changedInput schema / properties / scopeId / description
      Previous value: -"Saved team scope id (from list_teams). Changing it still requires complete queries plus period. Omit (with queries+period) to keep the saved scope; send null to clear. Do not send scopeId alone."New value: +"Team scope id (list_teams), stored on the alert, not merged into query filters. A change still needs full queries plus period. Omit (with queries+period) to keep the saved scope; null clears it. Do not send scopeId alone."
  2. Added

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare the safety profile (readOnlyHint=false, destructiveHint=false, openWorldHint=false); the description adds far more — replace-vs-omit semantics for tagIds, wholesale group replacement for queries+period and notification dest, the `[]` clearing sentinel, the legacy-threshold `warning` on condition edits, and the constraint that aggBy must not be sent. That covers destructive/irreversible effects the annotations do not.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the core rule in two sentences, then the highest-risk semantics, then examples. Dense and mostly load-bearing, but a few statements (e.g. tagIds behavior) restate the schema verbatim, making it longer than strictly necessary for an agent that already reads the schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With 16 parameters, one required, no output schema, and heavy cross-field coupling, this is exactly the complexity band where a rich description is required. It covers discovery of alertId, optionality, group replacement, sentinels, the legacy-alert warning, and the out-of-scope sharing workflow — nothing an agent needs to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Despite 100% schema coverage, the description adds meaning the schema cannot express: group atomicity for explorer/notification fields, omit-vs-null distinctions for scopeId, scopeId being stored separately rather than merged into query filters, and the warning that stored queries from `get` are not valid input. This is genuinely additive, not restatement.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb+resource ('Update an existing cost alert') and immediately disambiguates from siblings by naming the lookup tools (search / list_alerts / get / create_alert) that supply alertId. The reader knows this is a partial-update mutation on the cost-alert object, distinct from create_alert and archive_object.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit when-to-use rules ('omit a field to keep the stored value', 'most edits need nothing else'), explicit when-not ('Sharing is not this tool — use get_object_permissions then set_object_permissions with resourceKind "costAlert"'), and named alternatives for tag and scope discovery (list_tags, list_teams). Four worked examples map intent to payload.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources