Overview
Treasury is a self-hosted wealth operating system I built for private use. It combines brokerage investments from Trading 212 and Interactive Brokers with crypto, property, cash, pensions, manually valued assets, liabilities, and cash flows, then normalizes them into one view of net worth, performance, income, and allocation.
I worked across product scope, architecture, broker ingestion, financial services, the read-only MCP surface, and automated verification. The hard part was not drawing charts. It was preserving the meaning of money as data crossed brokers, currencies, storage, derived calculations, and an AI client.
Documented stage: private-use system. The AI surface is read-only; scenario tools calculate proposed actions but do not place trades or persist them.
Financial signal path
A number is useful only if the system can preserve where it came from, how it was normalized, and whether the sources still agree.
Sources
Broker + manual inputs
Trading 212, IBKR, crypto, property, cash, pensions, assets, and liabilities.
Correctness boundary
Normalize + reconcile
Currency, duplicates, cash semantics, cost basis, source failures, and freshness.
Product surface
Wealth model + bounded MCP
Net worth, performance, income, scenarios, and reliability-aware tool responses.
That boundary changes the product question from “can I display this value?” to “what would make this value misleading?”
Three boundaries that define the product
01. Integrate source behavior, not just endpoints
The Trading 212 client handles pagination, request pacing, retries, and rate limits, including Retry-After. Interactive Brokers has implemented paths for Client Portal Gateway data, Flex report retrieval and XML parsing, and CSV imports.
The point is not the number of connectors. Each source has different freshness, authentication, pagination, and failure behavior, so ingestion has to preserve source-specific diagnostics instead of pretending every sync is equivalent.
02. Reconcile financial meaning before reporting totals
Treasury explicitly prevents broker cash from being counted twice when it appears both as a holding and in an account snapshot. It also avoids subtracting a margin debit twice when the same debt is already represented as negative cash.
Reconciliation checks stored holdings and cash against broker-reported totals and surfaces missing exchange rates, duplicate broker references, missing cost basis, source failures, and stale synchronization. These are accounting semantics expressed as software constraints.
03. Give AI a governed view, not database access
The reviewed snapshot defines nine MCP tools for status, portfolio briefings, holdings, instrument detail, income, goals, debt, cash flow, and proposed-action analysis.
The access boundary validates signed JWTs against configured issuer, audience, allowed subject, and project-role claims, and fails closed on verification errors. Tool responses distinguish no data, stale data, partial data, and unavailable sources, and include source-freshness information.
That means an AI client receives both the answer and evidence about whether the underlying inputs are trustworthy enough to interpret.
Deterministic what-if, probabilistic interpretation
The scenario engine evaluates proposed buys and sells in application code. It calculates allocation changes, income effects, projections, and goal impact without executing trades or persisting the proposed actions.
Proposal
Describe a hypothetical action
A buy or sell request enters as data, not as an execution instruction.
Deterministic core
Calculate the consequences
Allocation, income, benchmark assumptions, and goal effects are computed in application code.
Interpretation
Explain the result
The AI can reason over the bounded response without gaining trade execution.
This division matters more than adding a generic “AI assistant.” It keeps financial calculation and authorization in deterministic application boundaries.
Verification
A regression test covers a subtle historical-FX failure: a transaction imported during synchronization must become visible to exchange-rate backfill and be resolved in the same run. The test controls external inputs and checks the stored pipeline result, rather than testing a helper in isolation.
At the reviewed 19 September 2026 snapshot, the successful GitHub Actions run included Ruff, backend pytest tests, Python and JavaScript dependency audits, TypeScript checking, the frontend build, and Playwright. The inspected job log ended with 111 Playwright tests passed.
That is a dated regression signal, not a claim of 100% coverage or independently audited financial accuracy. Some tests isolate behavior without exercising every live broker path or the complete OAuth journey.
Engineering detail
The main story is the set of trust boundaries. These notes keep the lower-level integration and verification evidence available without turning the case study into a repository audit.
Technical detail / 01Broker ingestion, fallback paths, and freshness
Trading 212 API ingestion supports paced requests, pagination, retry handling, and explicit rate-limit responses. Interactive Brokers supports a Client Portal path for live positions/account data, a Flex Web Service path for report retrieval and XML parsing, and CSV imports as a fallback.
Those modes should not be read as a claim that every path is simultaneously configured or independently verified against a live account. The useful engineering property is that source-specific failure and freshness state can survive ingestion instead of disappearing behind one generic “sync” flag.
Technical detail / 02Financial correctness as regression behavior
Net-worth calculation has explicit guards for two domain errors: counting broker cash twice when it is represented in more than one source structure, and subtracting a margin debit twice when negative cash already carries the liability.
Reconciliation adds diagnostics for missing FX rates, duplicate broker references, missing cost basis, stale synchronization, and source failures. Historical currency backfill is also covered by a pipeline regression where newly imported transactions must be resolved during the same synchronization run.
These checks are more useful than claiming that every financial number is “accurate.” They show where correctness can fail and how the software detects specific classes of error.
Technical detail / 03Read-only MCP containment and evidence limits
The MCP surface is a bounded product interface over existing read services, not unrestricted database access. Its authorization layer validates signed tokens and the configured project-role boundary; verification failures deny access.
Tool payloads carry provenance and state information, and the what-if tool remains pure computation even though its input resembles an action. It does not write portfolio state or execute a trade.
The reviewed CI snapshot supports automated backend and browser regression testing. It does not establish complete live-integration coverage, a full OAuth audit, universal AI-client compatibility, customer adoption, or commercial scale.
Outcome
Treasury currently combines multi-asset wealth tracking, brokerage ingestion, financial reconciliation, net-worth and performance views, deterministic scenario analysis, and read-only AI access behind explicit reliability states.
The strongest lesson is domain-specific: in financial software, missing, duplicated, stale, or semantically inconsistent data is not a presentation problem. It is product state that the system has to model.
Treasury remains a private-use product. This case study does not claim trade execution, audited financial accuracy, public adoption, or commercial traction.