Skip to main content
Glama

get_transactions

Read-only

Retrieve and filter Copilot Money transactions by date, category, merchant, amount, tag, or location, or look one up by ID. Search merchant text and pull special types like refunds, credits, and duplicates.

Instructions

Reads from the local LevelDB cache, which may lag behind Copilot's server if the macOS app hasn't synced recently. For real-time data use --live-reads with get_transactions_live. Unified transaction retrieval tool. Supports multiple modes: (1) Filter-based: Use period, date range, category, merchant, amount filters. (2) Single lookup: Provide transaction_id to get one transaction. (3) Text search: Use query for free-text merchant search. (4) Special types: Use transaction_type for foreign, refunds, credits, duplicates, hsa_eligible, tagged. (5) Location-based: Use city or lat/lon with radius_km. (6) Tag filter: Use tag to find transactions with a specific tag. Rows are TERSE by default: transaction_id, date, amount, name, category_name, account_id, item_id, pending, excluded, internal_transfer. excluded answers "is this row excluded from spending?" — the raw per-transaction flag OR the row's category being user-excluded, the same union exclude_excluded filters on — so it is true for a row Copilot never stamped individually. It is therefore nearly always false in a default response, since exclude_excluded already removed those rows; it carries information only when you pass exclude_excluded: false. A cache row carries ~30 fields and most callers need a handful, so the rest are excluded unless asked for. PARTIAL list of what that drops, not exhaustive: Plaid metadata (plaid_category_id, plaid_category_strings, plaid_deleted), internal IDs (category_id, recurring_id, goal_id, parent_transaction_id, children_transaction_ids, user_id), enrichment and intelligence fields (normalized_merchant — still the normalized merchant name when requested — intelligence_suggested_category_ids, suggestion_ids, original_name), tag_ids, review state (user_reviewed, user_note, user_changed_type — true only when a human re-typed the row, so do not second-guess its type), location (city, region, country, lat/lon), and flags like is_amazon/from_investment. amazon is worth naming because nothing else hints it exists: on rows Copilot matched to an Amazon order it carries the receipt — {order_id, items: [{id, name, link, price, quantity}], other: {giftWrapping, rewards, savings, shipping, tax}} — so fields: ["default", "amazon"] answers "what was in this order" without an exported CSV. Ask for any of them by name with fields: ["default", "tag_ids"], or take the whole document with fields: ["all"] (or "*"). category_name is always resolved to a human-readable name. compact was removed in v3.0.0 — passing it now raises an error naming this migration.

Input Schema

NameRequiredDescriptionDefault
latNoLatitude for proximity search (use with lon and radius_km)
lonNoLongitude for proximity search (use with lat and radius_km)
tagNoFilter by tag name (e.g. "vacation")
cityNoFilter by city name (partial match)
limitNoMaximum number of results (default: 100)
queryNoFree-text search in merchant/transaction names
fieldsNoReturn only these fields per transaction. Default when omitted: a terse row (transaction_id, date, amount, name, category_name, account_id, item_id, pending, excluded, internal_transfer). Anything else is requestable by name alongside the preset: fields: ["default", "tag_ids"], or "all" / "*" for the whole row. THIS TOOL's own description names what its rows drop — the two modes drop different things, because a live row is not a cache document. The note is user_note in cache mode and user_notes live; either spelling works in either mode, and each mode returns its own. Unknown names are omitted and reported via _field_warning.
offsetNoNumber of results to skip for pagination (default: 0)
periodNoPeriod shorthand: this_month, last_month, last_7_days, last_30_days, last_90_days, ytd, this_year, last_year
regionNoFilter by region/city (case-insensitive substring)
countryNoFilter by country code (e.g., US, CL)
pendingNoFilter by pending status (true for pending only, false for settled only)
categoryNoFilter by category ID from get_categories (exact match, not a name). A parent category's id also returns its subcategories' rows. An id that belongs to no category and to no transaction the call looked at is an error.
end_dateNoEnd date (YYYY-MM-DD)
merchantNoFilter by merchant name (case-insensitive substring)
radius_kmNoSearch radius in kilometers (default: 10)
account_idNoFilter by account ID
max_amountNoMaximum transaction amount
min_amountNoMinimum transaction amount
start_dateNoStart date (YYYY-MM-DD)
transaction_idNoGet a single transaction by ID (ignores other filters, though a `category` value must still be a real id)
exclude_deletedNoExclude deleted transactions marked by Plaid (default: true)
exclude_excludedNoExclude user-excluded transactions (default: true)
transaction_typeNoFilter by special type. Cache-only: foreign (international) and duplicates (potential duplicate transactions, paired among the rows the other filters keep; pass the matching exclude_*: false, e.g. exclude_deleted: false, to bring a hidden copy back). Same rule in cache and live mode (positive amount = money out). refunds: a negative REGULAR row in a spending category; never INCOME, a transfer or uncategorized. credits: a negative REGULAR row whose name has credit/cashback/reward/rebate/bonus and whose category is not income or transfer; may overlap refunds. hsa_eligible: a heuristic, not an eligibility ruling: a positive REGULAR row whose category name has health/medical/pharmac/dental/eye care/vision or whose name has cvs/walgreens/pharmacy/medical/dental/vision/hospital. tagged: has a tag. type_specific_data totals cover all matching rows, not just the returned page.
exclude_transfersNoExclude transfers between accounts and credit card payments (default: true)
exclude_split_parentsNoExclude split-transaction parents (docs with children_transaction_ids). The children already carry the real categorized amounts — returning the parent would double-count the spend. Default: true.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed4 schema fields changedv3.0.0
    • changedInput schema / properties / category / description
      Previous value: -"Filter by category (case-insensitive substring)"New value: +"Filter by category ID from get_categories (exact match, not a name). A parent category's id also returns its subcategories' rows. An id that belongs to no category and to no transaction the call looked at is an error."
    • addedInput schema / properties / fields
      Added value: +{
      +  "description": "Return only these fields per transaction. Default when omitted: a terse row (transaction_id, date, amount, name, category_name, account_id, item_id, pending, excluded, internal_transfer). Anything else is requestable by name alongside the preset: fields: [\"default\", \"tag_ids\"], or \"all\" / \"*\" for the whole row. THIS TOOL's own description names what its rows drop — the two modes drop different things, because a live row is not a cache document. The note is user_note in cache mode and user_notes live; either spelling works in either mode, and each mode returns its own. Unknown names are omitted and reported via _field_warning.",
      +  "items": {
      +    "type": "string"
      +  },
      +  "type": "array"
      +}
    • changedInput schema / properties / transaction_id / description
      Previous value: -"Get a single transaction by ID (ignores other filters)"New value: +"Get a single transaction by ID (ignores other filters, though a `category` value must still be a real id)"
    • changedInput schema / properties / transaction_type / description
      Previous value: -"Filter by special type: foreign (international), refunds, credits (cashback/rewards), duplicates (potential duplicate transactions), hsa_eligible (medical expenses), tagged (has tags)"New value: +"Filter by special type. Cache-only: foreign (international) and duplicates (potential duplicate transactions, paired among the rows the other filters keep; pass the matching exclude_*: false, e.g. exclude_deleted: false, to bring a hidden copy back). Same rule in cache and live mode (positive amount = money out). refunds: a negative REGULAR row in a spending category; never INCOME, a transfer or uncategorized. credits: a negative REGULAR row whose name has credit/cashback/reward/rebate/bonus and whose category is not income or transfer; may overlap refunds. hsa_eligible: a heuristic, not an eligibility ruling: a positive REGULAR row whose category name has health/medical/pharmac/dental/eye care/vision or whose name has cvs/walgreens/pharmacy/medical/dental/vision/hospital. tagged: has a tag. type_specific_data totals cover all matching rows, not just the returned page."
  2. Changed1 schema field changedv2.2.0
    • addedInput schema / properties / exclude_split_parents
      Added value: +{
      +  "default": true,
      +  "description": "Exclude split-transaction parents (docs with children_transaction_ids). The children already carry the real categorized amounts — returning the parent would double-count the spend. Default: true.",
      +  "type": "boolean"
      +}
  3. First observedv2.0.1

TDQS

A4.8/5.0
Behavior5/5

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

Although annotations already declare `readOnlyHint=true`, the description adds substantial behavioral context: cache lag, default terse rows, the approximately 30 dropped fields, how `excluded` behaves, the special `amazon` receipt field, and that `compact` was removed and now raises an error. These are exactly the kind of beyond-annotation details an agent needs.

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?

The description is long, but the complexity and parameter count justify substantial detail. It is front-loaded with the cache-lag caveat and then organized by numbered usage modes, though some field-list prose could be trimmed without losing value.

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 26-parameter read tool with no output schema, the description is complete: it covers cache behavior, alternate live tooling, supported retrieval modes, default return shape, field expansion, and a migration error for `compact`. An agent has enough information to call it correctly.

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 description coverage is 100%, so the schema already documents all 26 parameters thoroughly. The description adds useful meaning beyond the schema by grouping parameters into retrieval modes, explaining the default terse field set, and clarifying the nuanced behavior of `excluded` and field selection. It is not a 5 because much of the parameter-level detail is already present in the schema.

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: reading transactions from a local LevelDB cache. It clearly distinguishes itself from the live sibling by naming `get_transactions_live` and explains that the cache may lag. An agent can tell this is the cached retrieval tool without opening the schema.

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 this tool versus the real-time alternative: use the cache read normally, but use `get_transactions_live` for real-time data. It also enumerates the supported retrieval modes, giving clear context for selecting filters, transaction_id lookup, text search, type filters, location, and tags.

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