fix: use monarchmoney from git main to get budget fix (#119)
Some checks failed
Build and Push Monarch MCP Docker Image / build (push) Failing after 8s

Since no release has been published in ~11 months, install monarchmoney
directly from git main branch which contains the fix for flexible budgets.
Also updates gql to >=4.0 as required by the main branch.
This commit is contained in:
Ben
2025-12-25 04:35:06 +00:00
parent 52f7a746f9
commit 4382b02450
2 changed files with 56 additions and 75 deletions

View File

@@ -19,8 +19,8 @@ requires-python = ">=3.12"
dependencies = [ dependencies = [
"mcp[cli]>=1.0.0", "mcp[cli]>=1.0.0",
"fastmcp>=0.4.1", "fastmcp>=0.4.1",
"monarchmoney>=0.1.15", "monarchmoney @ git+https://github.com/hammem/monarchmoney.git",
"gql>=3.4,<4.0", "gql>=4.0",
"python-dotenv>=1.0.0", "python-dotenv>=1.0.0",
"pydantic>=2.0.0", "pydantic>=2.0.0",
"starlette>=0.35.0", "starlette>=0.35.0",

View File

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