portfolio-analytics-mcp
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@portfolio-analytics-mcpWhat's the beta of my 60% AAPL and 40% MSFT portfolio to SPY?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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 |
| How sensitive is this portfolio to the market? | Holdings (+ optional weights), benchmark |
| Is this book actually diversified, or is everything one bet? | Holdings with sector labels |
| 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.
Related MCP server: QuantRisk-MCP-Server
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 evalsExample
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 pytestThe 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
Available Tools
3 toolsportfolio_betaA
Compute the beta of a portfolio you supply against a benchmark.
Use this to answer how sensitive a set of holdings is to a market index — "what is my portfolio's beta to the S&P", "is this book more or less volatile than the market". Beta is estimated from daily returns over the lookback window.
You must pass the holdings in; this tool has no access to any brokerage account and
cannot look up what someone owns. Weights need not sum to 1. Non-US listings need
an exchange code to resolve the right venue.
Returns the portfolio beta, each holding's individual beta, and — importantly — the
number of overlapping observations and the date range actually used, which is
usually shorter than the range requested because of holidays and listing dates. A
beta computed on very few observations comes back with a note saying so, and
comes back as null rather than a misleading number when there are too few to
estimate at all.
| Name | Required | Description | Default |
|---|---|---|---|
| holdings | Yes | ||
| benchmark | No | SPY | |
| lookback_days | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| end | Yes | Last date in the window used. |
| beta | Yes | Portfolio beta, or null when too few overlapping observations exist. |
| note | No | Set when the result needs a caveat, e.g. a short window. |
| start | Yes | First date in the window used (not requested). |
| benchmark | Yes | |
| per_holding | No | Beta of each holding against the benchmark. |
| observations | Yes | Overlapping daily observations actually used. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries full burden and excels. It discloses that the tool cannot access brokerage accounts, that weights need not sum to 1, that non-US listings require an exchange code, and that returned observation counts/date ranges may be shorter than requested. It also details the null-and-note behavior for insufficient data.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is efficiently structured in three distinct paragraphs: purpose/use-case, requirements/constraints, and return behavior/edge cases. Every sentence contributes substantive information; nothing is redundant or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity and the presence of an output schema, the description is remarkably complete. It covers input requirements, methodology, return values (portfolio beta, individual betas, observations, date range), and edge-case handling (note and null when observations are too few) without needing to restate the output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already provides detailed descriptions for all parameters (weights normalized, exchange needed for non-US, lookback_days default). The tool description adds brief context like 'beta is estimated from daily returns over the lookback window' but does not significantly expand beyond schema semantics. Schema coverage is high, so baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a clear verb+resource statement: 'Compute the beta of a portfolio you supply against a benchmark.' It also gives concrete example questions ('what is my portfolio's beta to the S&P'), making the purpose unmistakable and distinct from sibling tools like sector_correlation and revalue_positions.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says when to use it ('Use this to answer how sensitive a set of holdings is to a market index') and states a critical prerequisite ('You must pass the holdings in; this tool has no access to any brokerage account'). It does not name alternatives explicitly, but it clearly frames the tool for benchmark sensitivity analysis, which differentiates it from siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
revalue_positionsA
Match buys and sells FIFO and compute realised and unrealised P&L.
Use this to turn a list of fills into a trade history — "what did I actually make on these trades", "which positions are still open", "what is my realised P&L". Fills are matched first-in-first-out per instrument: a sell consumes the oldest open lots first, and any excess opens a position in the opposite direction, so a sell of 150 against a long of 100 closes the 100 and leaves a short of 50. Longs and shorts are handled symmetrically.
Pass the executions in; this tool cannot fetch anyone's trade history. Realised P&L is converted to your reporting currency at the closing fill's FX rate, which is where the gain is crystallised.
Optionally pass marks (symbol to current price) to get unrealised P&L on whatever
remains open. Symbols without a mark are reported with a null rather than being
treated as flat.
| Name | Required | Description | Default |
|---|---|---|---|
| marks | No | ||
| executions | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| open_lots | Yes | |
| closed_trades | Yes | |
| realised_pnl_base | Yes | Total realised P&L in the reporting currency. |
| unrealised_pnl_by_symbol | No | Per-symbol mark-to-market on open lots, in each lot's own currency. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden and excels: it discloses FIFO matching mechanics, symmetric open-position behavior, FX conversion at closing fill's rate, and the null-for-unmarked-symbols behavior. These details go far beyond a generic tool description.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Every sentence earns its place. Main purpose is front-loaded, then use cases, then behavioral details, then parameter explanation. The length is justified by the complexity of FIFO matching and FX conversion, with no filler or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite having an output schema (which covers return values), the description covers inputs, processing algorithm, edge cases (opposite-direction opens), and limitations (cannot fetch trades). It is fully contextualized for the tool's complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema descriptions are rich, but the tool description adds semantic context beyond them, e.g., that `marks` maps symbol to current price and that missing marks yield null. It explains the effects of executions as a list but doesn't enumerate each field—still adds meaning above schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb+resource: 'Match buys and sells FIFO and compute realised and unrealised P&L.' It clearly distinguishes itself from siblings (portfolio_beta, sector_correlation) by focusing on trade history and P&L, not portfolio statistics.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit guidance: 'Use this to turn a list of fills into a trade history' and states a clear limitation: 'this tool cannot fetch anyone's trade history.' It also explains when to pass marks for unrealized P&L, giving actionable usage criteria.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sector_correlationA
Compute the correlation matrix between sectors of a portfolio you supply.
Use this to answer how diversified a book actually is — "are my sectors moving together", "where is the concentration risk". Each sector becomes a single weighted return series built from its members, and the tool correlates those series against each other.
Every holding needs a sector label; holdings without one are ignored. Weights are
used to size members within their sector and default to equal weighting. As with
every tool here, you supply the portfolio — nothing is looked up.
A correlation can legitimately come back null: if a sector's members offset each other exactly, its series has no variance and correlation against it is undefined rather than zero.
| Name | Required | Description | Default |
|---|---|---|---|
| holdings | Yes | ||
| lookback_days | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| end | Yes | |
| start | Yes | |
| matrix | Yes | Correlation of each sector's weighted return series against every other. |
| sectors | Yes | |
| observations | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It transparently explains that holdings without a sector label are ignored, weights default to equal weighting and are normalized, and correlations can legitimately return null when a sector's series has zero variance. It also clarifies that the portfolio is user-supplied. This covers key behavioral edge cases, though it does not discuss error conditions or data requirements beyond this.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is efficiently structured: a direct first sentence states the core action, followed by a use-case paragraph, then important caveats. Each sentence adds value, and the text is free of fluff. It front-loads the essential purpose while keeping technical details succinctly organized.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the main computation, user-supplied portfolio behavior, and a critical edge case (null correlations), and an output schema exists to specify return values. However, it omits the lookback_days parameter, which is essential for understanding the time horizon of the correlation. This omission makes the description incomplete for full autonomous invocation, despite the otherwise rich context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description adds meaningful context for holdings and weights (e.g., 'holdings without one are ignored', 'default to equal weighting'), supplementing the schema's structure. However, the lookback_days parameter is never mentioned, leaving its role and impact undocumented. Given that schema descriptions are absent for lookback_days (only a default of 365), this is a notable gap, but the description does compensate somewhat for the other parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb+resource: 'Compute the correlation matrix between sectors of a portfolio you supply.' It clearly distinguishes itself from sibling tools (portfolio_beta, revalue_positions) by focusing on sector-level correlation and diversification analysis. The use cases ('are my sectors moving together', 'where is the concentration risk') reinforce its unique purpose.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context for when to use the tool ('Use this to answer how diversified a book actually is') but does not explicitly mention when not to use it or name alternative sibling tools. It sets expectations that the user supplies the portfolio and that nothing is looked up, which helps avoid misuse. However, it lacks explicit exclusions or comparisons.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
3 tool updates
v0.1.0- First observed
portfolio_beta - First observed
revalue_positions - First observed
sector_correlation
TDQS
Each tool performs a distinctly different analytic: beta vs benchmark, sector correlation matrix, and FIFO P&L. There is no ambiguity or overlap between their purposes, so an agent can easily select the right tool.
All tool names use snake_case and are descriptive, but the pattern is slightly mixed: 'portfolio_beta' and 'sector_correlation' are noun phrases, while 'revalue_positions' is a verb phrase. This is a minor deviation that does not harm readability.
With three tools, the server is well-scoped. Each tool addresses a major portfolio analytics need (risk, diversification, and performance) and earns its place within the typical 3-15 tool range.
The server covers three important portfolio analytics functions, but it lacks additional common analytics like portfolio return or volatility. However, within its stated scope, there are no dead ends—each tool produces meaningful output from user-supplied data.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Research-only MCP server: turn your AI into a quant research desk — backtests, no trades.
Open-source MCP server for Zerodha Kite Connect. Portfolio, market data, backtesting, alerts.
MCP server with quote and live cryptocurrency price tools, local and cloud-deployed transports.
21Multi-tenant FastMCP server for Charles Schwab brokerage data, monetized via DPYC Tollbooth
Related MCP Servers
- AlicenseAqualityCmaintenanceA portfolio analysis MCP server that enables AI agents to manage investment portfolios, fetch financial data from Yahoo Finance and CoinGecko, and perform advanced analysis like weight optimization and Monte Carlo simulations. It utilizes reference-based caching to efficiently handle large datasets without bloating the LLM's context window.261MIT
- AlicenseAqualityDmaintenancePortfolio risk analytics MCP server — VaR, Monte Carlo simulation, stress testing, portfolio optimization, options Greeks, and correlation analysis. Real market data via Yahoo Finance. Free tier available, Pro at $29/mo.101162MIT
- AlicenseAqualityDmaintenanceMCP server for portfolio rotation analysis. Score holdings and candidates across 5 dimensions, identify optimal swaps, validate with risk checks and backtests.11MIT
- FlicenseNot gradedqualityCmaintenanceMCP server wrapping yfinance to provide stock market data, financials, and analytics via 24 tools.-
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/quanttrucker/portfolio-analytics-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server