fix: disable get_budgets tool due to upstream Monarch Money API bug
All checks were successful
Build and Push Monarch MCP Docker Image / build (push) Successful in 17s

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.
This commit is contained in:
Ben
2025-12-25 04:28:19 +00:00
parent bb38e2441d
commit 52f7a746f9

View File

@@ -105,76 +105,79 @@ async def get_transactions(
return serialize_json(formatted) return serialize_json(formatted)
@mcp.tool() # NOTE: get_budgets is disabled due to upstream Monarch Money API bug
@retry_on_auth_error() # See budget_bug.md for details
async def get_budgets(reason: Optional[str] = None) -> str: #
"""Get current budget information.""" # @mcp.tool()
client = await get_authenticated_client() # @retry_on_auth_error()
# async def get_budgets(reason: Optional[str] = None) -> str:
try: # """Get current budget information."""
# Disable both legacy and v2 goals to avoid API errors with goals fields # client = await get_authenticated_client()
# 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) # try:
except Exception as e: # # Disable both legacy and v2 goals to avoid API errors with goals fields
error_msg = str(e) # # The Monarch API appears to have issues with goals-related GraphQL fields
# Check if this is a Monarch API error about budgets not being set up # budgets = await client.get_budgets(use_legacy_goals=False, use_v2_goals=False)
if "Something went wrong" in error_msg: # except Exception as e:
return serialize_json( # error_msg = str(e)
{ # # Check if this is a Monarch API error about budgets not being set up
"error": "Budget data unavailable", # if "Something went wrong" in error_msg:
"detail": "The Monarch Money API returned an error. This may be a temporary API issue.", # return serialize_json(
"raw_error": error_msg, # {
} # "error": "Budget data unavailable",
) # "detail": "The Monarch Money API returned an error. This may be a temporary API issue.",
raise # "raw_error": error_msg,
# }
# Build a category lookup from categoryGroups # )
category_lookup = {} # raise
for group in budgets.get("categoryGroups", []): #
for cat in group.get("categories", []): # # Build a category lookup from categoryGroups
category_lookup[cat.get("id")] = { # category_lookup = {}
"name": cat.get("name"), # for group in budgets.get("categoryGroups", []):
"group": group.get("name"), # for cat in group.get("categories", []):
"variability": cat.get("budgetVariability"), # category_lookup[cat.get("id")] = {
} # "name": cat.get("name"),
# "group": group.get("name"),
# Process monthly amounts by category # "variability": cat.get("budgetVariability"),
budget_list = [] # }
for item in budgets.get("budgetData", {}).get("monthlyAmountsByCategory", []): #
cat_id = (item.get("category") or {}).get("id") # # Process monthly amounts by category
cat_info = category_lookup.get(cat_id, {}) # budget_list = []
# for item in budgets.get("budgetData", {}).get("monthlyAmountsByCategory", []):
for monthly in item.get("monthlyAmounts", []): # cat_id = (item.get("category") or {}).get("id")
budget_list.append( # cat_info = category_lookup.get(cat_id, {})
{ #
"month": monthly.get("month"), # for monthly in item.get("monthlyAmounts", []):
"category": cat_info.get("name"), # budget_list.append(
"group": cat_info.get("group"), # {
"planned": monthly.get("plannedCashFlowAmount"), # "month": monthly.get("month"),
"actual": monthly.get("actualAmount"), # "category": cat_info.get("name"),
"remaining": monthly.get("remainingAmount"), # "group": cat_info.get("group"),
"rollover": monthly.get("previousMonthRolloverAmount"), # "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( # # Also include monthly totals summary
{ # totals = []
"month": total.get("month"), # for total in budgets.get("budgetData", {}).get("totalsByMonth", []):
"income_planned": (total.get("totalIncome") or {}).get("plannedAmount"), # totals.append(
"income_actual": (total.get("totalIncome") or {}).get("actualAmount"), # {
"expenses_planned": (total.get("totalExpenses") or {}).get( # "month": total.get("month"),
"plannedAmount" # "income_planned": (total.get("totalIncome") or {}).get("plannedAmount"),
), # "income_actual": (total.get("totalIncome") or {}).get("actualAmount"),
"expenses_actual": (total.get("totalExpenses") or {}).get( # "expenses_planned": (total.get("totalExpenses") or {}).get(
"actualAmount" # "plannedAmount"
), # ),
} # "expenses_actual": (total.get("totalExpenses") or {}).get(
) # "actualAmount"
# ),
return serialize_json({"budgets": budget_list, "totals": totals}) # }
# )
#
# return serialize_json({"budgets": budget_list, "totals": totals})
def validate_account_id(account_id: str) -> int: def validate_account_id(account_id: str) -> int: