Financial Context Engine
README.md
# Financial Context Engine
An MCP (Model Context Protocol) server that exposes personal financial data — transaction ledger, portfolio holdings, live/historical market prices, and quantitative risk metrics — as standardized Tools, Resources, and Prompts. Any MCP host (Claude Desktop, Claude.ai, Cursor) can connect to it and reason over **real, deterministically computed numbers** instead of estimating them.
**This project is 100% pure Python. It runs natively on Windows — no WSL, no Docker, no Linux subsystem required.** DuckDB, FastMCP, numpy/pandas, and yfinance are all pip-installable packages with native Windows wheels.
---
## Architecture
```
┌──────────────────────────────────────────────┐
│ MCP HOST (Claude Desktop, etc.) │
└────────────────────┬───────────────────────────┘
│ MCP protocol (stdio)
┌────────────────────▼───────────────────────────┐
│ FINANCIAL CONTEXT ENGINE (this repo) │
│ ┌───────────┐ ┌────────────┐ ┌──────────────┐ │
│ │ RESOURCES │ │ TOOLS │ │ PROMPTS │ │
│ └─────┬─────┘ └─────┬──────┘ └──────┬───────┘ │
└────────┼─────────────┼───────────────┼──────────┘
│ │ │
┌────────▼─────────────▼───────────────▼──────────┐
│ DuckDB │ Rate Limiter + yfinance │ Quant │
│ (local) │ (token bucket, cached) │ (numpy) │
└───────────────────────────────────────────────────┘
```
No LLM lives inside this server. It's a data + compute backend that any MCP-compatible chat client connects to.
---
## Setup on Windows (VS Code, no WSL)
### 1. Install Python
Python 3.11+ from [python.org](https://www.python.org/downloads/) (check "Add to PATH" during install). Verify in a **regular Windows PowerShell or VS Code terminal** (not WSL):
```powershell
python --version
```
### 2. Open the project folder in VS Code
`File > Open Folder...` → select the `financial-context-engine` folder.
### 3. Create a virtual environment
In the VS Code terminal (make sure it's PowerShell or Command Prompt, not a WSL terminal — check the terminal dropdown in the top-right of the terminal panel):
```powershell
python -m venv .venv
.venv\Scripts\activate
```
Your prompt should now show `(.venv)`. If PowerShell blocks the activation script with an execution-policy error, run this once (you've hit this before with other projects):
```powershell
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
```
### 4. Install dependencies
```powershell
pip install -r requirements.txt
```
### 5. Copy the environment template
```powershell
copy .env.example .env
```
Defaults work out of the box (in-memory rate limiting, no Redis needed). Only edit `.env` if you want an Alpha Vantage API key or Redis-backed rate limiting later.
### 6. Seed demo data
```powershell
python -m db.seed
```
This creates `data/finance.duckdb` with ~6 months of synthetic transactions and 7 sample holdings — safe to demo, no real financial data involved.
### 7. Run the full test suite
```powershell
pytest tests/ -v
```
You should see **33 passed**.
### 8. Run the server in MCP Inspector (interactive dev mode)
```powershell
fastmcp dev server.py
```
This opens a browser-based inspector where you can call every tool and view every resource manually — no LLM needed, no config files needed. This is the fastest way to confirm everything works after any change.
---
## Connecting to Claude Desktop
Once you've verified the server works in MCP Inspector, add it to Claude Desktop's config so you can chat with it directly.
1. Open Claude Desktop → Settings → Developer → Edit Config (or find `claude_desktop_config.json` directly — on Windows it's usually at `%APPDATA%\Claude\claude_desktop_config.json`).
2. Add an entry (use the **full absolute Windows path** to your project and to the venv's python.exe):
```json
{
"mcpServers": {
"financial-context-engine": {
"command": "C:\\path\\to\\financial-context-engine\\.venv\\Scripts\\python.exe",
"args": ["C:\\path\\to\\financial-context-engine\\server.py"]
}
}
}
```
3. Restart Claude Desktop. You should see a 🔨 tools icon indicating the server connected — try asking: *"What's my current net worth?"* or *"Compute my portfolio's Sharpe ratio."*
---
## Project Structure
```
financial-context-engine/
├── server.py # MCP server entrypoint — run this
├── db/
│ ├── schema.sql # DuckDB table definitions
│ ├── models.py # Pydantic models (typed, shared everywhere)
│ ├── store.py # LedgerStore — the only module that touches SQL
│ └── seed.py # generates synthetic demo data
├── market/
│ ├── rate_limiter.py # token bucket (in-memory + Redis modes)
│ ├── client.py # yfinance wrapper: cache -> rate limiter -> fetch
│ ├── history.py # historical price fetching for quant calcs
│ └── demo.py # standalone script proving the limiter works
├── analytics/
│ └── quant.py # Sharpe, Monte Carlo VaR, correlation, HHI — pure numpy
├── mcpapp/ # (named mcpapp, not mcp, to avoid shadowing the MCP SDK)
│ ├── context.py # wires store + rate limiter + market client together
│ ├── tools.py # @mcp.tool() definitions
│ ├── resources.py # @mcp.resource() definitions
│ ├── prompts.py # @mcp.prompt() definitions
│ └── stream.py # background polling for "live" prices
└── tests/ # 33 tests across every module above
```
---
## What Each Tool Does
| Tool | Purpose |
|---|---|
| `get_market_quote(symbols)` | Current price/P-E/52-week range, rate-limited + cached |
| `query_ledger(category, start_date, min_amount)` | Filter transaction history |
| `get_recent_transactions(days)` | Last N days of transactions |
| `get_net_worth()` | Cash + invested totals, per-account breakdown |
| `compute_portfolio_health_report()` | Sharpe ratio, Monte Carlo VaR (95%/99%, 1-day/1-month), correlation matrix, concentration (HHI) — **all computed in Python, not estimated by the model** |
| `get_live_prices()` | Latest background-polled prices for your holdings |
| `get_rebalance_suggestions(target_allocation)` | Dollar-value buy/sell suggestions vs. a target allocation |
## What Each Resource Exposes
| Resource URI | Content |
|---|---|
| `finance://summary` | Net worth snapshot |
| `finance://transactions/recent` | Last 30 days of transactions |
| `finance://portfolio/holdings` | Current holdings |
| `finance://portfolio/live` | Background-polled live prices |
| `finance://api-usage` | Rate limiter decision log (allowed/blocked/cached) — transparency into throttling |
---
## Design Notes
**Why deterministic Python math instead of letting the LLM calculate?** LLMs are unreliable at multi-step arithmetic, especially statistics like Sharpe ratio or Value-at-Risk where a small error compounds. Every number this server returns is computed by numpy/pandas from real data, so the model's job is reasoning and communication, not arithmetic.
**Why rate-limit market data calls?** Free-tier providers (yfinance's soft limits, Alpha Vantage's 25 calls/day) get exhausted fast if an LLM calls them on every message. The token-bucket limiter (reused from a standalone Distributed Rate Limiter project) plus a 60-second TTL cache keeps usage sane — see `market/demo.py` for a runnable proof: 50 rapid requests → 5 fetched, 30 cache hits, 15 correctly throttled.
**Why polling instead of true SSE push for "live" prices?** True MCP resource-subscription push depends on transport/session details that vary across FastMCP versions and host clients, and is genuinely fragile to get right without a Linux dev environment. A background-thread poller (`mcpapp/stream.py`) is the reliable choice here — it reads from the same rate-limited, cached client, so it never floods the market data provider even while "live." If you later deploy this on Linux/Codespaces, the polling loop can be swapped for `mcp.send_resource_updated()` calls without touching the state management.
**Security & privacy:**
- All credentials load from `.env` (gitignored), never logged, never returned in tool output.
- `data/finance.duckdb` is local-only and gitignored — nothing syncs to the cloud.
- The only outbound network calls are to the market data provider (ticker symbol only, no personal data).
- Redis mode (for shared rate-limiting across multiple server instances) is opt-in via `.env`, not required for normal use.
---
## Running Individual Test Files
```powershell
pytest tests/test_store.py -v # data layer (6 tests)
pytest tests/test_rate_limiter.py -v # token bucket (6 tests)
pytest tests/test_market_client.py -v # market data + cache (5 tests)
pytest tests/test_quant.py -v # Sharpe/VaR/correlation (10 tests)
pytest tests/test_stream.py -v # live price polling (3 tests)
pytest tests/test_tools.py -v # MCP tool logic (3 tests)
python -m tests.smoke_test # end-to-end, no pytest needed
python -m market.demo # rate limiter demo output
```
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues