Skip to main content
Glama
klauern

MCP YNAB Server

by klauern

get_transactions_needing_attention

Identify YNAB transactions requiring attention, such as uncategorized or unapproved entries, by applying filters like type and date range for efficient budget management.

Instructions

List transactions that need attention based on specified filter type in a YNAB budget.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
budget_idYes
days_backNoNumber of days to look back (default 30, None for all)
filter_typeNoType of transactions to show. One of: 'uncategorized', 'unapproved', 'both'both

Implementation Reference

  • The core handler function for the 'get_transactions_needing_attention' tool. It fetches accounts and transactions from YNAB API, filters those needing attention (uncategorized or unapproved), formats into a markdown table. Includes inline schema via Pydantic Field annotations and registration via @mcp.tool() decorator.
    @mcp.tool() async def get_transactions_needing_attention( budget_id: str, filter_type: Annotated[ str, Field( description="Type of transactions to show. One of: 'uncategorized', 'unapproved', 'both'" ), ] = "both", days_back: Annotated[ Optional[int], Field(description="Number of days to look back (default 30, None for all)") ] = 30, ) -> str: """List transactions that need attention based on specified filter type in a YNAB budget.""" filter_type = filter_type.lower() if filter_type not in ["uncategorized", "unapproved", "both"]: return "Error: Invalid filter_type. Must be 'uncategorized', 'unapproved', or 'both'" async with await get_ynab_client() as client: transactions_api = TransactionsApi(client) accounts_api = AccountsApi(client) accounts_response = accounts_api.get_accounts(budget_id) account_map = { account.id: account.name for account in accounts_response.data.accounts if not account.closed and not account.deleted } since_date = (datetime.now() - timedelta(days=days_back)).date() if days_back else None response = transactions_api.get_transactions(budget_id, since_date=since_date) needs_attention = _filter_transactions(response.data.transactions, filter_type) markdown = f"# Transactions Needing Attention ({filter_type.title()})\n\n" if not needs_attention: return markdown + "_No transactions need attention._" markdown += "**Filters Applied:**\n" markdown += f"- Filter type: {filter_type}\n" if days_back: markdown += f"- Looking back {days_back} days\n" markdown += "\n" headers = ["ID", "Date", "Account", "Amount", "Payee", "Status", "Memo"] align = ["left", "left", "left", "right", "left", "left", "left"] rows = [_get_transaction_row(txn, account_map, filter_type) for txn in needs_attention] markdown += _build_markdown_table(rows, headers, align) return markdown
  • Helper function that filters the list of transactions to those needing attention based on the specified filter_type (uncategorized, unapproved, or both).
    def _filter_transactions( transactions: List[TransactionDetail], filter_type: str ) -> List[TransactionDetail]: """Filter transactions based on the filter type.""" needs_attention = [] for txn in transactions: if isinstance(txn, TransactionDetail): needs_category = filter_type in ["uncategorized", "both"] and not txn.category_id needs_approval = filter_type in ["unapproved", "both"] and not txn.approved if needs_category or needs_approval: needs_attention.append(txn) return needs_attention
  • Helper function to format a single TransactionDetail into a list of strings for the markdown table row, including status flags.
    def _get_transaction_row( txn: TransactionDetail, account_map: Dict[str, str], filter_type: str ) -> List[str]: """Format a transaction into a row for the markdown table.""" amount_dollars = float(txn.amount) / 1000 amount_str = f"${abs(amount_dollars):,.2f}" if amount_dollars < 0: amount_str = f"-{amount_str}" status = [] if not txn.category_id: status.append("Uncategorized") if not txn.approved: status.append("Unapproved") return [ txn.id, txn.var_date.strftime("%Y-%m-%d"), account_map.get(txn.account_id, "Unknown"), amount_str, txn.payee_name or "N/A", ", ".join(status), txn.memo or "", ]

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/klauern/mcp-ynab'

If you have feedback or need assistance with the MCP directory API, please join our Discord server