Local-first MCP server for personal investment portfolio analysis. Currently supports XP Investimentos; adapter-ready for Rico, NuInvest, Inter, Avenue, and crypto exchanges.
Strong foundation with 18 well-named tools following verb_noun convention. All tools have descriptions (avg 180 chars, within baseline 194). Input schemas present for all tools with type definitions. However, output schemas are not explicitly documented in the source code, only inferred from descriptions. Parameter descriptions are present but some lack detail on constraints (ranges, formats). Error handling guidance is minimal; most tools lack recovery hints. Security considerations around outbound_enabled gating are good, but no explicit permission declarations or audit trail patterns visible.
Compare current portfolio allocation against a target defined in ~/.xp-mcp/allocation.json. Returns per-class drift in percentage points and BRL, with suggested BUY/SELL actions to rebalance. Optional 'target_path' argument overrides the default location. Optional 'tolerance_pp' field in the JSON treats drifts within the band as 'ok' (no action).
Money-weighted return (MWR / IRR) — the rate that reflects when you put money in vs. out. Computed via bisection over signed cash flows including synthetic initial/terminal NAV. Requires ≥ 2 XPerformance imports. Returns mwr_period, mwr_annualized, cash_flow_breakdown, convergence diagnostics, and warnings.
Time-weighted return (TWR) over the XPerformance import history. Removes the effect of when you contributed/withdrew — pure portfolio performance metric, GIPS-compliant. Uses Modified Dietz between consecutive imports and chains sub-periods geometrically. Requires ≥ 2 XPerformance imports. Returns period_return, annualized return, per-sub-period breakdown, and quality warnings (sparse history, large cash flows, stale tail).
Read the advisor profile from ~/.xp-mcp/advisor-profile.json. Returns exists:false when the file is not yet configured; reports schema errors in the errors array.
List cash flows (APORTE/RESGATE) with optional date range and kind filters. Returns up to `limit` rows sorted by flow_datetime DESC, plus aggregate totals (aporte_total, resgate_total, net) computed over ALL matching rows.
Output schemas not explicitly documented in source. Tool descriptions infer return structure but no formal schema definitions visible for LLM planning.
Parameter constraints (ranges, formats, patterns) not consistently documented. E.g., 'limit' parameters lack min/max bounds; date strings lack ISO 8601 format hints.
Error handling lacks recovery guidance. Tools do not document what to do on failure (retry, ask user, fatal). E.g., import tools mention 'warnings' but no guidance on handling them.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 54 | 2026-07-28+ | v2 |
Spot crypto quotes in BRL via Mercado Bitcoin (e.g. BTC, ETH, SOL). Per-ticker partial failure: one unknown symbol doesn't fail the batch. 15-minute cache, outbound-gated. Quote only — crypto is not yet a tracked portfolio asset_class.
List dividend/JCP payouts with optional ticker, asset_class, kind, and date-range filters. Returns up to `limit` rows sorted by pay_date DESC, with gross/tax amounts in BRL. Zero outbound HTTP. Read-only.
Fetch quotes and/or fundamentals from brapi.dev for 1-50 tickers, with SQLite caching. Requires outbound_enabled=true in the advisor profile. Per-ticker partial failures are reported in results[].error without failing the whole call. cache_ttl_minutes overrides the default TTL (60 quote / 1440 fundamentals).
Aggregate stats + reconciliation gap for the portfolio. Returns total market value, per-class breakdown (% and BRL), top 5 positions, total/per-class P&L, FGC coverage, maturity buckets (short/medium/long), and the gap between the declared patrimônio total (from the last XPerformance PDF) vs computed total. Zero outbound HTTP. No inputs.
List all positions in the portfolio. Optional filter by asset_class. Returns each position with quantity, avg/current price, invested vs market value, and unrealized P&L. Values in BRL (Brazilian Reais).
List trade transactions (buys/sells) with optional ticker, asset_class, and date-range filters. Returns up to `limit` rows sorted by trade_date DESC, with amounts in BRL. Zero outbound HTTP. Read-only.
Import a PDF exported from XP's Conta Digital Extrato (digital account statement). Filters for transfers between digital account and investment account only (deposits = APORTE, withdrawals = RESGATE). Idempotent: re-importing the same file skips duplicates. Persists to the cash_flows table.
Import a CSV exported from XP Investimentos (Posicao Consolidada, Extrato). Idempotent: re-importing the same file updates existing positions instead of duplicating. Returns counts, warnings, and a preview of the first 5 parsed positions.
Import the XPerformance PDF (XP's official portfolio report). Extracts patrimônio total, reference date, and per-asset position rows (quantity, market value, %allocation, indexer, maturity). Idempotent: re-importing the same file updates existing positions. Returns import counts, warnings, and a preview of up to 10 positions.
Rank B3 assets (FII | ACAO | ETF) against criteria (sort_by, filters, limit). Fetches the universe and per-ticker quote+fundamentals from brapi.dev (cached). Profile's excluded_classes/excluded_tickers are merged with the call's exclude_tickers. Output is educational analysis, not investment advice.
Save (overwrite) the advisor profile at ~/.xp-mcp/advisor-profile.json. Required fields: risk_tolerance (1-10), horizon_years (>0), objective ('income'|'growth'|'balanced'). Optional: outbound_enabled (default false), excluded_classes, excluded_tickers, notes, brapi_token. Enabling outbound_enabled=true requires accept_disclaimer=true on the call.
Manually track a crypto holding (e.g. BTC, ETH). Fetches the current BRL quote (multi-source: Mercado Bitcoin → Foxbit → Binance) and stores a snapshot market value (quantity × current price) as a CRIPTO position, which then flows into get_portfolio_summary and calculate_allocation_drift. quantity=0 removes the holding (idempotent). Re-run to refresh the value. Outbound-gated. Snapshot only — no cost basis / P&L is recorded.
Suggest BUY actions per underweight asset class based on the advisor profile. Composes drift + screening per class (FII/ACAO/ETF) using a fixed objective × asset_class criteria matrix; non-screenable classes (TESOURO/RF/FUNDO) surface in skipped_classes with reason. Requires outbound_enabled=true. Output is educational analysis, not investment advice.
No explicit permission declarations or scope documentation. Tools like set_advisor_profile and set_crypto_position modify state but lack audit trail or permission gate patterns.
Idempotency claims in descriptions (e.g., 'Idempotent: re-importing updates positions') lack formal idempotent hints in schema annotations.