Skip to main content
Glama
lodetomasi

Portfolio Copilot

by lodetomasi

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault
PORTFOLIO_COPILOT_SEC_USER_AGENTNoUser-Agent string with contact information for SEC EDGAR requests. Optional; a default works, but set this if SEC blocks requests, e.g. 'your-app your@contact'.

Instructions

Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.

This server publishes no instructions, or was last inspected before Glama recorded them.

Capabilities

Features and capabilities supported by this server

Protocol revision2025-11-25

CapabilityDetails
tools
{
  "listChanged": false
}
prompts
{
  "listChanged": false
}
resources
{
  "subscribe": false,
  "listChanged": false
}
experimental
{}

Tools

Functions exposed to the LLM to take actions

NameDescription
parse_portfolio_exportA

Parse and normalize a local broker portfolio export. Never accesses any broker online.

get_portfolio_configA

Load targets, fees, risk_limits and rebalancing rules from config/portfolio.yaml. Falls back to the tracked config/portfolio.example.yaml when the user has not created their own file yet (flagged via is_example: say so before using those numbers as if they were the user's). Never invents or guesses these numbers.

analyze_stockA

Deterministic stock score (0-100) + confidence from free public data. Yahoo (tier B) provides the snapshot; audited SEC 10-K facts (tier A) override revenue growth and free cash flow when the company files with the SEC. Every override is listed in provenance. A metric where sources disagree without an official (tier A) tiebreaker is excluded from the score entirely; the full reconciliation is returned under "evidence".

screen_stocksA

Analyze an explicit ticker universe and rank it. Every ticker is scored, including revisions/catalysts when free data (yfinance analyst estimates/rating events, Yahoo earnings-surprise history, SEC Form 4/8-K counts) covers it -- see _enrich_snapshot_with_free_data. V1 intentionally requires a ticker list instead of scraping the whole market (see discover_stocks for that).

portfolio_riskB

Summarize weights, concentration and leveraged exposure from a local export.

allocate_cashA

Allocate new cash toward target weights without selling, while considering fees.

rebalance_portfolioA

Cash-flow-first rebalancer. New cash buys the most underweight buckets first (BUY orders only, via allocate_cash) -- CLAUDE.md's preferred order: use new cash, suspend buys on overweights, buy underweights, and sell only as a last resort. Set allow_sells=True to also see SELL orders for buckets still beyond the rebalance band after cash is deployed, listed separately under "sell_proposals"; the BUY-only orders key is unchanged either way. Nothing here executes a trade.

generate_order_planB

Return suggested manual orders. This tool cannot send orders to any broker.

build_investment_planA

Turn four rookie answers into a deterministic plan: profile, targets, example instruments to verify, initial manual orders, fee-aware contribution cadence, 12-month calendar and review rules. No return forecast. Nothing is executed.

backtest_planB

Replay the plan rules on past monthly prices (free provider): fees paid, drift, drawdown, final weights. Buckets without price data are reported, never invented. This is a replay of the past, not a forecast.

discover_stocksA

Discovery step for "I have no idea what to buy" (public pages, tier C, no account).

Nothing is excluded here: mode='universe' (default) samples the WHOLE market across every size bucket and style -- huge and small companies in the same net, no filter by index membership or overlap; mode='preset' runs one narrower Finviz preset screen instead (original behaviour, limit bounds it). Either way this is discovery only: every candidate must be re-scored with rank_candidates/screen_stocks/analyze_stock -- Finviz numbers never enter the score. Size, sector and overlap tags attached later by rank_candidates are information, never a reason to drop a candidate from this list.

log_decisionC

Append a suggested decision to the local decision ledger (data/private, git-ignored). Records what was decided and the shadow alternative so it can be measured later.

review_decisionsA

Shadow portfolio: for every logged decision older than min_days, compare what was chosen with the recorded alternative at today's prices (free provider). Reports mean decision alpha and hit rate, and refuses to draw conclusions on fewer than 10 decisions. Also includes an 'opportunity' section (portfolio.opportunity): regret against the full ranking shown at decision time, when decisions were logged with 'candidates'.

fx_ratesA

Official ECB euro reference rates (free): units of currency per 1 EUR, with as_of.

convert_amount_to_eurA

Convert an amount to EUR with the ECB reference rate. Unknown currency => value null.

company_factsA

Audited annual fundamentals from SEC EDGAR 10-K XBRL facts (US filers only, free): revenue and growth, net income/margin, free cash flow, equity, debt, with fiscal year and filing date. Foreign ADRs usually have no us-gaap facts: the result says so.

save_thesisA

Persist (create or update) a symbol's investment thesis: the claims made at BUY time plus concrete, checkable falsifiers (see check_thesis). Upserts by uppercased symbol; call this right after log_decision on a BUY so the thesis can later be checked against fresh data instead of re-litigated from memory.

check_thesisA

Evaluate a stored thesis's falsifiers against a fresh market snapshot (Yahoo, plus audited SEC facts when available -- see analyze_stock). Never invents a thesis: raises if none was saved for this symbol via save_thesis. Returns the new check plus the previous status and a qualitative delta (new/unchanged/improved/worsened).

propose_replacementA

Is current_symbol still worth its slot, versus one of candidate_tickers or plain cash? Utility blends each symbol's analyze_stock score/confidence with its fit against holdings' hidden exposure (portfolio.exposure) and, when a thesis was saved for it, its last check_thesis status. Returns HOLD/REPLACE/SELL_TO_CASH with fee-aware order(s) -- a good company is not automatically a good addition (CLAUDE.md), and the round-trip fee must be worth paying before rotating.

portfolio_exposureA

Hidden-exposure theme/driver rollup for a local export (config/exposure_graph.yaml): a small-cap ETF and an "AI software" fund can lean on the same driver despite unrelated sector labels. For each single-stock equity holding, fetches sector/industry from the market-data provider (a failed lookup is recorded under 'provider_errors', never guessed) so it can be classified; ETFs/certificates/bonds use only the fields already in the export. Includes a separate leverage-adjusted 'equivalent' view -- an intuitive metric only, never a VaR substitute (CLAUDE.md).

capital_auctionA

Rank every use of new cash -- underweight target buckets, screened candidate stocks and holding cash itself -- by marginal utility (portfolio.auction) and allocate cash_eur to the winners, one economic order at a time. Bucket current values come from the local export mapped via portfolio.mapping against config/model_portfolios.yaml's example instruments; targets come from get_portfolio_config(). Candidate stocks are scored via analyze_stock; a stock below 0.5 confidence can never win. Each candidate's fit is its hidden-exposure overlap against the portfolio's own exposure (portfolio.exposure) -- a candidate that piles onto an already-large driver scores lower fit than one that diversifies. A stored thesis (check_thesis) discounts a candidate's utility if it is WEAKENING or BROKEN. Suggestions only -- never sends an order.

personal_edgeB

This user's own track record, not a market study: mean decision alpha and hit rate by category/theme (see log_decision's category/theme fields), from the decision ledger's measured rows. Refuses to call a group's evidence threshold raise/lower until it has at least min_sample measured decisions in it (default 10, CLAUDE.md-aligned).

decision_qualityA

Process-quality rubric (0-100) for one logged decision (see log_decision): did it have sources, adequate confidence, a red-team pass, a documented reason, a recorded alternative, a recorded price/amount and a non-deteriorating thesis? Never looks at the outcome. Paired here with the decision/outcome matrix using today's measured alpha, when the decision is already priceable.

macro_snapshotA

Deterministic macro regime read: HICP (Eurostat, tier A), unemployment (Eurostat, tier A; EU27_2020 by default because the euro-area aggregate is not published for une_rt_m) plus the ECB deposit facility rate (tier A). regime is restrictive/neutral/accommodative only when both HICP and the deposit rate are available; either missing makes it 'unknown' -- never guessed.

filing_sectionsA

Item-section text from the most recent SEC filing of form for ticker (tier A, free, data.sec.gov). A ticker with no CIK, or no filing of that form (e.g. a foreign private issuer filing 20-F instead of 10-K), comes back ok=False with a readable reason -- text is extracted by a best-effort heading scan, never invented.

insider_activityA

Form 4 / 4-A filing counts in the trailing days window for ticker (SEC EDGAR, tier A, free) -- an insider-paperwork activity signal, not a buy/sell tally: the transaction XML (shares, price, direction) is not parsed, and that limitation is always stated in the result.

investor_relations_linksA

Find and classify a company's investor-relations page (annual/quarterly reports, earnings releases, guidance, presentations, press releases) from its public website (yfinance's info.website), respecting robots.txt. Tier A: the company's own site. Never logs in, executes JavaScript, or bypasses a paywall.

map_holdings_to_targetsA

Map every holding in a local export to a target allocation bucket (portfolio.mapping) by ISIN then by name keywords, using get_portfolio_config()'s targets and config/model_portfolios.yaml's example instruments. Certificates, leveraged instruments and single stocks are reported as satellite positions outside the bucket system -- never silently dropped from coverage. The result's 'current_values' plugs directly into rebalance_portfolio/allocate_cash's current_values parameter.

save_portfolio_snapshotA

Freeze the local export as one dated monthly snapshot (portfolio.snapshots, data/private/snapshots, git-ignored) so a later check-in can measure what actually changed instead of re-deriving history that was never recorded. Holdings are mapped to target buckets the same way map_holdings_to_targets does; the stored plan_targets prefer data/private/investment_plan.json's own targets over get_portfolio_config()'s. Refuses to overwrite an existing date unless force=True.

list_portfolio_snapshotsA

Every stored monthly snapshot date (portfolio.snapshots, data/private/snapshots, git-ignored, local-only), oldest first.

compare_snapshotsA

Diff two stored monthly snapshots (portfolio.snapshots.diff_snapshots): total and per-holding/per-bucket value change since 'older'. Cannot separate contributions from market move on its own -- always read the returned 'note' before calling a number 'gain' or 'loss'.

resolve_isinsA

Map ISINs to tickers via the free, keyless OpenFIGI mapping API (tier A, no signup): useful when a broker export identifies a holding only by ISIN and another tool (analyze_stock, map_holdings_to_targets) needs a yfinance-style ticker instead. A miss or an exchange OpenFIGI doesn't map to a known Yahoo suffix comes back as None for that ISIN -- never an invented ticker. OpenFIGI's anonymous rate limit (25 req/min) is respected internally; a persistent HTTP failure (e.g. 429) is raised as a ToolError rather than silently returning nothing.

rank_candidatesA

Score every ticker in tickers (screen_stocks) and rank the WHOLE set by potential -- huge and small caps in the same net. Nothing is excluded for being big, small, already inside an index/ETF, or concentrated in one sector: size, sector and index-overlap are informational tags attached to each ranked idea (portfolio.picker.annotate), never a filter. Only the caller's own risk caps (get_portfolio_config's risk_limits, when path is given) and a later red-team pass should ever limit how big a resulting BUY is sized -- never this ranking itself. top_n only bounds how many of the ranked ideas are returned in ranked; every scored ticker (minus screening-error placeholders, reported separately in screening_errors) still counts toward the summary stats.

backtest_pickerA

Disclosed PROXY backtest of the picker's ranking logic (portfolio.picker_backtest) on live free data: for each ticker, fetches price history (yfinance, tier B), earnings- surprise history (yfinance, tier B, see providers.yfinance_surprises), analyst rating- change events (yfinance, tier B, US-listed/ADR only) and as-filed annual fundamentals (SEC EDGAR XBRL, tier A, US filers only), then replays a quarterly-rebalance top-quintile strategy against benchmark. This is NOT the production scorer (scoring/engine.py) -- it is a narrower, point-in-time-honest proxy answering "would this ranking logic have beaten the benchmark on past data". Every mandatory disclosure (survivorship bias -- today's tickers only --, Yahoo backfill risk, no transaction costs, event-dated not true point-in-time consensus revisions) is always returned under disclosures; a ticker/benchmark with no usable price history is skipped and reported, never invented.

Prompts

Interactive templates invoked by user choice

NameDescription
portfolio_reviewOrchestrate a complete portfolio review.
stock_pickerRank a comma-separated candidate universe.
rebalanceGuide a fee-aware portfolio rebalance.
deploy_cashDecide how to deploy new cash across existing targets and new ideas.

Resources

Contextual data attached and managed by the client

NameDescription

No resources

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/lodetomasi/portfolio-copilot'

If you have feedback or need assistance with the MCP directory API, please join our Discord server