Skip to main content
Glama

update_expense

Destructive

Update a single existing expense row's category, tag, merchant or business purpose (e.g. 'recategorize expense X to Meals', 'tag it Client – Acme'). Identify it only by the exact expenseId from search_expenses (the full Receipt ID from Column Q); never a date, displayed number or sheet row number. Two-phase: calls with confirm omitted/false return a current→proposed preview and change nothing; after user confirmation, confirm:true applies it. If the expense is not found, search once for a current exact expenseId; never retry the same stale ID. If a business-purpose update exceeds the Notes capacity, stop and send the user to https://www.expensebot.ai/review-expenses?source=mcp. Only category/tag/merchant/businessPurpose are editable; amounts, dates and notes are not. Does not create or delete rows.

Input Schema

NameRequiredDescriptionDefault
fieldsYesPartial update object. Include one or more of these optional keys; omit every field that should remain unchanged.
confirmNoOmit or false = preview only (no write). Must be exactly true to apply the change.
expenseIdYesExact full Receipt ID from Column Q, returned as expenseId by search_expenses.

Output Schema

NameRequiredDescriptionDefault
dataYes
messageYes
successYes
finalAnswerNo
responseGuidanceNo

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • changedOutput schema / (root)
      Previous value: -nullNew value: +{
      +  "additionalProperties": true,
      +  "properties": {
      +    "data": {
      +      "additionalProperties": true,
      +      "properties": {
      +        "applied": {
      +          "type": "boolean"
      +        },
      +        "diff": {
      +          "items": {
      +            "additionalProperties": true,
      +            "properties": {
      +              "column": {
      +                "type": "string"
      +              },
      +              "columnLetter": {
      +                "type": "string"
      +              },
      +              "field": {
      +                "type": "string"
      +              },
      +              "from": {},
      +              "to": {}
      +            },
      +            "required": [
      +              "field",
      +              "from",
      +              "to"
      +            ],
      +            "type": "object"
      +          },
      +          "type": "array"
      +        },
      +        "dryRun": {
      +          "type": "boolean"
      +        },
      +        "expenseId": {
      +          "type": "string"
      +        },
      +        "preview": {
      +          "type": "boolean"
      +        },
      +        "reviewExpenseUrl": {
      +          "type": "string"
      +        },
      +        "unmapped": {
      +          "items": {
      +            "type": "string"
      +          },
      +          "type": "array"
      +        }
      +      },
      +      "required": [
      +        "applied",
      +        "expenseId",
      +        "diff",
      +        "unmapped"
      +      ],
      +      "type": "object"
      +    },
      +    "finalAnswer": {
      +      "type": "string"
      +    },
      +    "message": {
      +      "type": "string"
      +    },
      +    "responseGuidance": {
      +      "type": "string"
      +    },
      +    "success": {
      +      "type": "boolean"
      +    }
      +  },
      +  "required": [
      +    "success",
      +    "message",
      +    "data"
      +  ],
      +  "type": "object"
      +}
  2. Changed1 schema field changed
    • changedOutput schema / (root)
      Previous value: -{
      -  "additionalProperties": true,
      -  "description": "Standard ExpenseBot tool result envelope. `message` is the human-readable summary the AI cites; `data` is the structured payload (totals, breakdowns, ids, etc.). On failure, `success` is false and `error` carries a code/message/hint triple.",
      -  "properties": {
      -    "data": {
      -      "additionalProperties": true,
      -      "description": "Structured payload. Shape varies per tool — common keys: total, breakdown, comparison, sampleMeta, ids, expenseId, reportId, signupUrl, results.",
      -      "type": "object"
      -    },
      -    "error": {
      -      "additionalProperties": true,
      -      "description": "Present only when success === false.",
      -      "properties": {
      -        "code": {
      -          "type": "string"
      -        },
      -        "hint": {
      -          "type": "string"
      -        },
      -        "message": {
      -          "type": "string"
      -        }
      -      },
      -      "type": "object"
      -    },
      -    "message": {
      -      "description": "Human-readable result text. Always present on success; prefer rendering this verbatim before any further reasoning.",
      -      "type": "string"
      -    },
      -    "sampleMeta": {
      -      "additionalProperties": true,
      -      "description": "Set when the underlying dataset was truncated. isTruncated=true means the agent saw a sample of `sampleCount` of `totalCount` rows; aggregate totals are still accurate.",
      -      "properties": {
      -        "isTruncated": {
      -          "type": "boolean"
      -        },
      -        "sampleCount": {
      -          "type": "integer"
      -        },
      -        "totalCount": {
      -          "type": "integer"
      -        }
      -      },
      -      "type": "object"
      -    },
      -    "success": {
      -      "description": "False on tool errors; check before reading `data`.",
      -      "type": "boolean"
      -    }
      -  },
      -  "type": "object"
      -}New value: +null
  3. First observed

TDQS

A4.8/5.0
Behavior5/5

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

Beyond the destructiveHint/openWorldHint annotations, the description discloses the two-phase preview→confirm contract ('return a current→proposed preview and change nothing'), the not-found recovery rule, the Notes-capacity abort, and the non-editable field set. That is substantial behavioral context an agent could not infer from annotations alone.

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-loaded with the action and editable fields, then layered rules in a logical order with zero filler. It is dense and long for a tool description, but nearly every clause carries an operational constraint rather than restating 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?

For a destructive mutation with nested parameters and an output schema, the description covers identification, preview semantics, confirmation, failure handling, and scope limits — everything needed to invoke it correctly without guessing.

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

Parameters4/5

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

Schema coverage is 100%, so the baseline is 3; the description adds mapping between natural-language intents and the fields object ('recategorize expense X to Meals', 'tag it Client – Acme') and reinforces that expenseId must be the exact Receipt ID, not a row number. It does not add format or validation detail beyond that.

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?

States a specific verb and resource ('Update a single existing expense row') and enumerates exactly which fields are editable (category, tag, merchant, business purpose) with example phrasings. It also draws explicit boundaries against siblings: 'Does not create or delete rows' and routes the agent to search_expenses for the identifier.

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?

Gives strong when/when-not guidance: identify only via exact expenseId from search_expenses, never a date/displayed number/sheet row, and 'If the expense is not found, search once ... never retry the same stale ID.' It also names the fallback path (review-expenses URL) when business-purpose text exceeds Notes capacity.

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.