Skip to main content
Glama

get_category_spending_summary

Analyze category spending patterns over time to track expenses, view monthly breakdowns, and understand budget performance with visual charts.

Instructions

Get spending summary for a category over a date range.

Args: budget_id: The ID of the budget (use 'last-used' for default budget) category_id: The category ID to analyze since_date: Start date (YYYY-MM-DD format) until_date: End date (YYYY-MM-DD format) include_graph: Include terminal graph visualization (default: True) Returns: JSON string with summary including total spent, average per month, transaction count, monthly breakdown, and optional graph

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
budget_idYes
category_idYes
include_graphNo
since_dateYes
until_dateYes

Implementation Reference

  • MCP tool handler and registration via @mcp.tool() decorator. Defines input schema via type hints and docstring. Executes tool logic by delegating to YNABClient.get_category_spending_summary and returns JSON.
    @mcp.tool() async def get_category_spending_summary( budget_id: str, category_id: str, since_date: str, until_date: str, include_graph: bool = True, ) -> str: """Get spending summary for a category over a date range. Args: budget_id: The ID of the budget (use 'last-used' for default budget) category_id: The category ID to analyze since_date: Start date (YYYY-MM-DD format) until_date: End date (YYYY-MM-DD format) include_graph: Include terminal graph visualization (default: True) Returns: JSON string with summary including total spent, average per month, transaction count, monthly breakdown, and optional graph """ client = get_ynab_client() result = await client.get_category_spending_summary( budget_id, category_id, since_date, until_date, include_graph ) return json.dumps(result, indent=2)
  • Core helper method in YNABClient that implements the spending summary logic: fetches transactions via YNAB API, filters by category and date range, aggregates total spent, transaction count, monthly breakdown, average per month, and generates optional terminal graph.
    async def get_category_spending_summary( self, budget_id: str, category_id: str, since_date: str, until_date: str, include_graph: bool = True, ) -> dict[str, Any]: """Get spending summary for a category over a date range. Args: budget_id: The budget ID or 'last-used' category_id: The category ID to analyze since_date: Start date (YYYY-MM-DD) until_date: End date (YYYY-MM-DD) include_graph: Include terminal graph visualization (default: True) Returns: Summary with total spent, average, transaction count, and monthly breakdown """ try: # Get transactions for the category url = f"{self.api_base_url}/budgets/{budget_id}/transactions" params = {"since_date": since_date} result = await self._make_request_with_retry("get", url, params=params) txn_data = result["data"]["transactions"] # Filter and aggregate total_spent = 0 transaction_count = 0 monthly_totals = {} for txn in txn_data: # Filter by category and date range if txn.get("category_id") != category_id: continue if txn["date"] > until_date: continue amount = txn["amount"] / 1000 if txn.get("amount") else 0 total_spent += amount transaction_count += 1 # Track monthly totals month_key = txn["date"][:7] # YYYY-MM if month_key not in monthly_totals: monthly_totals[month_key] = 0 monthly_totals[month_key] += amount # Calculate average per month num_months = len(monthly_totals) if monthly_totals else 1 average_per_month = total_spent / num_months if num_months > 0 else 0 # Convert monthly totals to sorted list monthly_breakdown = [ {"month": month, "spent": amount} for month, amount in sorted(monthly_totals.items()) ] result = { "category_id": category_id, "date_range": {"start": since_date, "end": until_date}, "total_spent": total_spent, "transaction_count": transaction_count, "average_per_month": average_per_month, "num_months": num_months, "monthly_breakdown": monthly_breakdown, } # Add graph if requested if include_graph and monthly_breakdown: graph_data = [(item["month"], item["spent"]) for item in monthly_breakdown] result["graph"] = self._generate_graph( graph_data, f"Monthly Spending: {since_date} to {until_date}" ) return result except Exception as e:
  • Supporting utility method used by get_category_spending_summary to generate terminal-based graph visualization of monthly spending data using termgraph library.
    def _generate_graph(self, data: list[tuple], title: str = "") -> str: """Generate a terminal graph using termgraph. Args: data: List of (label, value) tuples title: Graph title Returns: String containing the terminal graph """ if not data: return "" # Capture termgraph output old_stdout = sys.stdout sys.stdout = StringIO() try: # Prepare data for termgraph labels = [label for label, _ in data] values = [[abs(value)] for _, value in data] # Configure termgraph args = { "stacked": False, "width": 50, "format": "{:.2f}", "suffix": "", "no_labels": False, "color": None, "vertical": False, "different_scale": False, "calendar": False, "start_dt": None, "custom_tick": "", "delim": "", "verbose": False, "label_before": False, "histogram": False, "no_values": False, } # Print title if title: print(f"\n{title}") print("=" * len(title)) # Generate graph tg.chart(colors=[], data=values, args=args, labels=labels) # Get the output output = sys.stdout.getvalue() return output finally: sys.stdout = old_stdout

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/dgalarza/ynab-mcp'

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