cbc46314db
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
97 lines
3.7 KiB
C#
97 lines
3.7 KiB
C#
using System.ComponentModel;
|
|
using System.Text.Json;
|
|
using ModelContextProtocol.Server;
|
|
using MoneyMap.Models;
|
|
using MoneyMap.Services;
|
|
|
|
namespace MoneyMap.Mcp.Tools;
|
|
|
|
[McpServerToolType]
|
|
public static class BudgetTools
|
|
{
|
|
private static readonly JsonSerializerOptions JsonOptions = new() { WriteIndented = true };
|
|
|
|
[McpServerTool(Name = "get_budget_status"), Description("Get all active budgets with current period spending vs. limit.")]
|
|
public static async Task<string> GetBudgetStatus(
|
|
[Description("Date to calculate status for (defaults to today)")] string? asOfDate = null,
|
|
IBudgetService budgetService = default!)
|
|
{
|
|
DateTime? date = null;
|
|
if (!string.IsNullOrWhiteSpace(asOfDate) && DateTime.TryParse(asOfDate, out var parsed))
|
|
date = parsed;
|
|
|
|
var statuses = await budgetService.GetAllBudgetStatusesAsync(date);
|
|
|
|
var result = statuses.Select(s => new
|
|
{
|
|
s.Budget.Id,
|
|
Category = s.Budget.DisplayName,
|
|
s.Budget.Amount,
|
|
Period = s.Budget.Period.ToString(),
|
|
s.PeriodStart,
|
|
s.PeriodEnd,
|
|
s.Spent,
|
|
s.Remaining,
|
|
PercentUsed = Math.Round(s.PercentUsed, 1),
|
|
s.IsOverBudget
|
|
}).ToList();
|
|
|
|
return JsonSerializer.Serialize(result, JsonOptions);
|
|
}
|
|
|
|
[McpServerTool(Name = "create_budget"), Description("Create a new budget for a category or total spending.")]
|
|
public static async Task<string> CreateBudget(
|
|
[Description("Budget amount limit")] decimal amount,
|
|
[Description("Period: Weekly, Monthly, or Yearly")] string period,
|
|
[Description("Start date for period calculation, e.g. 2026-01-01")] string startDate,
|
|
[Description("Category name (omit for total spending budget)")] string? category = null,
|
|
IBudgetService budgetService = default!)
|
|
{
|
|
if (!Enum.TryParse<BudgetPeriod>(period, true, out var budgetPeriod))
|
|
return $"Invalid period '{period}'. Must be Weekly, Monthly, or Yearly.";
|
|
|
|
var budget = new Budget
|
|
{
|
|
Category = category,
|
|
Amount = amount,
|
|
Period = budgetPeriod,
|
|
StartDate = DateTime.Parse(startDate),
|
|
IsActive = true
|
|
};
|
|
|
|
var result = await budgetService.CreateBudgetAsync(budget);
|
|
|
|
return JsonSerializer.Serialize(new { result.Success, result.Message, BudgetId = budget.Id }, JsonOptions);
|
|
}
|
|
|
|
[McpServerTool(Name = "update_budget"), Description("Update an existing budget's amount, period, or active status.")]
|
|
public static async Task<string> UpdateBudget(
|
|
[Description("Budget ID to update")] int budgetId,
|
|
[Description("New budget amount")] decimal? amount = null,
|
|
[Description("New period: Weekly, Monthly, or Yearly")] string? period = null,
|
|
[Description("Set active/inactive")] bool? isActive = null,
|
|
IBudgetService budgetService = default!)
|
|
{
|
|
var budget = await budgetService.GetBudgetByIdAsync(budgetId);
|
|
if (budget == null)
|
|
return "Budget not found";
|
|
|
|
if (amount.HasValue)
|
|
budget.Amount = amount.Value;
|
|
|
|
if (!string.IsNullOrWhiteSpace(period))
|
|
{
|
|
if (!Enum.TryParse<BudgetPeriod>(period, true, out var budgetPeriod))
|
|
return $"Invalid period '{period}'. Must be Weekly, Monthly, or Yearly.";
|
|
budget.Period = budgetPeriod;
|
|
}
|
|
|
|
if (isActive.HasValue)
|
|
budget.IsActive = isActive.Value;
|
|
|
|
var result = await budgetService.UpdateBudgetAsync(budget);
|
|
|
|
return JsonSerializer.Serialize(new { result.Success, result.Message }, JsonOptions);
|
|
}
|
|
}
|