portfolio-analytics-mcp
MCP server providing portfolio analytics tools: beta to a benchmark, sector correlation, and FIFO trade matching with realized/unrealized P&L using Yahoo Finance prices.
README
portfolio-analytics-mcp
An MCP server that gives an AI agent three portfolio analytics tools: beta to a benchmark, correlation between sectors, and FIFO trade matching with realised and unrealised P&L.
Point an agent at it and ask "what's the beta of this book to the S&P", "are my sectors actually diversified", or "what did I make on these fills" — in natural language, against a portfolio you supply.
No API key. Prices come from Yahoo Finance, so a bare checkout works.
Tools
| Tool | Answers | You supply |
|---|---|---|
portfolio_beta |
How sensitive is this portfolio to the market? | Holdings (+ optional weights), benchmark |
sector_correlation |
Is this book actually diversified, or is everything one bet? | Holdings with sector labels |
revalue_positions |
What did I make, and what's still open? | A list of fills, optionally current marks |
What these tools do not do
They have no brokerage connection and no account access. Nothing here can look up what you own — you pass the portfolio in. That is a deliberate boundary, not a missing feature: the analytics are useful without ever touching a broker, and the server has no business holding credentials.
Install
git clone https://github.com/quanttrucker/portfolio-analytics-mcp
cd portfolio-analytics-mcp
python3 -m venv .venv && .venv/bin/pip install -e .
Register it with an MCP client — for Claude Desktop, in claude_desktop_config.json:
{
"mcpServers": {
"portfolio-analytics": {
"command": "/absolute/path/to/portfolio-analytics-mcp/.venv/bin/portfolio-analytics-mcp"
}
}
}
Restart the client and the three tools appear.
Demo
A recorded session of a real agent (claude-opus-5) driving this server over stdio —
MCP handshake, live Yahoo prices, plain-English questions, verbatim tool calls and
answers. It comes in two forms:
demo/transcript.html— the session rendered as a self-contained page: tool calls as cards, results as charts (beta bars, sector correlation heatmap, P&L tiles), raw JSON collapsed underneath. Open it in a browser; no build step, no external assets.demo/TRANSCRIPT.md— the same session as plain markdown, the source of record.
What the session shows, one exchange per tool:
- "I hold 60% AAPL and 40% MSFT — what's my beta to SPY?" → one
portfolio_betacall with the weights and benchmark filled in correctly; answer 0.83 with a per-holding decomposition. - "Is my portfolio actually diversified?" →
sector_correlationandportfolio_betacalled in parallel; the agent states its equal-weight assumption, reads the near-zero cross-sector correlations, and flags that XOM's −0.48 beta is regime-specific rather than presenting it as a stable hedge. - "I bought 100 AAPL at 180, sold 40 at 195, it's at 210 now — what did I make?"
→
revalue_positionsmatches the fills FIFO: $600 realised, $1,800 unrealised on the 60-share remainder.
Re-record against the current market with:
python demo/transcript.py # needs the same .env credentials as the evals
Example
Matching two fills and marking what's left open:
// revalue_positions
{
"executions": [
{"symbol": "AAA", "side": "BUY", "quantity": 100, "price": 10.0, "timestamp": "2025-01-02T10:00:00"},
{"symbol": "AAA", "side": "SELL", "quantity": 40, "price": 12.5, "timestamp": "2025-01-09T15:30:00"}
],
"marks": {"AAA": 13.0}
}
{
"realised_pnl_base": 100.0, // 40 units closed at +2.50
"open_lots": [
{"symbol": "AAA", "direction": "Long", "quantity": 60,
"entry_price": 10.0, "unrealised_pnl_currency": 180.0}
]
}
Details worth knowing
FIFO matching is symmetric. A sell consumes the oldest open lots first; any excess opens a position the other way, so a sell of 150 against a long of 100 closes the 100 and leaves a short of 50. Shorts work identically in reverse. Realised P&L converts at the closing fill's FX rate, which is where the gain is crystallised.
London prices are handled. Yahoo quotes LSE listings in pence and reports their
currency as GBp, not GBP. Left alone that inflates a UK holding 100× against
everything else in the portfolio; here it is normalised to major units at ingestion.
Non-US listings take an exchange code (LSE, IBIS, SEHK) to resolve the venue.
Cross-venue portfolios don't share a trading calendar. A UK line and a US line disagree on holidays, so on some dates one is missing. Summing across such a row drops the absent member's weight rather than its return, understating the portfolio on exactly the days two markets diverge. Returns are complete-case by default.
Undefined statistics come back as null, never as a number. A beta estimated on too
few overlapping observations is null with a note saying so, rather than a figure that
looks authoritative. A sector whose members offset each other exactly has no variance,
so its correlation is genuinely undefined — also null, not zero.
Prices are cached to disk. Yahoo is unofficial and occasionally flaky. Fetches are
cached (12h TTL) under ~/.cache/portfolio-analytics-mcp, overridable with
PORTFOLIO_ANALYTICS_CACHE. A corrupt cache entry refetches rather than failing.
Development
.venv/bin/pip install -e ".[dev]"
.venv/bin/python -m pytest
The test suite never touches the network — the price downloader sits behind a protocol and is faked. Symbology and the pence conversion are additionally checked against the live feed by hand, since those are the two claims a fake cannot validate.
Licence
MIT
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.