Development
Layout
Section titled “Layout”Directoryavenir_mcp/ — the server (see Architecture)
- …
Directorytests/ — unit tests, protocol tests, documentation and hygiene tests
- …
Directoryevals/ — the demo budget, a stand-in for YNAB’s API, the agent evaluation
- …
Directorydocsgen/ — generates the tool reference, the error catalogue and the examples
- …
Directorydocs/ — this site (Astro Starlight, English, French, Spanish)
- …
- AGENTS.md — the contract for contributors, human or not
- justfile — every command below
- pyproject.toml, uv.lock — the Python project, locked
Set up
Section titled “Set up”git clone https://github.com/mathbeal/avenir-mcp && cd avenir-mcpuv sync # Python 3.14 and the locked dependenciesjust check # every gate CI runsThe checks
Section titled “The checks”just check runs, in CI’s order:
| Check | Command | Fails when |
|---|---|---|
| format | ruff format --check |
a file is not formatted |
| lint | pylint |
the score is below 10.00 |
| ruff | ruff check |
a docstring of the package is not in Google style or leaves out an argument, the return value or an exception raised; imports are not sorted; bandit’s security checks find a risky pattern (TLS not verified, a shell command, a password in the code…) |
| dependencies | deptry . |
the code imports a package pyproject.toml does not declare, or declares one it does not use |
| types | mypy (strict) |
any type error |
| tests | pytest |
a test fails, any warning is raised, or coverage of lines or branches is below 100 % |
| vocabulary | lexdrift check avenir_mcp --baseline lexdrift.lock |
a new word appears for an idea already named |
| lock | uv lock --check |
uv.lock does not match pyproject.toml |
CI also runs typos, zizmor on the workflows, pip-audit on the locked dependencies,
gitleaks on every commit of the history (just secrets, with Docker),
the documentation build with the tests of its own code, CodeQL and the OpenSSF Scorecard
(once the repository is public), a weekly comparison of YNAB’s API with its snapshot
(just api-drift), and the official MCP Inspector
(just inspect), which checks the server as a client sees it on the demo budget: its
lists, the portability of its tool schemas, and one call of each kind. The test suite runs on Linux and macOS with Python 3.12,
3.13 and 3.14, and on Windows with Python 3.14 (on a pull request, macOS tries 3.14 only:
its runners cost ten Linux ones); coverage is enforced on Linux and macOS,
where the file-permission checks apply. Python 3.15 runs too, as an experiment: a failure there is a warning,
not a red check. On
a pull request, every commit must be signed off and the title must start with the kind of
change. Two checks must be green: CI passed, which stands for every job of the
quality workflow, and MCP Inspector, a workflow of its own so that its badge shows it
alone.
Dependencies
Section titled “Dependencies”Renovate opens pull requests every Monday morning:
| Update | Handling |
|---|---|
| development tools, CI actions, the documentation site (minor and patch) | grouped, merged by itself once CI passes |
fastmcp, httpx, pydantic — they run in front of users’ budgets |
one pull request each, reviewed by hand; the evaluation runs before a fastmcp update |
| any major version | one pull request each, reviewed by hand |
| a known vulnerability | at once, whatever the day |
A new release waits three days before Renovate proposes it, so a broken or malicious version withdrawn quickly never reaches the project.
| Kind | Files | What they check |
|---|---|---|
| Unit | test_classifier, test_triage, test_writes, test_reconcile, test_forecast, test_analytics, test_journal, test_client |
the pure logic and the HTTP client, with invented data |
| Properties | test_properties |
with Hypothesis, rules that hold for any input: amounts round-trip, spreading keeps every cent, months add up, cursors, bank text, confirmation fingerprints |
| Protocol | test_protocol*, test_context, test_policy |
tools through an in-memory MCP client: schemas, annotations, confirmation paths, undo |
| Documentation | test_docs |
generated pages and examples match the code; every page exists in French and Spanish; every environment variable is documented |
| API coverage | test_api_coverage |
every operation of YNAB’s API is used by a tool, planned or left out with a reason; the client calls only documented paths |
| Hygiene | test_hygiene |
no IBAN, token, statement, home path or Finder copy in the repository |
| Evaluation | test_evals |
the evaluation’s own checks are right |
Tests are written first. No test calls YNAB.
just mutate runs mutation testing (mutmut) on the modules that compute: it changes the
code on purpose, some 1,500 times, and checks that a test fails each time. The changes no
test notices point to the tests to write; many are harmless, such as a message’s wording.
Documentation
Section titled “Documentation”uv run python -m docsgen # tool pages, error catalogue, examplesjust docs # build the site in three languages; broken links failjust docs-serve # live preview on http://localhost:4321/avenir-mcp/docsgen runs avenir-mcp on the demo budget and writes what it really answers, with the
date fixed and random ids replaced. Hand-written pages exist in English, French and
Spanish; a test fails when one is missing.
Evaluation
Section titled “Evaluation”just evaluate # all tasks, Sonnet, about 1 USD of your Claude planuv run python -m evals.run --task classify --model haikuSee Evaluation.
Commits and releases
Section titled “Commits and releases”- Commit messages start with a type —
feat:,fix:,docs:,refactor:,test:,build:,ci:,chore:— becauseCHANGELOG.mdis generated from them by git-cliff. - To release:
just changelog, commit, tagvX.Y.Zmatchingavenir_mcp.__version__, and publish a GitHub release. Thepublishworkflow builds, runstwine check --strictand uploads to PyPI through Trusted Publishing: no token is stored.
Unofficial project. We are not affiliated, associated, or in any way officially connected with YNAB or any of its subsidiaries or affiliates. YNAB and You Need A Budget are registered trademarks of YNAB. avenir-mcp is provided as is, without warranty, and is not financial advice. Legal notice