Skip to main content
Glama

group_expenses

Destructive

Group an exact set of recorded expenses for a client, project, trip, job, or other user-named purpose, e.g. 'group my Mexico meals for client Rob' or 'group these for client Rob and create a report'. The user need not know about tags: ExpenseBot resolves the name against existing groups and proposes creating one only when needed. Use exact expenseId values from search_expenses. Existing assignments are preserved by default; set replaceExistingTags:true only for an explicit replacement request. A grounded preview is automatic for every bulk request. First call with confirm omitted/false, show the exact rows, count, totals, proposed group, exclusions and conflicts, then ask for approval. Only after explicit user approval, repeat the same operationId and selection with confirm:true (a premature confirm:true is converted to preview). If the request includes a report, set createReport:true on that confirmed call and use its report result; do not run a separate broader create_report query. For 'without personal expenses' set excludePersonal:true; Personal-tagged and Personal-category rows are removed before preview so their marker is never overwritten. The confirmed operation returns exact report and Bill Client links. Expenses already on another ordinary report are excluded; if none remain, no duplicate report is created and the result links to Reports. Keep the response concise, with no unsolicited tax or substantiation advice; do not call check_compliance, get_report_details or tax/deductibility tools around this workflow unless the user asks. In user-facing prose call the destination a group, not a tag. Treat preview totals as provisional; after confirmation use only the terminal result's exact count, total and currency without reconciling to the preview. A Bill Client URL opens the reviewed billing handoff; it does not mean an invoice was created, sent, or confirmed. Sharing remains a separate share_report action with recipient confirmation.

Input Schema

NameRequiredDescriptionDefault
undoNoUndo a completed grouping within its undo window.
groupNoThe user-named destination group to apply to every eligible selected expense.
statusNoRead operation status using operationId.
confirmNoOmit/false for preview; true only after explicit approval.
selectionNoExact expenses returned by search_expenses and approved for this bounded operation.
operationIdYesStable idempotency key generated once for the preview and reused unchanged.
reportTitleNoOptional title when createReport is true; otherwise ExpenseBot derives one from the group.
createReportNoCreate a report from the exact eligible grouped expenses.
excludedTagsNoExisting groups to exclude before preview and grouping.
approveNewGroupNoTrue only when the preview says a new group is required.
excludePersonalNoExclude Personal-tagged and Personal-category expenses from both grouping and the exact report.
excludedCategoriesNoExpense categories to exclude before preview and grouping.
replaceExistingTagsNoDefault false preserves existing assignments. True only after the user explicitly requests replacement; preview shows existing and proposed tags.

Output Schema

NameRequiredDescriptionDefault
undoNo
groupNo
reportNo
statusYes
messageNo
previewNo
successYes
manifestNo
candidatesNo
exclusionsNo
reportsUrlNo
finalAnswerNo
operationIdNo
confirmationNo
suggestedTagNo
creationStatusNo
responseGuidanceNo
reviewExpensesUrlNo
requiresConfirmationNo
requiresNewGroupApprovalNo

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed2 schema fields changed
    • addedInput schema / properties / selection / properties / items / items / properties / expected / properties / city
      Added value: +{
      +  "description": "Recorded location from the reviewed selection.",
      +  "type": "string"
      +}
    • addedInput schema / properties / selection / properties / items / items / properties / expected / properties / date
      Added value: +{
      +  "description": "Recorded YYYY-MM-DD from the reviewed selection.",
      +  "type": "string"
      +}
  2. Changed1 schema field changed
    • addedInput schema / properties / replaceExistingTags
      Added value: +{
      +  "description": "Default false preserves existing assignments. True only after the user explicitly requests replacement; preview shows existing and proposed tags.",
      +  "type": "boolean"
      +}
  3. Changed1 schema field changed
    • changedOutput schema / (root)
      Previous value: -nullNew value: +{
      +  "additionalProperties": true,
      +  "properties": {
      +    "candidates": {
      +      "items": {
      +        "additionalProperties": true,
      +        "type": "object"
      +      },
      +      "type": "array"
      +    },
      +    "confirmation": {
      +      "additionalProperties": true,
      +      "type": "object"
      +    },
      +    "creationStatus": {
      +      "type": "string"
      +    },
      +    "exclusions": {
      +      "additionalProperties": true,
      +      "type": "object"
      +    },
      +    "finalAnswer": {
      +      "type": "string"
      +    },
      +    "group": {
      +      "additionalProperties": true,
      +      "type": "object"
      +    },
      +    "manifest": {
      +      "additionalProperties": true,
      +      "type": "object"
      +    },
      +    "message": {
      +      "type": "string"
      +    },
      +    "operationId": {
      +      "type": "string"
      +    },
      +    "preview": {
      +      "additionalProperties": true,
      +      "type": "object"
      +    },
      +    "report": {
      +      "additionalProperties": true,
      +      "type": "object"
      +    },
      +    "reportsUrl": {
      +      "type": "string"
      +    },
      +    "requiresConfirmation": {
      +      "type": "boolean"
      +    },
      +    "requiresNewGroupApproval": {
      +      "type": "boolean"
      +    },
      +    "responseGuidance": {
      +      "type": "string"
      +    },
      +    "reviewExpensesUrl": {
      +      "type": "string"
      +    },
      +    "status": {
      +      "type": "string"
      +    },
      +    "success": {
      +      "type": "boolean"
      +    },
      +    "suggestedTag": {
      +      "type": "string"
      +    },
      +    "undo": {
      +      "additionalProperties": true,
      +      "type": "object"
      +    }
      +  },
      +  "required": [
      +    "success",
      +    "status"
      +  ],
      +  "type": "object"
      +}
  4. 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
  5. Changed7 schema fields changed
    • addedInput schema / properties / group / description
      Added value: +"The user-named destination group to apply to every eligible selected expense."
    • addedInput schema / properties / group / properties / kind / description
      Added value: +"How to label the destination in user-facing confirmation text."
    • addedInput schema / properties / reportTitle / description
      Added value: +"Optional title when createReport is true; otherwise ExpenseBot derives one from the group."
    • addedInput schema / properties / selection / description
      Added value: +"Exact expenses returned by search_expenses and approved for this bounded operation."
    • addedInput schema / properties / selection / properties / items / description
      Added value: +"One exact receipt identity per selected expense; never broaden this list after preview."
    • addedInput schema / properties / selection / properties / items / items / properties / expected / description
      Added value: +"Optional current state copied from search results for conflict detection."
    • addedInput schema / properties / selection / properties / items / items / properties / expected / properties / tag / description
      Added value: +"Current group/tag value observed before preview; an empty string means ungrouped."
  6. First observed

TDQS

A4.8/5.0
Behavior5/5

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

Annotations mark it destructive and open-world; the description goes well beyond them by disclosing the mandatory preview, the premature-confirm downgrade, operationId idempotency reuse, conflict/exclusion handling, preservation of existing assignments, and that a Bill Client URL is not an invoice. That is unusually rich mutation context.

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?

Purpose and the preview/confirm rule are front-loaded and there are no filler sentences, but the block runs long and packs many rules into dense prose. Almost every sentence earns its place; the size is justified by the tool's complexity but hurts scannability.

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 13-parameter, nested-object, destructive bulk tool with an output schema, the description covers the workflow, safety gates, exclusion behavior, report creation and what the returned links mean. 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.

Parameters4/5

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

Schema coverage is 100%, so the schema already documents each parameter; the description adds cross-parameter workflow meaning instead of repeating field text — confirm only after approval, reuse the same operationId, set createReport on the confirmed call, excludePersonal semantics. It stops short of explaining undo/status/approveNewGroup interplay, so not a 5.

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 (group) and resource (an exact set of recorded expenses) plus the user-named destination kinds, with concrete examples. It also names the sibling it depends on (search_expenses) and the one it replaces (create_report), so an agent can distinguish it without opening schemas.

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?

Explicitly says when to use it, when not to call adjacent tools ('do not call check_compliance, get_report_details or tax/deductibility tools'), and that a separate create_report must not be run. The preview-then-confirm workflow and the replaceExistingTags condition are stated outright.

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.