From 52f7a746f9889f9826f5894a546a2ab4d7db931b Mon Sep 17 00:00:00 2001 From: Ben Date: Thu, 25 Dec 2025 04:28:19 +0000 Subject: [PATCH] fix: disable get_budgets tool due to upstream Monarch Money API bug The Monarch Money API incorrectly processes @include(if: false) GraphQL directives, causing errors on goals-related fields. Tool commented out until upstream issue is resolved. See budget_bug.md for details. --- src/monarch_mcp_custom/server.py | 143 ++++++++++++++++--------------- 1 file changed, 73 insertions(+), 70 deletions(-) diff --git a/src/monarch_mcp_custom/server.py b/src/monarch_mcp_custom/server.py index 446f83d..4874caa 100644 --- a/src/monarch_mcp_custom/server.py +++ b/src/monarch_mcp_custom/server.py @@ -105,76 +105,79 @@ async def get_transactions( return serialize_json(formatted) -@mcp.tool() -@retry_on_auth_error() -async def get_budgets(reason: Optional[str] = None) -> str: - """Get current budget information.""" - client = await get_authenticated_client() - - try: - # Disable both legacy and v2 goals to avoid API errors with goals fields - # The Monarch API appears to have issues with goals-related GraphQL fields - budgets = await client.get_budgets(use_legacy_goals=False, use_v2_goals=False) - except Exception as e: - error_msg = str(e) - # Check if this is a Monarch API error about budgets not being set up - if "Something went wrong" in error_msg: - return serialize_json( - { - "error": "Budget data unavailable", - "detail": "The Monarch Money API returned an error. This may be a temporary API issue.", - "raw_error": error_msg, - } - ) - raise - - # Build a category lookup from categoryGroups - category_lookup = {} - for group in budgets.get("categoryGroups", []): - for cat in group.get("categories", []): - category_lookup[cat.get("id")] = { - "name": cat.get("name"), - "group": group.get("name"), - "variability": cat.get("budgetVariability"), - } - - # Process monthly amounts by category - budget_list = [] - for item in budgets.get("budgetData", {}).get("monthlyAmountsByCategory", []): - cat_id = (item.get("category") or {}).get("id") - cat_info = category_lookup.get(cat_id, {}) - - for monthly in item.get("monthlyAmounts", []): - budget_list.append( - { - "month": monthly.get("month"), - "category": cat_info.get("name"), - "group": cat_info.get("group"), - "planned": monthly.get("plannedCashFlowAmount"), - "actual": monthly.get("actualAmount"), - "remaining": monthly.get("remainingAmount"), - "rollover": monthly.get("previousMonthRolloverAmount"), - } - ) - - # Also include monthly totals summary - totals = [] - for total in budgets.get("budgetData", {}).get("totalsByMonth", []): - totals.append( - { - "month": total.get("month"), - "income_planned": (total.get("totalIncome") or {}).get("plannedAmount"), - "income_actual": (total.get("totalIncome") or {}).get("actualAmount"), - "expenses_planned": (total.get("totalExpenses") or {}).get( - "plannedAmount" - ), - "expenses_actual": (total.get("totalExpenses") or {}).get( - "actualAmount" - ), - } - ) - - return serialize_json({"budgets": budget_list, "totals": totals}) +# NOTE: get_budgets is disabled due to upstream Monarch Money API bug +# See budget_bug.md for details +# +# @mcp.tool() +# @retry_on_auth_error() +# async def get_budgets(reason: Optional[str] = None) -> str: +# """Get current budget information.""" +# client = await get_authenticated_client() +# +# try: +# # Disable both legacy and v2 goals to avoid API errors with goals fields +# # The Monarch API appears to have issues with goals-related GraphQL fields +# budgets = await client.get_budgets(use_legacy_goals=False, use_v2_goals=False) +# except Exception as e: +# error_msg = str(e) +# # Check if this is a Monarch API error about budgets not being set up +# if "Something went wrong" in error_msg: +# return serialize_json( +# { +# "error": "Budget data unavailable", +# "detail": "The Monarch Money API returned an error. This may be a temporary API issue.", +# "raw_error": error_msg, +# } +# ) +# raise +# +# # Build a category lookup from categoryGroups +# category_lookup = {} +# for group in budgets.get("categoryGroups", []): +# for cat in group.get("categories", []): +# category_lookup[cat.get("id")] = { +# "name": cat.get("name"), +# "group": group.get("name"), +# "variability": cat.get("budgetVariability"), +# } +# +# # Process monthly amounts by category +# budget_list = [] +# for item in budgets.get("budgetData", {}).get("monthlyAmountsByCategory", []): +# cat_id = (item.get("category") or {}).get("id") +# cat_info = category_lookup.get(cat_id, {}) +# +# for monthly in item.get("monthlyAmounts", []): +# budget_list.append( +# { +# "month": monthly.get("month"), +# "category": cat_info.get("name"), +# "group": cat_info.get("group"), +# "planned": monthly.get("plannedCashFlowAmount"), +# "actual": monthly.get("actualAmount"), +# "remaining": monthly.get("remainingAmount"), +# "rollover": monthly.get("previousMonthRolloverAmount"), +# } +# ) +# +# # Also include monthly totals summary +# totals = [] +# for total in budgets.get("budgetData", {}).get("totalsByMonth", []): +# totals.append( +# { +# "month": total.get("month"), +# "income_planned": (total.get("totalIncome") or {}).get("plannedAmount"), +# "income_actual": (total.get("totalIncome") or {}).get("actualAmount"), +# "expenses_planned": (total.get("totalExpenses") or {}).get( +# "plannedAmount" +# ), +# "expenses_actual": (total.get("totalExpenses") or {}).get( +# "actualAmount" +# ), +# } +# ) +# +# return serialize_json({"budgets": budget_list, "totals": totals}) def validate_account_id(account_id: str) -> int: