Hundo
Server Details
Read your accounts, budgets and net worth, and draft changes you confirm.
- Status
- Healthy
- OAuth
- Works in Glama
- Last Tested
- Transport
- Streamable HTTP
- URL
TDQS
Scored across 21 tools
Each tool has a clearly distinct purpose: get_* for reads, propose_* for creating proposals of different kinds (transaction, asset trade, asset convert, budget, transfer, saved insight), and confirm_proposal/list_pending_proposals for proposal lifecycle. Overlap between propose_asset_trade and propose_asset_convert is minimal and clearly explained (trade is buy/sell, convert is swap without cash). run_read_query vs run_insight_query are distinct (raw SQL vs analytics). No two tools appear to do the same thing.
All tool names follow a consistent verb_noun snake_case pattern: get_* for data retrieval, propose_* for proposal creation, confirm_proposal, list_pending_proposals, run_* for queries. This makes the tool surface predictable and easy for an agent to navigate.
With 21 tools, the set is on the heavier side (per calibration, 16-25 is 'heavy'), but the server covers a broad personal-finance domain: accounts, assets, budgets, categories, IOUs, net worth, insights, transactions, transfers, and proposals. Each tool addresses a distinct concern, so the count feels justified rather than bloated. A slight trim might be possible (e.g., merging some propose_* variants), but the scope is coherent.
The surface covers core lifecycle operations: transactions (create/edit/delete via propose_transaction, propose_transaction_edit, propose_delete_transaction), assets (trade/convert), budgets (upsert/delete), transfers, and saved insights (propose/run). Minor gaps exist: there is no tool to edit or delete an asset trade or transfer, and IOU management (while visible via get_ious) has no dedicated propose tool—users must go to the app UI for those. These are workarounds rather than dead ends, so the set is largely complete.
Available Tools
21 toolsconfirm_proposalADestructiveInspect
Commit a pending proposal (created by a propose_* tool) to the user's finances. In this MCP context this is the ONLY way a proposal is recorded - there is no Hundo UI button. Call this with the proposalId returned by a propose_* tool (or from list_pending_proposals) once the user has approved the change in the conversation. Only call after the user has explicitly approved this exact proposal.
| Name | Required | Description | Default |
|---|---|---|---|
| proposalId | Yes | The proposal id to confirm. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already convey mutating/destructive intent. The description adds that this is the only recording path in the MCP context (no UI button) and that the proposal must be approved first. It could state whether the action is reversible or what happens to the pending proposal, but the destructiveHint reduces that burden.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with a specific verb and object, then operational details. The 'only after explicit approval' warning is included in the correct final position without padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the effect, the input source, the sole-path context, and the approval precondition. It does not describe what happens after commit or whether it is reversible, but the destructiveHint annotation and minimal parameter surface make this adequate.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with a brief description of 'proposal id'. The description adds meaningful provenance — the id must come from a propose_* tool or list_pending_proposals and must have been explicitly user-approved — which goes beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the action ('commit a pending proposal to the user's finances') and distinguishes it from the propose_* tools that create pending proposals. It is explicit that this is the only way a proposal gets recorded, with no UI alternative.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit invocation conditions: use the proposalId returned by a propose_* tool or list_pending_proposals, and only call after the user has explicitly approved that exact proposal. This is strong when-to-use guidance with a clear prohibition.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_accountsARead-onlyInspect
List the user's financial accounts. Use this to resolve an account name mentioned in an email (e.g., 'BCA ***1234') to an accountId before calling propose- tools. If no confident match, omit accountId on the proposal — the user will pick on review.
| Name | Required | Description | Default |
|---|---|---|---|
| nameLike | No | Optional case-insensitive substring filter on account name (e.g., 'bca', 'robinhood', 'visa'). Omit to list all accounts. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The readOnlyHint annotation already covers safety. The description adds useful workflow behavior (resolving to accountId and handling no-match cases) but does not disclose output format, pagination, or potential response limits. It does not contradict annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no wasted words. The first sentence states purpose; the second gives workflow context and a conditional fallback. Well structured and front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only list tool with a single filter parameter and no output schema, the description covers the key agent workflow. It implies that results contain accountId, but does not explicitly enumerate fields; still adequate for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, and the schema already documents nameLike as a case-insensitive substring filter. The description reinforces its use (resolving account names) but does not add meaning beyond the schema. Baseline is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a clear verb and resource (List financial accounts) and a specific intended use case (resolving account names to accountId). Differentiates from sibling read-only tools by the resource type and the explicit proposal workflow context.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete when-to-use guidance (before calling propose-* tools) and a decision rule for ambiguous matches (omit accountId if no confident match). Does not explicitly contrast with sibling read-only tools, but the workflow context is sufficient for an agent to select it appropriately.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_assetsARead-onlyInspect
List the user's assets (crypto, stocks, real estate, vehicles, etc.) with quantity, purchase price, latest market valuation, and P&L — the same numbers the app's net-worth page shows. costBasis, pnl, realizedPnl, and avgCostPerUnit are in the user's base currency; costBasis is the blended total cost (per-trade history included) and avgCostPerUnit is costBasis/quantity — use avgCostPerUnit for any 'average cost per share' question, NOT purchasePrice (which is only the fallback for units without recorded trades). purchasePrice and latestValuation.value are per-unit in the asset's own currency. All monetary fields are in major units. pnl is null only when no market price/valuation or exchange rate is available for the asset.
| Name | Required | Description | Default |
|---|---|---|---|
| type | No | Filter by asset type. Omit to return all. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes well beyond the readOnlyHint annotation. It explains monetary units, per-unit vs. blended totals, the relationship between costBasis and avgCostPerUnit, the fallback meaning of purchasePrice, and the exact condition under which pnl is null. This meaningfully helps the agent interpret the response.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but every clause earns its place: it front-loads the purpose, then adds high-value monetary-unit and costing clarifications. It does not repeat schema contents or waste tokens.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description carries the burden of explaining what the response will contain and how to interpret it. It covers the key numeric fields, currencies, units, per-unit vs. total quantities, and the pnl null edge case. The single optional input parameter is already fully covered by the schema, making this sufficiently complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The only parameter, type, is already fully documented in the schema with an enum list and description that says to omit it to return all asset types. Since schema_description_coverage is 100%, the description adds no additional parameter-level meaning beyond what the schema already gives, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states a specific verb and resource: it lists the user's assets with quantity, purchase price, valuation, and P&L. It is distinct from the propose_* write tools by nature, though it does not explicitly contrast itself with get_net_worth even though that sibling is close in name and scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context for when to use the tool: when asset-level holdings and performance numbers are needed, and it notes the optional type filter. It does not explicitly explain when to prefer get_net_worth or when to avoid this tool, but the intended use is strongly implied by the detailed field guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_budgetARead-onlyInspect
Get the user's budgets for a specific month, with budgeted/spent/remaining for each. Use for questions about budget status, overspending, or remaining budget balances. Month must be 'YYYY-MM'.
| Name | Required | Description | Default |
|---|---|---|---|
| month | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations provide readOnlyHint=true, and the description adds value beyond that by specifying the output structure (budgeted/spent/remaining per budget) and the required month format. It does not cover edge cases like empty months or pagination, but for a simple read-only tool this is adequate and does not contradict annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise—two sentences that front-load the purpose and output, then state the usage context and format constraint. No wasted words, and every sentence contributes necessary information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter, read-only tool without an output schema, the description is complete: it states what it returns (budgeted/spent/remaining per budget), the required month format, and the use case. There is no missing information an agent needs to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must compensate. It does so by explaining the month format in human terms ('Month must be 'YYYY-MM'') and implying its purpose ('for a specific month'). The pattern in the schema is reiterated, but the description adds clarity for an agent. While it could elaborate on default behavior, it sufficiently clarifies the single parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states a specific action (get budgets) with a clear resource (user's budgets) and scope (specific month). It also mentions the output fields (budgeted/spent/remaining), making it unambiguous. Although it doesn't name a sibling, no sibling performs a similar read of budgets, so differentiation is inherent.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use this tool: 'for questions about budget status, overspending, or remaining budget balances.' This gives clear context for selection. It does not mention alternatives or when not to use it, but given that no other sibling serves this exact purpose, the guidance is sufficient.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_categoriesARead-onlyInspect
List the user's transaction categories. Use this to resolve a category mentioned by the user to a categoryId before proposing a transaction or asset trade. If there is no confident match, omit categoryId. If the result is truncated, call again with a more specific nameLike.
| Name | Required | Description | Default |
|---|---|---|---|
| nameLike | No | Optional case-insensitive substring filter on category name. Omit to list all categories. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=true, and the description adds useful behavioral context: truncation handling, the confidence-based omission rule, and the implication that results include categoryId/name pairs. It doesn't fully specify return shape, but the description still adds meaningful detail beyond the annotation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, each carrying essential information: the core action, the matching/omission rule, and the truncation retry rule. The purpose is front-loaded and there is no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only tool with one optional parameter and no output schema, the description covers the main scenarios: normal listing, ambiguous category matching, and truncated results. The reference to categoryId gives enough contract clarity for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already fully documents nameLike as an optional case-insensitive substring filter with 100% coverage, so the baseline is 3. The description adds practical guidance by tying nameLike to the truncation retry strategy, which gives the parameter more operational meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'List the user's transaction categories'. It also clarifies the tool's role in resolving a category to categoryId before proposing transactions or asset trades, distinguishing it from sibling get_* tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly says when to use the tool: before proposing a transaction or asset trade, to resolve a category mentioned by the user. It also provides clear fallback instructions: omit categoryId if there is no confident match, and re-call with a more specific nameLike if results are truncated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_iousARead-onlyInspect
Get the user's IOU/debt ledger: who owes the user and whom the user owes, across all counterparties (or one, via counterpartyId). Each entry is a single transfer against a per-counterparty virtual account, labeled with a direction — 'lend' (user gave money, receivable grows), 'collect' (user was paid back, receivable shrinks), 'borrow' (user received money, payable grows), or 'settle' (user paid back, payable shrinks). virtualAccount.type is 'receivable' (they owe the user) or 'payable' (the user owes them); virtualAccount.currency is the debt's currency. amount is in major units. Use this for any question about who owes whom, outstanding debts, or IOU history — this data is not visible via run_read_query.
| Name | Required | Description | Default |
|---|---|---|---|
| counterpartyId | No | Filter to a single counterparty by id (resolve a name to an id via run_read_query against the counterparty table first). Omit to return the ledger for every counterparty. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With readOnlyHint=true present, the description adds context about the virtual account types, currency handling, and the effect of each direction on receivable/payable, which is valuable. It does not overdo it; a 4 is justified because it goes beyond the annotation without contradicting it.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a few sentences but packed with essential information about directions and virtual accounts; it is somewhat long but every part adds value. Front-loads the core purpose well.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given there is no output schema, the description explains the return structure (directions, virtualAccount fields) indirectly, but doesn't explicitly state that it returns a list or how amount is formatted beyond major units. It is fairly complete for a simple tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the description elaborates on the single parameter, explaining the filtering behavior and how to resolve names, adding significant meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the purpose: retrieving an IOU/debt ledger, specifying the directional labels and virtual account fields. It also distinguishes itself from run_read_query, though no sibling has 'get_iou' in its name.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly says to use for questions about who owes whom, outstanding debts, or IOU history, and notes that this data is not visible via run_read_query. It also explains the optional counterpartyId filter and how to resolve names via run_read_query.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_net_worthARead-onlyInspect
Get the user's current net worth in their base currency, with a breakdown by account and asset. Each asset also carries costBasis, pnl (both in the base currency, major units), and pnlPercent - the same numbers the net-worth page shows. Use this for any question about total wealth, total assets, total liabilities, or how rich/poor the user is.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, so the read-only nature is covered. The description adds value by explaining the return structure (breakdown by account and asset, including costBasis, pnl, pnlPercent) and clarifying that it mirrors the net-worth page. This is context beyond what annotations provide, though it does not address optional details like pagination or specific data freshness.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with no filler. The first sentence delivers the core function and output details, and the second provides explicit usage guidance. It is front-loaded and every word earns its place, making it an excellent example of efficient tool documentation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity (no parameters, no output schema), the description fully covers what an agent needs: what it returns, the data breakdown, and when to use it. It also pre-empts common questions about currency and the comparison to the net-worth page. There is no missing information that would hinder a correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so there is nothing for the description to add beyond what the schema implies. With no parameters, the baseline is 4, and the description does not need to compensate for missing param docs. The description does not over-explain or introduce ambiguity.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool returns the user's current net worth in their base currency, with a breakdown by account and asset, and specifies the included fields (costBasis, pnl, pnlPercent). This distinguishes it from siblings like get_accounts and get_assets, which would provide individual account or asset data rather than an aggregated net worth.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly directs use: 'Use this for any question about total wealth, total assets, total liabilities, or how rich/poor the user is.' This is clear and actionable. It does not explicitly compare to alternatives or state when NOT to use it, but the guidance is specific enough to route the agent correctly for net-worth queries.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_saved_insightsARead-onlyInspect
List the user's pinned dashboard insights (Saved Insights tab): id, title, viz spec, and sort order. Does not recompute current data for each one - pass an insight's spec to run_insight_query if you need fresh numbers. Use this to see what's already pinned before proposing a new one, or to find an insight's id/spec to edit or rerun.
| Name | Required | Description | Default |
|---|---|---|---|
| id | No | Optional saved insight id to fetch a single pinned insight. Omit to list all of the user's pinned dashboard insights. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=true, and the description adds behavioral context beyond that: it states the tool does not recompute current data, which is a meaningful behavioral trait. It also implies the return includes a viz spec that can be passed to run_insight_query. The description doesn't contradict annotations. A small gap: it doesn't mention pagination or ordering, but the description already adds value beyond the annotation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences, each earning its place: the first states the core function and return fields, the second clarifies a key behavioral distinction, and the third gives concrete use cases. It is front-loaded with the most important information and has no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only list tool with one optional parameter and no output schema, the description is nearly complete. It covers what the tool returns, what it doesn't do, and when to use it. The only minor gap is that it doesn't describe the exact structure of the 'viz spec' field, but that is likely documented elsewhere or self-explanatory given the sibling tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 the single optional 'id' parameter. The description adds context by explaining the parameter's purpose ('fetch a single pinned insight') and the omission behavior ('Omit to list all'), which goes slightly beyond the schema's description. This is a good complement to the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('List'), a specific resource ('the user's pinned dashboard insights'), and the exact fields returned (id, title, viz spec, sort order). It also distinguishes itself from run_insight_query by explicitly saying it does not recompute current data, which differentiates it from the sibling tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says when to use this tool: 'Use this to see what's already pinned before proposing a new one, or to find an insight's id/spec to edit or rerun.' It also names the alternative (run_insight_query) and the condition for using it ('if you need fresh numbers'). This is clear, actionable guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_yesterday_summaryARead-onlyInspect
Get yesterday's morning briefing: net-worth change, budget alerts (envelopes at >= 80% utilization), and yesterday's transaction/transfer/asset activity, plus a single prioritized headline (insight) summarizing what matters most. All monetary values are in major units. Use this for 'what happened yesterday' / daily-digest style questions instead of composing it from run_read_query - the alert thresholds and headline priority are not simple SQL.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The readOnlyHint annotation already establishes non-destructive behavior, lowering the burden. The description adds useful context: all monetary values are in major units, and it explains why SQL composition is inadequate for the alert/headline logic. It does not disclose potential limitations like latency or pagination, but for a 0-parameter briefing tool, this is sufficient. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single dense paragraph but front-loads the purpose and lists components clearly. It is not overly verbose and every clause adds value (content, units, usage guidance). It loses one point only because a bulleted or more segmented structure might improve scannability, but the prose is efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has no output schema, the description fully specifies the return components: net-worth change, budget alerts (with utilization threshold), transaction/transfer/asset activity, and a prioritized headline. It also states the unit of monetary values and provides usage context. An agent can invoke and interpret the result correctly without further detail.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema is empty (0 parameters), so the baseline is 4. The description correctly avoids inventing parameters and instead clarifies the return payload, which is the meaningful semantic content an agent needs. No additional parameter explanation is necessary.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Get') and resource ('yesterday's morning briefing') and enumerates the exact contents (net-worth change, budget alerts, activity, headline). It also explicitly contrasts with run_read_query, distinguishing itself from the most likely sibling and preempting confusion. This is unambiguous and differentiated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly instructs to use this tool for 'what happened yesterday' / daily-digest style questions and tells the agent to use it 'instead of composing it from run_read_query', with a reason (alert thresholds and headline priority are not simple SQL). This is a clear when-to-use directive that also names the alternative, leaving no ambiguity about selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_pending_proposalsARead-onlyInspect
List your currently-pending proposals (proposals you've made that the user hasn't confirmed or cancelled yet). Use this when the user asks to change one of several pending proposals so you only re-propose the affected one. Returns up to 20 most-recent pending proposals. Amounts in summaries are in MAJOR units — pass them through to the propose tools as-is for relative edits.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, so the read-only nature is known. The description adds valuable behavioral details: 'Returns up to 20 most-recent pending proposals' (pagination/limit) and 'Amounts in summaries are in MAJOR units — pass them through to the propose tools as-is for relative edits' (unit convention and integration guidance). This goes beyond the annotation without contradicting it.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences, front-loaded with the main purpose, then the usage scenario, then the behavioral details. No redundant wording or fluff. Every sentence adds essential information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool is simple (0 params, read-only), the description covers the key aspects: what it returns (list of pending proposals), the limit (20), and the unit convention. It does not describe the full structure of each proposal, but since there is no output schema, it might be slightly incomplete. However, the agent can infer proposal structure from sibling propose tools, so this is adequate.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There are no parameters (0 params, schema coverage 100% vacuously). The baseline for 0-param tools is 4. The description does not need to explain parameters, and it doesn't. It focuses on output and usage, which is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('List') and the resource ('your currently-pending proposals'), and further clarifies what qualifies as pending ('proposals you've made that the user hasn't confirmed or cancelled yet'). This distinguishes it from sibling tools like get_accounts or propose_* by focusing on the specific proposal lifecycle state.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives a concrete usage scenario: 'Use this when the user asks to change one of several pending proposals so you only re-propose the affected one.' This is explicit guidance on when to invoke it. It does not mention when not to use it, but the context is clear enough. Could mention alternatives like confirm_proposal, but the scenario is sufficient.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
propose_asset_convertADestructiveInspect
Propose converting one asset into another (a cashless swap, e.g. spend SOL to acquire a new coin). Records a sell of the source and a buy of the destination at one shared value, moving no cash account. Returns a proposal id; to record it, call the confirm_proposal tool with the returned proposalId after the user approves (there is no UI button or proposal card to click in this context). Validates the user holds enough of the source. Pass the trade value in the user's base currency, or omit it to auto-derive from the source's market price. Always include a short user-supplied description.
MCP note: this tool only CREATES a pending proposal; nothing is recorded until confirm_proposal is called.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | YYYY-MM-DD. | |
| value | No | Trade value in MAJOR units of the user's base currency (the displayed amount, e.g. 850 for $850). This is the value of the source quantity at trade time; it becomes the destination's cost basis. Omit to auto-derive it from the source asset's latest market price. | |
| description | Yes | Short user-supplied description, e.g. 'Swapped SOL for BONK'. | |
| destAssetId | Yes | Id of the asset being acquired (the destination). Must already exist and differ from the source. | |
| destQuantity | Yes | Number of units of the destination asset received. | |
| sourceAssetId | Yes | Id of the asset being spent (the source of the swap). | |
| sourceQuantity | Yes | Number of units of the source asset to spend. | |
| editsProposalId | No | Id of an existing pending proposal to update in place. Pass this when the user asks to modify a proposal you previously made (e.g. 'make it 5 SOL instead'). Look up current ids with listPendingProposals if you're unsure. Omit when proposing something new. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only show readOnlyHint=false and destructiveHint=true. The description adds valuable nuance: the tool 'only CREATES a pending proposal,' does not record anything until confirm_proposal is called, and validates that the user holds enough of the source. This provides meaningful transparency beyond the structured annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is generally well-structured and front-loaded with the primary purpose, followed by operational notes on confirmation, validation, and optional value handling. It is a bit long, and the final 'MCP note' partly duplicates the earlier pending-proposal caveat, but most sentences carry substantive guidance.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an 8-parameter, 6-required tool with no output schema, the description is thorough: it explains the return value, the mandatory follow-up with confirm_proposal, the validation behavior, and the optional value semantics. It gives an agent enough to invoke the tool correctly and understand the consequences in context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents all parameters in detail, including the meaning of 'value' (major units, cost basis, optional auto-derive). The description repeats some of this and adds the 'one shared value' phrasing, but it does not materially compensate for anything missing. It stays at the baseline 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource: 'Propose converting one asset into another' with an example ('spend SOL to acquire a new coin') and states the key distinction from other tools: it is a cashless swap that 'moves no cash account.' This effectively differentiates it from cash-related or transaction-capture siblings without confusion.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly tells the agent the follow-up usage: 'call the confirm_proposal tool with the returned proposalId after the user approves' and explains that there is no UI button to click. It establishes when the tool is appropriate (creating a pending proposal) and explicitly distinguishes creating from recording, but it doesn't name alternative sibling tools or say when to prefer them.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
propose_asset_tradeADestructiveInspect
Propose a buy or sell trade for an asset. Returns a proposal id; to record it, call the confirm_proposal tool with the returned proposalId after the user approves (there is no UI button or proposal card to click in this context). For sells, validates the user holds enough quantity. The cash account currency must match priceCurrency. Always include a short user-supplied description; optionally include a categoryId.
MCP note: this tool only CREATES a pending proposal; nothing is recorded until confirm_proposal is called.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | YYYY-MM-DD. | |
| fees | No | Transaction fees in MAJOR units (e.g. 1.99 for $1.99, 5000 for Rp 5,000). Pass 0 if none. | |
| action | Yes | ||
| assetId | Yes | Id of the asset being traded. | |
| quantity | Yes | Number of units to buy or sell. | |
| categoryId | No | Optional category id to attach to the cash transaction. | |
| description | Yes | Short user-supplied description, e.g. 'DCA into AAPL'. | |
| pricePerUnit | Yes | Per-unit price in MAJOR units (the displayed amount, e.g. 180.25 for $180.25, 3123.98 for Rp 3,123.98). Fractional values are allowed (e.g. 0.000001 for high-supply crypto). The server scales to storage units; never pre-multiply by 100. | |
| cashAccountId | No | Id of the cash account funding or receiving this trade. Omit only in the email-import pipeline when the source email doesn't make it clear which cash account is involved — the user picks one via the Edit button. In chat, always pass a real id. Do not pass an empty string; omit the field entirely instead. | |
| priceCurrency | Yes | 3-letter currency code for the trade price. | |
| editsProposalId | No | Id of an existing pending proposal to update in place. Pass this when the user asks to modify a proposal you previously made (e.g. 'make it $50 instead'). Look up current ids with listPendingProposals if you're unsure. Omit when proposing something new. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations set readOnlyHint=false and destructiveHint=true, but the description adds critical nuance: it only CREATES a pending proposal and nothing is recorded until confirm_proposal is called. This clarifies that the destructiveHint is not about immediate data loss but about a mutating side-effect that remains uncommitted. The validation for sells and the currency-match requirement are also disclosed. This goes beyond what annotations provide and directly addresses a potential misunderstanding, so it fully satisfies this dimension.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two compact paragraphs. The first paragraph front-loads the core purpose, workflow, and key constraints. The second is a helpful MCP note reinforcing the pending nature. There is minor redundancy (the pending-only point appears twice), but overall every sentence earns its place without excessive length. It is well-structured and easy to scan.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 11 parameters and a two-step workflow, the description covers the essential contextual needs: it states the return value (a proposal id), the required follow-up (confirm_proposal), validation behaviors, and currency matching. Since there is no output schema, explicitly saying it returns a proposal id is important. Given the high schema coverage for parameters, the description is sufficiently complete for an agent to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 91% schema description coverage, the input schema already documents parameters thoroughly (e.g., pricePerUnit, cashAccountId, fees). The description adds only general guidance ('always include a description', 'optionally include a categoryId') that is already implied by required/optional flags in the schema. It does not add deeper meaning to any parameter beyond what the schema provides, so the baseline 3 is correct.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with an explicit verb and resource: 'Propose a buy or sell trade for an asset.' It clearly distinguishes this from sibling tools like propose_transaction, propose_transfer, and propose_asset_convert by focusing on asset trades. The phrase 'buy or sell trade' is specific and unambiguous, and the mention of returning a proposal id further clarifies its role in a two-step workflow.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description tells the agent when to use this tool (for buy/sell trades of an asset) and explicitly instructs to call confirm_proposal afterward with the returned proposalId. It also provides conditions: validates sell quantity, requires currency match, and mandates a description. However, it does not explicitly contrast with alternatives (e.g., 'use propose_transfer for transfers'), leaving some differentiation to inference. The workflow guidance is strong, so a 4 is appropriate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
propose_budget_upsertADestructiveInspect
Propose creating a new budget or updating an existing one's amount. For create: provide name, allocated, currency. For update: provide envelopeId, allocated; the name and currency are kept from the existing budget. Returns a proposal id; to record it, call the confirm_proposal tool with the returned proposalId after the user approves (there is no UI button or proposal card to click in this context).
MCP note: this tool only CREATES a pending proposal; nothing is recorded until confirm_proposal is called.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Required when creating a new budget. | |
| currency | Yes | ||
| allocated | Yes | Allocation in MAJOR units (the displayed amount, e.g. 500.00 for $500.00, 5000000 for Rp 5,000,000). The server scales to storage units; never pre-multiply by 100. | |
| categoryId | No | ||
| envelopeId | No | Id of an existing budget to update; omit to create a new budget. | |
| editsProposalId | No | Id of an existing pending proposal to update in place. Pass this when the user asks to modify a proposal you previously made (e.g. 'make it $50 instead'). Look up current ids with listPendingProposals if you're unsure. Omit when proposing something new. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (non-read-only, destructive hint), it discloses the critical pending-proposal semantics: the tool only creates a pending proposal and nothing is recorded until confirm_proposal is called. It also clarifies that name and currency are preserved on update, removing ambiguity about how existing budgets behave.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Each sentence earns its place: purpose, field selection by mode, return value, required follow-up, and the pending-proposal warning. The structure is front-loaded and compact with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given six parameters, no output schema, and partial annotations, this is complete enough for correct invocation: the agent knows what to pass, what it returns, and what to do next. The only minor omission is categoryId, but the create path is explicitly specified without it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 67% schema coverage, the description adds important conditional parameter semantics: create requires name, allocated, and currency, while update keeps name/currency from the existing budget. However, categoryId is never explained in either the description or the schema, so a small semantic gap remains.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Propose creating a new budget or updating an existing one's amount.' It clearly differentiates create from update and is readily distinguishable from sibling proposal tools such as propose_delete_budget and confirm_proposal.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit field requirements per mode ('For create: provide name, allocated, currency. For update: provide envelopeId, allocated'), tells the agent to call confirm_proposal with the returned proposalId after approval, and notes there is no UI button/card in this context. It also instructs when to pass editsProposalId and how to look up pending proposals with listPendingProposals.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
propose_delete_budgetADestructiveInspect
Propose deleting an existing budget (envelope). Returns a proposal id; to record it, call the confirm_proposal tool with the returned proposalId after the user approves (there is no UI button or proposal card to click in this context). Look the budget up with the budget tool first and pass its id. Transactions already assigned to the budget are kept — only the budget itself is removed.
MCP note: this tool only CREATES a pending proposal; nothing is recorded until confirm_proposal is called.
| Name | Required | Description | Default |
|---|---|---|---|
| envelopeId | Yes | Id of the budget (envelope) to delete. Look it up with the budget tool before calling. | |
| editsProposalId | No | Id of an existing pending budget-delete proposal to update in place. Pass this when the user retargets a delete you previously proposed. Look up current ids with listPendingProposals if you're unsure. Omit when proposing something new. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark destructiveHint=true, but the description adds valuable nuance: this tool only creates a pending proposal and nothing is recorded until confirm_proposal is called. It also discloses that transactions assigned to the budget are preserved and only the budget itself is removed, giving the agent accurate expectations about side effects and timing.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact despite covering workflow, prerequisites, side effects, and MCP proposal semantics. Each sentence carries distinct operational information, and the most important scoping sentence is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description still tells the agent it gets a proposal id and what to do with it, including the exact confirm_proposal call and user-approval condition. It also covers the lookup prerequisite, transaction preservation, and the pending-proposal nature, making the tool safely invocable.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the input schema already documents both envelopeId and editsProposalId. The description repeats the lookup-before-call guidance and the retarget/omit behavior, but adds little new parameter-level meaning beyond what the schema provides. Baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description begins with a specific verb and resource: 'Propose deleting an existing budget (envelope).' It immediately distinguishes itself from confirm_proposal by stating it returns a proposal id and that a follow-up confirm call is required. It also clarifies that it only creates a pending proposal, separating it from direct deletion or upsert operations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives an explicit precondition: look up the budget with the budget tool first and pass its id. It also says exactly when to call confirm_proposal (after user approval) and why (no UI button or proposal card to click in this context), plus when to omit or pass editsProposalId. This is a complete workflow guide for correct invocation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
propose_delete_transactionADestructiveInspect
Propose deleting an existing income or expense transaction. Returns a proposal id; to record it, call the confirm_proposal tool with the returned proposalId after the user approves (there is no UI button or proposal card to click in this context). Look the target up with the read-query tool first and pass its id. Transfers, buys and sells can't be deleted here — tell the user to delete those on the Transactions page. Neither can IOUs, which are transfers to a virtual receivable/payable account — tell the user to manage those on the IOUs page. The preview states the full effect — relay it to the user before they confirm.
MCP note: this tool only CREATES a pending proposal; nothing is recorded until confirm_proposal is called.
| Name | Required | Description | Default |
|---|---|---|---|
| transactionId | Yes | Id of the transaction to delete. Look it up with the read-query tool (filtering by description/date/amount/etc.) before calling. Must be an income or expense: transfers, buys and sells belong on the Transactions page, and IOUs on the IOUs page. | |
| editsProposalId | No | Id of an existing pending delete proposal to update in place. Pass this when the user retargets a delete you previously proposed (e.g. 'actually delete the other one'). Look up current ids with listPendingProposals if you're unsure. Omit when proposing something new. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses the critical two-phase behavior: this tool only creates a pending proposal and nothing is recorded until confirm_proposal is called. It also reveals there is no UI button/card in this context and instructs the agent to relay the preview before confirmation, which goes well beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but every sentence earns its place: scope, required post-step, exclusions, caller guidance, and the critical MCP note are all packed in with no filler. The core workflow is front-loaded in the first two sentences.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with no output schema and destructive annotations, the description fully covers the proposal lifecycle, return value, next step, exclusions, lookup requirement, preview handling, and environmental caveat. An agent has everything needed to call and complete the flow correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 both parameters thoroughly. The description reinforces the transactionId lookup workflow but does not add materially new parameter-level meaning beyond what the schema provides, matching the high-coverage baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'Propose deleting an existing income or expense transaction.' It also distinguishes itself from confirm_proposal (the recording step) and from proposing transfers, buys, sells, and IOUs, making its scope unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly names sibling alternatives and the conditions that select them: use confirm_proposal to record, direct transfers/buys/sells to the Transactions page, IOUs to the IOUs page, and use read-query first to obtain the target id. No ambiguity remains about when to call this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
propose_saved_insightADestructiveInspect
Propose pinning a filtered insight to the user's Saved Insights tab. Returns a proposal id; to record it, call the confirm_proposal tool with the returned proposalId after the user approves (there is no UI button or proposal card to click in this context).
MCP note: this tool only CREATES a pending proposal; nothing is recorded until confirm_proposal is called.
| Name | Required | Description | Default |
|---|---|---|---|
| spec | Yes | The visualization spec. vizType is one of: 'value' (single number), 'comparison' (template income_vs_expense / period_over_period, or custom A/B), 'chart_time' (bucketed time series), 'breakdown' (top groups by category/envelope/account/type), 'table' (list of N transactions). Always set the filter.period — use relative.value='this_month' / 'last_30_days' etc. unless the user gave explicit dates. | |
| title | Yes | Short user-facing label for the pinned insight, e.g. 'Expenses this month excluding Investment' or 'Dating spending over 6 months'. | |
| editsProposalId | No | Id of an existing pending saved-insight proposal to update in place. Pass this when the user asks to adjust a proposal you previously made (e.g. 'exclude Dining too'). Use listPendingProposals if unsure. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description directly contradicts the annotation destructiveHint: true. The description states 'this tool only CREATES a pending proposal; nothing is recorded until confirm_proposal is called,' implying no destructive side effects. However, destructiveHint: true suggests the tool may modify or delete data. This is a significant inconsistency, as the tool appears to be non-destructive and merely stages a proposal. Therefore, the description fails to align with annotations, meriting a score of 1.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise, with the primary purpose stated in the first sentence. The second sentence explains the required follow-up and the MCP note clarifies the non-destructive nature. Every sentence adds value, and the structure is well-organized with the key action and caveat front-loaded. No superfluous text.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the two-step flow (propose then confirm), the need for user approval, and the lack of a UI button. It does not explain how to construct the complex spec, but the schema's extensive parameter descriptions compensate for that. The output (proposal ID) is mentioned. Overall, the description provides enough context for an agent to use the tool correctly, though it could have elaborated on error handling or the nature of 'pending proposals'.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has 100% description coverage, with detailed descriptions for the spec and title parameters. The tool description adds no additional parameter semantics beyond what the schema already provides. It does mention the return value (proposal ID) but that is not a parameter. Since the schema fully documents parameters, a baseline score of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action: 'Propose pinning a filtered insight to the user's Saved Insights tab.' It identifies the specific resource (Saved Insights) and the outcome (a proposal ID). This distinguishes it from sibling tools like confirm_proposal (which records) and list_pending_proposals (which lists), making the purpose unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit instructions: after calling this tool, the agent must call confirm_proposal with the returned proposalId upon user approval. It also notes that there is no UI button or proposal card to click, eliminating ambiguity about the required follow-up. This clearly tells the agent when and how to use this tool versus the alternative confirm_proposal.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
propose_transactionADestructiveInspect
Propose a new income or expense transaction. Returns a proposal id; to record it, call the confirm_proposal tool with the returned proposalId after the user approves (there is no UI button or proposal card to click in this context). Validate account exists and is owned by the user before calling.
MCP note: this tool only CREATES a pending proposal; nothing is recorded until confirm_proposal is called.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | YYYY-MM-DD. | |
| type | Yes | ||
| amount | Yes | Amount in MAJOR units (the displayed amount, e.g. 12.34 for $12.34, 50000 for Rp 50,000). The server scales to storage units; never pre-multiply by 100. | |
| currency | Yes | 3-letter currency code. May differ from the account's currency; the server records an exchange rate to convert into the account currency. | |
| accountId | No | Id of the financial account. Omit only in the email-import pipeline when the source email is genuinely ambiguous about which account paid — the user will pick one via the proposal card's Edit button. In chat, always pass a real id (ask the user instead of guessing). Do not pass an empty string; omit the field entirely instead. | |
| categoryId | No | ||
| envelopeId | No | ||
| description | Yes | ||
| exchangeRate | No | Rate to convert the amount into the account's currency, used only when currency differs from the account. Usually omit — the server auto-fetches the rate as of the date. | |
| editsProposalId | No | Id of an existing pending proposal to update in place. Pass this when the user asks to modify a proposal you previously made (e.g. 'make it $50 instead'). Look up current ids with listPendingProposals if you're unsure. Omit when proposing something new. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description clarifies that this only creates a pending proposal and nothing is recorded until confirm_proposal is called, adding critical behavioral context beyond the annotations. It also warns about account validation requirements, making side effects and prerequisites explicit.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense yet concise, front-loading the purpose and workflow, then addressing parameter nuances. Every sentence adds value, with no fluff or repetition of schema details.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 10 parameters, no output schema, and a multi-step workflow, the description covers all critical aspects: the follow-up confirm_proposal step, account validation, parameter semantics, and alternatives. It is sufficient for an agent to invoke correctly without further clarification.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With only 60% schema coverage, the description adds essential meaning for amount (major units, no pre-multiplication), currency (exchange rate handling), accountId (when to omit vs pass real id), exchangeRate (usually omit), and editsProposalId (when to use). This compensates well for schema gaps.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action ('Propose a new income or expense transaction') with a clear resource and distinguishes it from siblings like propose_transfer and propose_transaction_edit. It also notes it returns a proposal id, which clarifies the tool's role in the proposal workflow.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly instructs to call confirm_proposal after approval, names the alternative for editing (editsProposalId), and gives preconditions like validating account ownership. It also provides context-specific guidance for chat vs email-import, leaving no ambiguity about when to use this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
propose_transaction_editADestructiveInspect
Propose an edit to an existing past income or expense transaction. Returns a proposal id; to record it, call the confirm_proposal tool with the returned proposalId after the user approves (there is no UI button or proposal card to click in this context). Only works on income/expense transactions — transfers and asset trades (buy/sell) must be edited on the Transactions page. ONLY pass the fields the user explicitly asked to change; omit the rest so they keep their current value. Pass null for an optional field only when the user explicitly asks to clear that field (e.g. 'remove the category').
MCP note: this tool only CREATES a pending proposal; nothing is recorded until confirm_proposal is called.
| Name | Required | Description | Default |
|---|---|---|---|
| date | No | Optional. New date (YYYY-MM-DD). | |
| type | No | Optional. New type for the transaction. Only income↔expense is allowed via this tool. | |
| notes | No | Optional. New notes, or null to clear. | |
| amount | No | Optional. New amount in MAJOR units (displayed amount, e.g. 12.34 for $12.34). Never pre-multiply by 100. | |
| currency | No | Optional. New 3-letter currency code. Must match the transaction's account currency (no foreign-currency edits via chat). | |
| categoryId | No | Optional. New category id, or null to clear the category. | |
| envelopeId | No | Optional. New budget (envelope) id, or null to clear it. | |
| description | No | Optional. New description. Pass null to clear it. | |
| transactionId | Yes | Id of the existing transaction to edit. Look it up with runReadQuery (filtering by description/date/amount/etc.) before calling. | |
| editsProposalId | No | Id of an existing pending edit-proposal to update in place. Pass this when the user revises a previous edit you proposed ('actually make it $60 not $50'). Omit when proposing a fresh edit. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations carry readOnlyHint=false and destructiveHint=true, but the description adds genuinely valuable context beyond them: this tool only creates a pending proposal and 'nothing is recorded until confirm_proposal is called.' It also warns there is no UI affordance to click, so the agent must complete the flow itself. The pending-proposal disclosure meaningfully refines the conservative destructiveHint rather than contradicting it.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but proportionate to its job: a 10-parameter two-phase workflow with exclusion rules and an omit/null protocol. Each block carries distinct operational information. There is one redundancy — the closing 'MCP note' repeats the pending-not-recorded point already made in the second sentence — so it is not perfectly lean.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex tool with no output schema, the description covers the main operational essentials: the proposal/confirm two-step flow, the allowed transaction scope, the exclude cases, and the null-vs-omit semantics. The return value is named ('proposal id') and routed to the confirm tool. Remaining gaps are minor (e.g., no statement about what happens if confirm_proposal is not called, or error behavior).
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, setting the baseline at 3, and the description earns an extra point by disambiguating the critical 'omit vs. null' rule: omit fields the user didn't mention so they keep current values; pass null only for explicit clears. It also clarifies when to use editsProposalId (revising a prior proposal like 'actually make it $60 not $50'), which the schema's property description does not convey.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb–object pair — 'Propose an edit to an existing past income or expense transaction' — defining both the action and the allowed resource. It further distinguishes the tool from siblings by explicitly excluding transfers and asset trades, which map to propose_transfer/propose_asset_trade, and from propose_transaction (new) and propose_delete_transaction (delete). An agent can select it correctly 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit when-to-use (edits to existing income/expense transactions), explicit when-not-to-use (transfers and asset trades → Transactions page), and the exact follow-up step (call confirm_proposal with the returned proposalId since there is no UI button). It also covers the revision scenario via editsProposalId. Nearly nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
propose_transferADestructiveInspect
Propose a transfer between two of the user's accounts. Same-currency transfers move the amount as-is; cross-currency transfers use the user-supplied exchangeRate or fall back to the latest exchange_rate. Always include a short user-supplied description; optionally include a fee (in fromAccount currency) recorded as a separate expense on the source account. Returns a proposal id — to record it, call the confirm_proposal tool with the returned proposalId after the user approves (there is no UI button or proposal card to click in this context).
MCP note: this tool only CREATES a pending proposal; nothing is recorded until confirm_proposal is called.
| Name | Required | Description | Default |
|---|---|---|---|
| fee | No | Optional transfer fee in fromAccount currency, MAJOR units (e.g. 2.50 for $2.50, 1000 for Rp 1,000). Recorded as a separate expense on the source account. | |
| date | Yes | ||
| amount | Yes | Amount to transfer, in fromAccount currency, MAJOR units (the displayed amount, e.g. 100.00 for $100.00, 50000 for Rp 50,000). The server scales to storage units; never pre-multiply by 100. | |
| toCurrency | No | 3-letter currency for the destination amount. Required when toAccountId is omitted; otherwise inferred from the account. | |
| description | Yes | Short user-supplied description, e.g. 'rent to landlord'. | |
| toAccountId | No | Id of the destination account. Omit only in the email-import pipeline when the email is genuinely ambiguous about the destination account. Do not pass an empty string; omit the field entirely instead. | |
| exchangeRate | No | ||
| fromCurrency | No | 3-letter currency for the source amount. Required when fromAccountId is omitted; otherwise inferred from the account. | |
| fromAccountId | No | Id of the source account. Omit only in the email-import pipeline when the email is genuinely ambiguous about the source account — the user picks one via the Edit button. In chat, always pass a real id. Do not pass an empty string; omit the field entirely instead. | |
| editsProposalId | No | Id of an existing pending proposal to update in place. Pass this when the user asks to modify a proposal you previously made (e.g. 'make it $50 instead'). Look up current ids with listPendingProposals if you're unsure. Omit when proposing something new. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations are readOnlyHint=false and destructiveHint=true, which already indicate mutation and potential data loss. The description adds context: it creates a pending proposal (non-destructive, temporary), requires user approval before confirmation, and mentions no UI button—important for chat context. It doesn't disclose all side effects (e.g., fee effects) in detail, but it adds sufficient value beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but structured logically: it opens with the core action, proceeds to sub-behaviors (fee, description, returns), and closes with a critical MCP note. Every sentence adds value, but the multiple clauses in the first sentence could be split for easier scanning. It's slightly long but well-organized.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (10 params, no output schema, two-step workflow), the description covers the essential context: the proposal lifecycle, parameter dependencies (currency vs. account), and the return value's purpose. It doesn't detail return format or error handling, but it provides enough for an agent to call it correctly. Missing details like date format are in the schema, so this is adequate.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 80%, so the schema provides robust parameter descriptions. The description adds critical semantics: it explains the 'as-is' vs. 'exchangeRate' behavior, the fee currency and recording as an expense, and clarifies that amounts are in MAJOR units and never pre-multiplied—essential for correct invocation. This goes beyond the schema's basic descriptions, demonstrating high value.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Propose a transfer between two of the user's accounts'—a specific verb and resource. It details the action (propose, not execute), distinguishes it from record (confirm_proposal), and differentiates it from siblings like propose_asset_convert and propose_transaction. The inclusion of key details (same-currency, cross-currency, fee) adds specificity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when to use: 'Always include a short user-supplied description; optionally include a fee...' and clarifies the two-step workflow: 'only CREATES a pending proposal; nothing is recorded until confirm_proposal is called.' It also names confirm_proposal as the follow-up and implies when not to use (for executing directly). This is thorough, with clear context and no ambiguity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
run_insight_queryARead-onlyInspect
Compute an analytics insight (a single value, a comparison, a breakdown, or a time-series) over a filtered period of transactions, from an ad-hoc spec, WITHOUT saving it. Use this to answer one-off analytical questions like 'how much did I spend on Dining last month' or 'compare income vs expense this year'. If the user wants to keep the result pinned on their dashboard, use propose_saved_insight instead.
| Name | Required | Description | Default |
|---|---|---|---|
| spec | Yes | The visualization spec describing what to compute. vizType is one of: 'value' (single number), 'comparison' (template income_vs_expense / period_over_period, or custom A/B), 'chart_time' (bucketed time series), 'breakdown' (top groups by category/envelope/account/type), 'table' (list of N transactions). Always set filter.period - use relative.value='this_month' / 'last_30_days' etc. unless the user gave explicit dates. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description clearly indicates a read-only operation ('generate'), and the readOnlyHint annotation confirms no side effects. However, it doesn't state that it does not modify data, which could be made explicit.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is succinct and directly states what the tool does without unnecessary details. It appropriately omits schema internals, keeping it concise.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description, tool name, and sibling tools (create/update/delete/get/share) make it clear this is the execution action for insights. It gives enough context for an agent to understand when to use it, though it could explicitly mention that it runs an existing ad-hoc query or saved insight definition.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The single 'spec' parameter has a detailed schema defining metric, groupBy, filter with periods and optional account/category filters. However, the schema is complex with multiple variantsainer and the description provides no explanation of the parameter structure, relying entirely on the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The name 'run_insight' and description explicitly state that this tool generates an insight (a number, chart, or breakdown). Sibling tools like create/update/delete differentiate this as the execution/read operation, making the purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains what the tool does but provides no guidance on when to use it versus alternatives or prerequisites. While the sibling tools imply run is for executing existing insights, there's no explicit direction on selecting this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
run_read_queryARead-onlyInspect
Run a single Postgres SELECT against the user's data. The database automatically scopes results to the current user — do NOT add WHERE user_id clauses. For net worth, budget, or asset valuation use the dedicated tools instead. Provide a one-line rationale explaining the query.
IMPORTANT - money units: columns the schema below marks as minor units (the marker reads roughly "[minor units - divide by 100]") are stored as INTEGER minor units - the real amount x 100, for ALL currencies including IDR with no decimal places (e.g. Rp 2,500,000 is stored as 250000000). Divide ONLY those marked columns by 100.0 in your SELECT projection to get real amounts, e.g. SELECT SUM(amount) / 100.0 AS total. Do NOT divide columns that are already in major units - in particular the v_chat_transaction view's amount_major and signed_amount are already real major-unit amounts, so use them directly (they are the easiest correct way to sum spend/income). Never multiply by 100.
asset
purchase_price is the per-unit purchase price in purchase_currency rows with deleted_at IS NOT NULL are soft-deleted; exclude them for per-asset P&L questions the getAssets tool already returns cost basis, P&L, and P&L % in the user's base currency; prefer it over hand-rolled SQL
id: string
user_id: string
account_id: string (nullable)
type: string [enum: crypto | stock | real_estate | vehicle | commodity | bond | other]
symbol: string (nullable)
display_symbol: string (nullable)
quantity: string
unit: string (nullable)
purchase_price: number (nullable) [minor units — divide by 100]
purchase_currency: string (nullable)
valuation_mode: string [enum: auto | manual]
created_at: date
updated_at: date
deleted_at: date (nullable)
asset_split
id: string
asset_id: string
effective_date: string
ratio_from: number
ratio_to: number
source: string [enum: manual | yahoo]
status: string [enum: pending | applied | dismissed]
cache_applied: boolean
created_at: date
updated_at: date
asset_transaction
per-trade buy/sell record for an asset; join transaction on transaction_id for date, type (buy | sell), currency, and soft-delete status (exclude deleted_at IS NOT NULL) price_per_unit is in the joined transaction's currency an asset conversion (swap of one asset for another) appears as a paired sell + buy on the same date whose transactions have account_id IS NULL; they move no cash (v_chat_transaction reports them as neutral with signed_amount 0)
id: string
transaction_id: string
asset_id: string
quantity: string
price_per_unit: number [minor units — divide by 100]
created_at: date
category
id: string
user_id: string
name: string
icon: string (nullable)
parent_id: string (nullable)
created_at: date
updated_at: date
deleted_at: date (nullable)
counterparty
id: string
user_id: string
name: string
notes: string (nullable)
created_at: date
updated_at: date
deleted_at: date (nullable)
envelope
this table represents what the user calls a 'budget' — the DB table is named
envelopefor historical reasons, but always say 'budget' in user-facing replies budgets are buckets that group categories — a user mentioning a budget by name (e.g., 'dating', 'vacation') almost always means a row here, not a category v_chat_transaction.envelope_name resolves the (transaction → budget) link for you; prefer that over joining envelope_category yourself
id: string
user_id: string
name: string
budgeted_amount: number [minor units — divide by 100]
currency: string
period: string [enum: weekly | monthly]
tracking_mode: string [enum: category | manual]
include_investments: boolean
category_id: string (nullable)
created_at: date
updated_at: date
deleted_at: date (nullable)
envelope_category
junction table linking categories to budgets; v_chat_transaction.envelope_name already follows this path, so you rarely need to query envelope_category directly
id: string
envelope_id: string
category_id: string
exchange_rate
stored one direction per pair (typically from_currency = USD); for the reverse direction, use 1/rate from the existing row rather than expecting an explicit inverse row use the latest row per (from_currency, to_currency) pair (order by fetched_at DESC, limit 1)
id: string
from_currency: string
to_currency: string
rate: string
fetched_at: date
financial_account
balance_cache is the live balance in minor units rows with deleted_at IS NOT NULL are soft-deleted; exclude them
id: string
user_id: string
name: string
type: string [enum: checking | savings | credit_card | cash | investment | crypto | loan | mortgage | property | vehicle | receivable | payable]
currency: string
institution: string (nullable)
icon: string (nullable)
is_liability: boolean
initial_balance: number [minor units — divide by 100]
balance_cache: number [minor units — divide by 100]
credit_limit: number (nullable) [minor units — divide by 100]
is_active: boolean
is_virtual: boolean
counterparty_id: string (nullable)
created_at: date
updated_at: date
deleted_at: date (nullable)
net_worth_snapshot
id: string
user_id: string
total_assets: number [minor units — divide by 100]
total_liabilities: number [minor units — divide by 100]
net_worth: number [minor units — divide by 100]
currency: string
breakdown_json: json (nullable)
snapshot_date: string
created_at: date
price
cached market price per unit of the asset, keyed by (type, symbol); join asset on both columns use the latest row per (type, symbol) (order by fetched_at DESC, limit 1) for commodities the price is per troy ounce regardless of asset.unit; convert before comparing to per-unit purchase prices
id: string
type: string [enum: crypto | stock | real_estate | vehicle | commodity | bond | other]
symbol: string
price: number [minor units — divide by 100]
currency: string
fetched_at: date
transaction
amount is always non-negative; direction lives in type for spend/income totals, prefer the v_chat_transaction view rows with deleted_at IS NOT NULL are soft-deleted; exclude them
id: string
user_id: string
account_id: string (nullable)
type: string [enum: income | expense | transfer | buy | sell]
amount: number [minor units — divide by 100]
currency: string
exchange_rate: string (nullable)
date: string
description: string (nullable)
category_id: string (nullable)
envelope_id: string (nullable)
notes: string (nullable)
receipt_image_url: string (nullable)
created_at: date
updated_at: date
deleted_at: date (nullable)
valuation
one row per asset per day; latest row is the current value
id: string
asset_id: string
value: number [minor units — divide by 100]
currency: string
fetched_at: date
v_chat_transaction (view)
Presentation view over transaction. Soft-deleted rows already excluded. Prefer this over the raw transaction table for any spend/income question.
id: string
user_id: string
date: date
type: string [enum: income | expense | transfer | buy | sell]
description: string (nullable)
currency: string
amount_major: numeric (always >= 0; major units, e.g. dollars not cents)
signed_amount: numeric (negative for expense and buy; positive for income and sell; zero for transfer and for cashless asset-conversion legs)
direction: string [enum: outflow | inflow | neutral]
account_id: string (nullable; null on the cashless legs of an asset conversion, which move no cash)
category_id: string (nullable)
category_name: string (nullable, joined from category)
envelope_id: string (nullable; direct budget assignment, often null)
envelope_name: string (nullable; the user's budget label, resolved via direct envelope_id OR via the envelope_category junction on category_id — match this when the user names a budget like "Dating")
| Name | Required | Description | Default |
|---|---|---|---|
| sql | Yes | A single Postgres SELECT statement. | |
| rationale | Yes | One-line plain-English explanation of why you're running this query. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint annotation, the description discloses that the database auto-scopes to the current user, that domestic money columns are stored in minor units and must be divided by 100.0, that soft-deleted rows must be excluded, and that v_chat_transaction already excludes them. These are behavioral quirks the annotation alone would not reveal.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long, but it is organized: an initial purpose statement, an all-caps money-unit warning, and then a table-by-table schema with compressed inline comments. Every sentence serves as either a necessary constraint (deleted_at, minor units, view preference) or a pointer to a better tool. Although dense, the length is justified by the complexity of allowing raw SQL.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool that exposes full SQL to a complex schema and has no defined output schema, the description covers all necessary ground: schema, enums, soft-delete flags, money-unit conversion, view preference, and dedicated-tool routing. It leaves an agent almost fully equipped to write correct SELECT statements without previous domain knowledge.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema only labels `sql` as 'a single Postgres SELECT statement.' The description adds extensive meaning to that parameter: which columns are minor units, how to divide them, how to interpret signed_amount/amount_major, and which tables/views to prefer. This goes beyond the schema's coverage and gives the agent the domain knowledge needed to build correct queries.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific action and resource: 'Run a single Postgres SELECT against the user's data.' It also separates itself from dedicated tools by saying 'For net worth, budget, or asset valuation use the dedicated tools instead,' naming siblings like get_net_worth, get_budget, and get_assets. This makes its purpose and boundary unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly tells the agent when not to use the tool ('use the dedicated tools instead') and when to prefer it ('for spend/income totals, prefer the v_chat_transaction view'). It also forbids adding YES WHERE user_id clauses and mandates a `rationale` parameter, giving concrete conditions for invocation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
21 tool updates
- First observed
confirm_proposal - First observed
get_accounts - First observed
get_assets - First observed
get_budget - First observed
get_categories - First observed
get_ious - First observed
get_net_worth - First observed
get_saved_insights - First observed
get_yesterday_summary - First observed
list_pending_proposals - First observed
propose_asset_convert - First observed
propose_asset_trade - First observed
propose_budget_upsert - First observed
propose_delete_budget - First observed
propose_delete_transaction - First observed
propose_saved_insight - First observed
propose_transaction - First observed
propose_transaction_edit - First observed
propose_transfer - First observed
run_insight_query - First observed
run_read_query
Related MCP Connectors
Read-only access to your net worth, wealth percentile, projections, splits and budget.
Chat with your bank data: balances, transactions, budgets, bills. Reads only, never moves money.
Personal finance by conversation: expenses, receipts, statement import, budgets, net worth.
Read-only access to your bank, investment, and crypto accounts: balances, transactions, holdings.
Related MCP Servers
- AlicenseAqualityCmaintenanceEnables AI assistants to interact with YNAB budgets, performing read-only queries by default and optional write operations like creating transactions and managing categories through natural language.3814630MIT
- AlicenseAqualityBmaintenanceEnables reading and writing YNAB budget data, such as listing budgets, accounts, categories, transactions, and creating or updating transactions, through natural language commands.8MIT
- AlicenseAqualityBmaintenanceProvides a read-only interface to YNAB budget data, allowing AI assistants to inspect budgets, accounts, categories, transactions, and more. Includes an experimental guarded write workflow for category assignments.1056MIT
- AlicenseNot gradedqualityFmaintenanceProvides read-only access to Monarch Money financial data, enabling AI assistants to analyze transactions, budgets, and cashflow.4MIT