Skip to content

Add budget creation MCP tool#70

Merged
RadCod3 merged 5 commits intomainfrom
feat/40-add-budget-create
Jan 31, 2026
Merged

Add budget creation MCP tool#70
RadCod3 merged 5 commits intomainfrom
feat/40-add-budget-create

Conversation

@RadCod3
Copy link
Owner

@RadCod3 RadCod3 commented Jan 31, 2026

This PR adds an MCP tool to create budgets. Also adds a temp fix for available budgets which seems to have broken again.

@coderabbitai
Copy link

coderabbitai bot commented Jan 31, 2026

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added budget creation with configurable auto-budget settings (type, amount, period, currency)
    • Added budget deletion capability
    • Added bulk transaction request enhancements (atomic bulk creation)
  • Bug Fixes

    • Improved currency ID handling in API responses for consistent serialization
  • Tests

    • Added comprehensive unit and integration tests for budget workflows
  • Documentation

    • Updated README and tool counts to include new budget tool and description

✏️ Tip: You can customize this high-level summary in your review settings.

Walkthrough

Adds budget creation end-to-end: new CreateBudgetRequest model, BudgetService.create_budget(req) update, MCP tool create_budget, FireflyClient.delete_budget, model coercion for currency_id, and tests/fixtures to exercise creation and cleanup.

Changes

Cohort / File(s) Summary
Client API
src/lampyrid/clients/firefly.py
Added async def delete_budget(budget_id: str) -> bool sending DELETE /api/v1/budgets/{budget_id}, invoking API error handling, and returning True on 204.
Request Model
src/lampyrid/models/lampyrid_models.py
Added CreateBudgetRequest Pydantic model (name, auto_budget_* fields, active, notes) with post-validation and extra='forbid'.
Firefly Models
src/lampyrid/models/firefly_models.py
Added _coerce_to_str(v) and applied BeforeValidator to ArrayEntryWithCurrencyAndSum.currency_id to coerce integer IDs to strings.
Service Layer
src/lampyrid/services/budgets.py
Changed create_budget() signature to accept CreateBudgetRequest; maps request into BudgetStore including auto-budget enum conversions and stringified amounts.
MCP Tool
src/lampyrid/tools/budgets.py
Added MCP tool create_budget(req: CreateBudgetRequest) -> Budget that delegates to budget_service.create_budget(req) and exposes the tool tag {'budgets','create'}.
Tests — Fixtures & Conftest
tests/conftest.py, tests/fixtures/budgets.py
Switched test budget creation to CreateBudgetRequest; added budget_cleanup fixture and make_create_budget_request() factory for tests.
Tests — Integration & Unit
tests/integration/test_budgets.py, tests/unit/test_budgets_service.py, tests/unit/test_models.py
Added integration tests for budget creation scenarios; updated unit tests to use CreateBudgetRequest; added model tests for CreateBudgetRequest.
Docs / Config
README.md, pyproject.toml
Updated README tool counts and description; added pytest unit marker.

Sequence Diagram(s)

sequenceDiagram
  participant MCP_Tool as "MCP Tool\ncreate_budget"
  participant BudgetService as "BudgetService\n.create_budget(req)"
  participant FireflyClient as "FireflyClient\n.create_budget / .delete_budget"
  participant FireflyAPI as "Firefly III API\n(/api/v1/budgets)"

  rect rgba(200,230,201,0.5)
    MCP_Tool->>BudgetService: call create_budget(req)
  end

  rect rgba(187,222,251,0.5)
    BudgetService->>FireflyClient: map req -> BudgetStore, call create_budget(store)
  end

  rect rgba(255,224,178,0.5)
    FireflyClient->>FireflyAPI: POST /api/v1/budgets (body)
    FireflyAPI-->>FireflyClient: 201 Created (budget JSON)
    FireflyClient-->>BudgetService: Budget model
    BudgetService-->>MCP_Tool: Budget result
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 I hopped through models, tools, and tests today,
I wrapped requests in carrots, then sent them away.
Budgets bloom in burrows, tidy and neat,
Create, then delete — a tidy little feat! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description check ✅ Passed The PR description accurately describes the changeset, mentioning the addition of an MCP tool to create budgets and a temporary fix for available budgets, which aligns with the code changes.
Linked Issues check ✅ Passed The PR successfully implements all requirements from issue #40: adds create_budget tool with required parameters (name, auto_budget_type, auto_budget_amount, auto_budget_period, auto_budget_currency_code, active, notes) and uses the correct API endpoint.
Out of Scope Changes check ✅ Passed All changes are within scope of issue #40: create_budget implementation, supporting models, service layer updates, tests, and documentation. Changes align with the feature request objectives.
Docstring Coverage ✅ Passed Docstring coverage is 96.77% which is sufficient. The required threshold is 80.00%.
Title Check ✅ Passed Title check skipped as CodeRabbit has written the PR title.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/40-add-budget-create

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai bot changed the title @coderabbit Implement budget creation and deletion operations Jan 31, 2026
@codecov-commenter
Copy link

codecov-commenter commented Jan 31, 2026

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 92.85714% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 97.56%. Comparing base (eb2b12b) to head (943d8bb).

Files with missing lines Patch % Lines
src/lampyrid/models/firefly_models.py 57.14% 3 Missing ⚠️
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #70      +/-   ##
==========================================
- Coverage   97.62%   97.56%   -0.07%     
==========================================
  Files          19       19              
  Lines        3080     3118      +38     
==========================================
+ Hits         3007     3042      +35     
- Misses         73       76       +3     
Flag Coverage Δ
integration 97.56% <92.85%> (-0.07%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@RadCod3 RadCod3 changed the title Implement budget creation and deletion operations Add budget creation MCP tool Jan 31, 2026
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/lampyrid/models/lampyrid_models.py`:
- Around line 701-740: Add a model-level validator on CreateBudgetRequest that
enforces the documented combinations: when auto_budget_type is set (i.e., not
None and not 'none') then auto_budget_amount and auto_budget_period must be
non-None (and optionally validate auto_budget_amount > 0 is already covered); if
those fields are missing raise a ValueError with a clear message. Implement this
using pydantic v2's `@model_validator`(mode='after') on the CreateBudgetRequest
class and reference the fields auto_budget_type, auto_budget_amount, and
auto_budget_period in the check.
🧹 Nitpick comments (2)
tests/fixtures/budgets.py (1)

71-90: Guard against incomplete auto-budget payloads in the factory.

If auto_budget_type is set, the API expects an amount and period. The helper currently allows missing values, which can lead to invalid requests in tests. Consider adding a small validation guard.

🔧 Suggested guard
 def make_create_budget_request(
     name: str,
     auto_budget_type: Literal['none', 'reset', 'rollover'] | None = None,
     auto_budget_amount: float | None = None,
     auto_budget_period: Literal['daily', 'weekly', 'monthly', 'quarterly', 'half-year', 'yearly']
     | None = None,
     auto_budget_currency_code: str | None = None,
     active: bool = True,
     notes: str | None = None,
 ) -> CreateBudgetRequest:
     """Create a CreateBudgetRequest for testing."""
+    if auto_budget_type is not None and (
+        auto_budget_amount is None or auto_budget_period is None
+    ):
+        raise ValueError(
+            "auto_budget_amount and auto_budget_period are required when auto_budget_type is set"
+        )
     return CreateBudgetRequest(
         name=name,
         auto_budget_type=auto_budget_type,
         auto_budget_amount=auto_budget_amount,
         auto_budget_period=auto_budget_period,
         auto_budget_currency_code=auto_budget_currency_code,
         active=active,
         notes=notes,
     )
tests/integration/test_budgets.py (1)

183-291: Consider using the new CreateBudgetRequest factory for validated payloads.

These tests construct raw dicts; using make_create_budget_request() would validate inputs and keep tests aligned with model changes. Example for one test (apply similarly to others):

♻️ Example adjustment
+from tests.fixtures.budgets import make_create_budget_request
 ...
 async def test_create_budget_simple(mcp_client: Client, budget_cleanup: List[str]):
     """Test creating a basic budget with just a name."""
-    result = await mcp_client.call_tool('create_budget', {'req': {'name': 'Test Created Budget'}})
+    req = make_create_budget_request(name='Test Created Budget')
+    result = await mcp_client.call_tool('create_budget', {'req': req.model_dump()})
     budget = Budget.model_validate(result.structured_content)
     budget_cleanup.append(budget.id)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@README.md`:
- Around line 162-170: The Budget Management Markdown table needs proper spacing
and surrounding blank lines to satisfy MD058/MD060: add a blank line before the
table (after the "### Budget Management (6 tools)" heading if needed) and a
blank line after the table, and update the header and separator rows so each
cell and each pipe has spaces (e.g., ensure the header row uses " | " between
columns and the separator row uses " | --- | --- | " style with spaces around
pipes). Apply these changes to the "Budget Management" table that lists tools
like list_budgets, get_budget, get_budget_spending, get_budget_summary,
get_available_budget, and create_budget.

@RadCod3 RadCod3 merged commit dfdc711 into main Jan 31, 2026
5 checks passed
@RadCod3 RadCod3 deleted the feat/40-add-budget-create branch January 31, 2026 12:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add budget creation tool

2 participants