firma
firma is a local-first, AI-native MCP server for managing overseas stock investments, personal finances, and portfolio analytics — all stored locally on your machine.
Portfolio Management: View holdings with average cost, P&L, and market value (
show_portfolio); view cached price snapshots (show_prices); sync latest prices from Finnhub (sync_prices).Transaction Tracking: Record buy/sell/deposit/dividend/tax entries (
add_txn), edit (edit_txn) or delete (delete_txn) by ID, and list history with optional ticker filter (show_txns).Balance Sheet Management: Add/update monthly asset and liability entries in KRW (
add_balance), view with optional period filter (show_balance), and delete entries (delete_balance).Cash Flow Management: Add/update monthly income and expense entries in KRW (
add_flow), view with optional period filter (show_flow), and delete entries (delete_flow).Financial Reporting: Generate a period summary with computed net worth and net flow (
report_settle).Market Research via Finnhub: Fetch company news (
show_news), insider transactions (show_insider), SEC-reported financials (show_financials), and earnings calendar (show_earnings).
All commands support --json output for scripting and piping.
You: Here's my IBKR trade history [trades.csv]. Set up firma.
Claude: I see 47 transactions. Logging in chronological order... done.
Syncing prices and FX history... your portfolio: $179K, +61% all-time. TSLA is 78%.
You: My portfolio feels really volatile lately. Should I be worried?
Claude: TSLA is 74% of your equity — a 10% TSLA move is a 7% net worth move.
Cash flow is solid at $6.4k/month saved. The volatility is market, not lifestyle.
You: That July expense spike looks alarming.
Claude: That was $57k in TSLL — a leveraged bet, not spending.
Strip it out: expenses flat at ~$7k/month, savings rate 47.8%.
You: Give me a full overview with charts.
Claude: Net worth: $294k → $490k in 8 months, pulled back to $427k with TSLA's Q1 dip.
[builds net worth trend, income vs expenses, portfolio allocation, unrealized P&L]Why firma
Talks to Claude natively.
firma mcp installwires firma into Claude Desktop. Every command you can run in the terminal, Claude can call through MCP — log trades, sync prices, render charts, reason about your data.Local-first, no exceptions. Everything lives in
~/.firma/firma.db. No server, no sync, no account. Your financial data never leaves your machine.Multi-market, one stored currency. Track holdings across 9 markets (US, KRX, KOSDAQ, JP, HK, LSE, XETRA, NSE, TW) — plus non-stock assets like crypto, commodities, and real estate. Every value is stored in USD and displayed in the currency you pick, with historical FX rates from FRED — so a 2018 balance shows the 2018 exchange rate, not today's.
Transactions as source of truth. No holdings table to drift out of sync. Portfolio, cost basis, and P&L are always derived live from your trade log.
A daily brief that actually advises.
get_briefdoesn't just dump data — it returns a weekly stance (lean aggressive or defensive), ranked moves (deploy idle cash, derisk, rebalance, …), and a watchlist of new tickers, all computed deterministically from your holdings, cash flow, and macro signals. It also bundles macro signals, commodity prices, the dividend calendar, global macro (World Bank), and active disaster alerts (GDACS) in one call — no extra API keys needed for the global data.Developer-friendly.
--jsonon every read command. Three clean verb groups:add,show,report.
Get started
Two ways to install — both work the same way once set up.
macOS Installer
Download and double-click. Node.js is bundled — nothing to install first. API keys are configured via setup dialogs (opens Finnhub + FRED in your browser, then prompts you to paste each key). Claude Desktop is connected automatically.
↓ Download firma-mac-arm64.pkg
npm
# 1. Install
npm install -g @evan-moon/firma
# 2. Set API keys (both free)
firma config set finnhub-key YOUR_KEY # finnhub.io — prices, news, earnings
firma config set fred-key YOUR_KEY # fred.stlouisfed.org — macro & FX history
# 3. Connect Claude Desktop
firma mcp install
# Restart Claude Desktop — firma tools will appear in the toolbar.Drop your data into Claude. Paste a CSV, brokerage export, or plain text — Claude logs everything and syncs prices automatically.
Prefer the terminal? Every MCP tool has a matching
firmacommand — see CLI reference.
If firma helps you track your money, please ⭐ star the repo — it's the cheapest way to help others find it.
CLI reference
--json is available on every read command. Alias: firma rm = firma delete.
Portfolio
Command | What it does |
| Holdings with P&L, avg cost, market value |
| Transaction history with running avg cost |
| Estimated annual income + per-ticker yield |
| HHI concentration by ticker, currency, sector, country |
| Portfolio value history; |
| Portfolio return vs SPY/QQQ (or custom benchmarks via |
| Volatility, drawdown, Sharpe, Sortino, beta — requires snapshots |
| Set up your goals (birth year, retirement target, target net worth, risk tolerance, notes) — every field optional |
| Show the stored profile |
Balance & Cash Flow
Command | What it does |
| Monthly asset & liability snapshot |
| Monthly income & expense entry |
| Balance + flow in one call (month-end) |
| Stored balance entries for a period |
| Stored cash flow entries for a period |
| Net worth trend + cash flow charts (combined) |
| Targeted views |
| Display in any supported currency — |
Transactions
Command | What it does |
| Record a transaction — a stock in any of 9 markets, or a non-stock asset (crypto / commodity / real estate) — type buy / sell / deposit / dividend / tax |
| Set the current value of non-stock holdings (they have no price feed) |
| Edit a transaction |
| Delete a transaction |
Snapshots
Command | What it does |
| Sync prices and record today's portfolio snapshot |
| Edit a snapshot entry (interactive picker) |
| Delete all entries for a date |
Research (Finnhub)
Command | What it does |
| Recent company news |
| Insider buy/sell transactions |
| SEC-reported quarterly financials (income, cash flow, balance sheet) |
| PEG ratio, P/S, FCF yield — computed from 8 quarters of SEC filings |
| Earnings calendar + EPS history |
Macro (FRED)
Command | What it does |
| VIX, 10Y yield, yield curve, USD index, HY spread, inflation, fed funds, FX + Economic Stress Index (0–100) + macro regime bias (Risk-on / Mixed / Risk-off) |
| Inspect cached FX history with |
Global Intelligence (no API key)
Command | What it does |
| World Bank macro (GDP, inflation, unemployment) + GDACS active disaster alerts in one view |
Daily Brief & Actions
Command | What it does |
| Daily intelligence brief: movers, news, earnings, macro, commodities, dividend calendar, world macro, disaster alerts (cached per day; |
| Fetch latest prices (Finnhub) + FX rate history (FRED) |
| FX history only — incremental backfill from your earliest entry date |
| Check setup status — API keys, data, FX cache |
| Register MCP server in Claude Desktop |
| Set Finnhub API key |
| Set FRED API key |
| Set home currency (KRW, USD, JPY, …) |
Claude integration (MCP)
After firma mcp install, Claude has full read/write access to your data through conversation. Two tools are available only via MCP:
Tool | What it does |
| Fetch any FRED time series by ID (800K+ series) |
| Search the FRED catalog by keyword |
get_brief is the primary entry point for any daily check-in or market question. In a single call it returns:
Stance — a deterministic weekly verdict (aggressive / mixed / defensive / contrarian-aggressive) at the intersection of market signal and your personal capacity (runway, goal pace, idle cash)
Moves — ranked recommendations: deploy idle cash, raise contributions, derisk, extend runway, rebalance, or play a tactical tilt — each with a quantified rationale and a
drill_downpointer to the tool that explains itWatchlist — new-ticker candidates surfaced from peers of what you already hold
Freshness — last-synced dates for prices and FX, so Claude knows when to
syncfirstPortfolio — holdings with weights, daily P&L, total cost vs market value
Concentration — HHI by ticker, sector, currency, country
Movers — top winners and losers for the day
News — recent headlines per holding
Earnings — upcoming earnings dates with EPS estimates
Economic calendar — high/medium-impact events for the week
Macro — FRED snapshot (VIX, 10Y yield, credit spread, fed funds, FX impact in home currency)
Stress & Regime — Economic Stress Index + Risk-on / Mixed / Risk-off bias
Commodities — WTI oil, gold, copper (via FRED — no extra key)
Dividend calendar — upcoming ex-dates and estimated income for held positions
World macro — GDP growth, inflation, unemployment across major economies (World Bank — no extra key)
Disaster alerts — active GDACS Orange/Red events (no extra key)
The recommendations are computed in code — analysis baked into the tool result, not improvised in prose. The show_* tools (show_concentration, show_macro, …) carry their dimension's recommendation too, so a drill-down stays consistent with the brief.
If today's snapshot is missing, get_brief records one automatically before assembling the brief, so daily history accrues even when you forget to run firma add snapshot.
show_valuation and show_world_intel are available for deeper drill-downs after reading the brief.
Prompts — type / in Claude Desktop to access guided workflows:
Prompt | What it does |
| Confirms column mapping then inserts every row in a single |
| Same flow for a net-worth spreadsheet (rows = months, columns = balance categories) → one |
| Same flow for an income/expense spreadsheet → one |
| Walks through balance + cash flow entry for the period, submits in one batch |
| Calls |
| Activates a financial-analyst persona — Claude leads with concentration risk, frames every number against net worth or runway, and combines portfolio + cash flow + macro into a single view |
| Captures your goals (birth year, retirement target, target net worth, risk tolerance, notes) so all future analysis is anchored to them — every field optional |
| Five plausible ways a position could go wrong over 12 months — concrete failure modes tied to actual data, with portfolio impact in dollars |
| Compares current allocation against your stated target, flags drift, suggests specific trades while accounting for tax cost and wash-sale risk |
| Scans unrealized losses, checks 30-day wash-sale rule, suggests similar-but-not-identical replacements, estimates tax savings by bracket |
| Models a market shock or macro shift on your actual portfolio with explicit beta assumptions you can override |
setup_status (called by Claude at the start of any conversation) also returns an analyst_context block — a lightweight version of the analyst persona that influences every reply without a manual prompt invocation.
Historical FX note: firma sync fx backfills daily FX rates (KRW, JPY, EUR, CNY, GBP, HKD, INR, TWD) from FRED starting at your earliest transaction date. Subsequent runs are increment-only. This means a 2018 balance in KRW uses the 2018 rate — not today's.
Architecture
Firma is a Yarn Berry monorepo with a layered, port-and-adapter design. The application layer never imports an external-API package directly — it talks to domain interfaces, and adapters implement those interfaces against specific services.
Workspace layout reflects the layers:
packages/
domain/ ports + types + routers, no external-API dep
domain/ market/ (Quote, StockSnapshot, Candle, news, …),
macro/ (series, country indicators, live FX, stress,
regime), event/ (world disaster events)
external-api/ raw API clients, no firma-domain dep
finnhub/ fred/ worldbank/ gdacs/ open-er-api/ yahoo-finance/
adapter/ the only layer that imports both sides
adapters/ provider registry — createMarketProviders, …
use-case/ business logic
portfolio/ brief/ advisor/
shared/ cross-cutting
db/ utils/
apps/
cli/ mcp/ docs/Import dependencies (A → B means "A imports B"):
apps/cli, apps/mcp
→ @firma/adapters data-clients.ts builds providers via the registry
→ @firma/domain commands/tools call domain clients directly
for simple reads (e.g. `show news`)
→ use-case packages richer flows (portfolio sync, brief)
use-case (portfolio, brief, advisor)
→ @firma/domain brief also composes @firma/advisor
@firma/adapters
→ @firma/domain implements MarketDataProvider / MacroDataProvider /
EventDataProvider
→ external-api packages calls the raw HTTP/RSS clients
external-api (finnhub, fred, worldbank, gdacs, open-er-api, yahoo-finance)
→ shared only pure API clients; no domain/adapter knowledge
@firma/domain
→ shared only the stable core; no external-api / adapter /
use-case / app dependency
shared (db, utils)
→ nothing cross-cutting leaf; imported by every layer aboveAt runtime, data flows the opposite way:
External API → @firma/adapters → domain client → use-case → cli / mcpDependency rule: external-API packages have zero firma-domain knowledge; domain packages have zero external-API knowledge. @firma/adapters is the only package that imports both sides. Application code (apps/cli, apps/mcp) talks to domain clients; the one place it touches @firma/adapters is data-clients.ts, which constructs the concrete providers.
Capabilities — each domain interface declares a capability set; the router picks a provider per capability:
Sub-domain | Capabilities |
| quote, snapshot, candles, news, insider, financials, earnings, dividends, peers, economic-calendar |
| series, metadata, search, country-indicator, live-fx |
| disasters |
Why this matters: adding a data source touches no command or business-logic code. Adding KRX coverage, for example, means a new packages/external-api/naver/ raw client, a createNaverProvider(): MarketDataProvider in packages/adapter/adapters/src/, and one registration line in packages/adapter/adapters/src/registry.ts. See CONTRIBUTING.md for the full recipe.
Development
Requires Node.js 22+ and Yarn Berry.
corepack enable
yarn install
yarn dev:cli show portfolio # CLI dev mode
yarn typecheck # Full type check
yarn test # Run unit testsSee CONTRIBUTING.md for the full architecture walkthrough and the recipe for adding a new external data provider.
Works with Herald
Firma is the financial intelligence layer of the Herald ambient voice assistant stack. When connected, Herald can:
report your portfolio performance and net worth by voice
answer "how much did I spend on fees this quarter?" without opening a spreadsheet
surface market context mid-conversation alongside your own position data
Herald + Firma + Memex — ambient voice, financial intelligence, and persistent memory in one personal AI stack.
llms.txt
llms.txt is a machine-readable summary of this project for LLM agents — concise description with documentation links, following the llms.txt standard.
License
MIT © Evan Moon
Maintenance
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/evan-moon/firma'
If you have feedback or need assistance with the MCP directory API, please join our Discord server