tickerinside-mcp
v1.10.0
Published
Holdings, overlap, correlation and look-through risk for US ETFs. Free data, no key.
Maintainers
Readme
tickerinside-mcp
What is inside a US ETF, and what you actually hold once you look through the funds to the companies underneath.
TickerInside is an open, machine-readable database of US ETF holdings, with the source and date of each holding. This is its MCP server, over the free data at tickerinside.com: no key, no account, no per-user quota. Each answer names the file it came from, the issuer's own holdings file or the fund's SEC filing, with a link where it can be checked.
Install: one URL
The server answers at this address, so most clients need nothing installed:
https://tickerinside.com/mcpClaude. TickerInside is available in Claude's connector directory: open https://claude.ai/directory/tickerinside and click Connect. There is nothing to sign in to, and once connected it works in Claude Desktop and the mobile apps too. As a custom connector instead: in claude.ai, open Customize, then Connectors, click + Add, choose Add custom connector, paste the URL above and choose No sign in.
Claude Code
claude mcp add --transport http tickerinside https://tickerinside.com/mcpCodex CLI
codex mcp add tickerinside --url https://tickerinside.com/mcpGemini CLI
gemini mcp add --transport http tickerinside https://tickerinside.com/mcpOther clients. Cursor, VS Code and any client that accepts a remote MCP
server: add a server named tickerinside with the URL above. It speaks
Streamable HTTP, keeps no session and asks for no authorization. It answers
MCP 2026-07-28, where a client opens with server/discover and each request
carries its protocol version in _meta with no handshake, and the revisions
from 2024-11-05 to 2025-11-25, which open with initialize, on the same URL.
This package, over stdio, speaks the revisions up to 2025-11-25.
Or run it locally with npx
This package runs the same twelve tools on your own machine, with Node 20 or later. The remote server runs this package's own tool code, so the answers are the same; only where the arithmetic runs differs. Use it when a client only runs local servers, or when you would rather it ran on your machine.
npx -y tickerinside-mcp@latestClaude Code
claude mcp add tickerinside -- npx -y tickerinside-mcp@latestCodex CLI
codex mcp add tickerinside -- npx -y tickerinside-mcp@latestCursor, Claude Desktop, VS Code and other clients: add a server named
tickerinside with command npx and arguments ["-y", "tickerinside-mcp@latest"].
@latest makes npx fetch the current version rather than run one it cached
earlier.
What it answers that other tools do not
Most fund tools report allocation and sector weights. This one answers the two questions a holder actually has.
How much of a company do I own, in money, across all my funds. Paste four funds with what each is worth and it returns the companies underneath, ranked, with the amount carried on each and which funds it comes through.
Which of my positions produces my risk rather than my capital. It returns an Euler decomposition of portfolio variance, so the shares sum to one hundred, and the squared diversification ratio, which counts positions that behave differently rather than positions held. Four funds frequently turn out to be one and a bit independent bets.
It is also not limited to comparisons someone wrote by hand. Each fund file carries its full holdings and, where the price history is in the data, 156 weekly returns, so the server computes any pair, any basket, and any covariance matrix from the data itself.
Tools
Every tool only reads, and says so in its annotations, so clients can run it without asking each time. Each has a short title for a client's list, and a description that opens on the questions it answers, says what it returns, and ends on what it is not for, naming the tool that answers that instead.
| Tool | What it returns |
| --- | --- |
| list_etfs | Every covered US ETF, the date of the data, and where each fund's holdings come from, or the funds whose ticker or name matches a query. |
| get_etf_holdings | One fund: holdings with weights, cost, assets, returns, volatility, beta over three years and one, worst fall, concentration. |
| compare_etfs | Any two funds: overlap measured three ways, the largest shared holdings, correlation, covariance, cost and risk for both, beta over three years and one. |
| get_etf_overlap_matrix | Every pair in a list of 2 to 30 funds, ranked by overlap by weight. |
| get_etf_portfolio_lookthrough | The companies under a portfolio, in percent and in money, with the funds each comes through. |
| get_etf_portfolio_risk | Portfolio volatility and beta, each position's share of the risk, the diversification ratio, and both matrices. |
| find_etfs_holding_stock | The covered funds holding one stock, heaviest first, with each fund's holdings date and source, the stock's rank in the fund and the dollars held; how many funds have it as their largest holding, the funds with the most dollars in it, whether it is in VOO, SPY, IVV, QQQ, VTI and SCHD, the issuers holding the most, the cheapest exposure per $1,000, and one sentence to quote; compact for the counts and the sentence alone. |
| compare_stocks | Two US stocks side by side, their correlation, and the funds holding both. A fund works on one side. |
| get_etf_ownership | How much of one US stock the covered ETFs own, as a lower bound: at least this percent of its shares outstanding, from this many funds, with the SEC's count and both dates. |
| get_etf_holdings_history | One fund's holdings history from its issuer's files: every file date with its position count and top 10 weight, one line per step from a file to the next, and how its overlap with its ten closest funds moved. |
| get_etf_holdings_changes | What one fund added and dropped from one issuer file to the next since a date, and the weights that moved, which include price moves and not only trades, before and after, with the file each step is compared with. |
| get_etf_flows | Whether the ETFs read daily from their issuers' files bought or sold a stock: the net change in shares held on the latest market close, its value at the files' own prices, the funds adding and trimming, a 20-day series, index entries and exits and corporate actions (mergers, spin-offs, takeovers and splits are no trades); without a ticker, the day's largest net additions and reductions. |
Older tool names (list_funds, fund_profile, compare_funds, overlap_matrix, look_through, risk_decomposition, stock_exposure, etf_ownership, fund_history, fund_changes) still work.
Prompts
Since 1.10.0 the server also offers five prompts, ready questions a client
can show its user. Each returns one user message that asks the question in
plain words and names the tool that answers it. In Claude Code each is a
command named after the server: for a server added as tickerinside, for
example /mcp__tickerinside__what_does_this_etf_hold VOO. Type a list without
spaces, as VOO,QQQ,SCHD or VOO:60,QQQ:40, since Claude Code passes a
prompt's argument up to its first space.
| Prompt | Argument | What it asks |
| --- | --- | --- |
| what_does_this_etf_hold | ticker, for example VOO | One fund's largest holdings with their weights, its cost and size, and the date of its holdings file (get_etf_holdings). |
| which_etfs_hold_this_stock | ticker, for example NVDA | The funds holding one stock, heaviest first, each with its weight and holdings date (find_etfs_holding_stock). |
| do_my_etfs_overlap | tickers, for example VOO,QQQ,SCHD | How much 2 to 30 funds hold in common, by weight (compare_etfs for two, get_etf_overlap_matrix for more). |
| what_is_inside_my_etf_portfolio | holdings, for example VOO:60,QQQ:40 | The companies under a portfolio, how much of each and the funds each comes through (get_etf_portfolio_lookthrough). |
| are_etfs_buying_this_stock | ticker, for example NVDA | Whether the ETFs read daily bought or sold a stock on the latest market close, and the value (get_etf_flows). |
A missing, unknown or malformed argument is answered with the JSON-RPC
error -32602 and the reason, as an unknown prompt is. So is a list that ends
with a comma or a semicolon, such as VOO:60,, which is how a list typed with
spaces arrives from Claude Code.
What an answer looks like
An answer about funds carries prices_as_of and holdings_as_of, because
holdings refresh when the issuer publishes, daily for some funds and monthly
for others, and the two dates are returned rather than merged into one. It
also says where each fund's holdings come from (holdings_source): the
issuer's own file, the fund's latest SEC Form N-PORT filing (for the other US
stock ETFs, bond, credit and mortgage ETFs, multi-asset ETFs, and leveraged,
inverse and option-based ETFs), which describes the portfolio at a quarter end,
months before it is read, and is dated to that quarter end, or the
trust's own SEC filing (for a gold, bitcoin or currency trust or a commodity
pool, which file no Form N-PORT), or the sponsor's own file (sponsor_files, a
fund too new for a Form N-PORT, read from the holdings its sponsor publishes
and dated to that file), or its prospectus (prospectus: a fund with no
holdings yet, whose stated objective is quoted and whose first holdings filing
replaces it; nothing overlaps it). A fixed income ETF gives its lines by issuer, coupon
and maturity, with no identifier, and its average coupon, maturity and
duration; compare_etfs and get_etf_overlap_matrix give fixed income funds their issuer overlap
(the smaller weight of each issuer both hold, summed), labelled as issuer
overlap and never mixed with overlap by shares. A leveraged or option-based ETF gives
its swaps, futures and options as notional exposure in percent of net assets,
never as shares held, and find_etfs_holding_stock lists such funds apart from the
funds that hold a stock.
Every answer also carries a source block with the JSON file the figures came
from and the licence. Answers about funds and about who holds a stock add the
page on the site where the figure can be checked, when there is one, and a
cite_as line to put under a quoted figure. An answer with a one-year beta
also names SPY's file, which that beta is measured against, in
benchmark_url.
A ticker outside the coverage is an ordinary answer, not an error. It comes
back with covered: false, the tickers that were not found, the six issuers
that are covered and the SEC layer beside them, so an assistant can tell its
user what is covered instead of retrying. In a basket, the covered funds are answered and the others are listed
under skipped. Only input that the caller must fix, such as an amount on some
lines and not others, or an argument the tool's schema does not name, comes
back as an error.
Every answer is JSON text, and the same answer as an object in
structuredContent, every field and every row, so a client that reads one
and a client that reads the other read the same thing. Each tool states what
it returns in its outputSchema: the dates, the source block and the key
figures and rows a program reads, with their types. An error carries no
structured part.
The three overlap measures, because they disagree
Published overlap figures for the same pair of funds differ across sites, because sites quote different measures without naming them.
- Overlap by weight is the sum, across every company both funds hold, of the smaller of its two weights. Symmetric, and the headline figure.
- Share of A held in common is the part of A's own weight sitting in companies B also holds, as a percentage of A. Not symmetric, and the gap between the two directions is usually the interesting part.
- Companies in both is a plain count, useful for seeing when a high weight overlap rests on very few names.
Some sites publish these by counting positions rather than by weight, which is a fourth number again. Every response here says which measure it is.
Checking it
Covariance is annualised and in percent squared, so the diagonal is each fund's variance. Divide an off-diagonal by the two volatilities and you get back the correlation printed beside it. That is the whole method, and it is published so it can be checked rather than believed.
Correlation and covariance are measured on the weeks every fund in the answer
has, and weeks_used says how many. A fund younger than three years has empty
weeks at the start of its series, and they are left out rather than read as a
0% return. The three-year beta is the one in each fund's file; the one-year
beta is measured against SPY over the last 52 weeks, from at least 40 of them.
Coverage and limits
US ETFs from iShares, SPDR, Vanguard, Invesco and Global X, each from the
issuer's own full holdings file, and the other US stock ETFs, Schwab's
among them, from their latest SEC Form N-PORT filing, which have holdings
but in most cases no prices, cost or risk figures; bond, credit, mortgage, multi-asset, leveraged,
inverse and option-based ETFs from the same filings, trusts and commodity
pools from their own SEC filings, funds too new for a Form N-PORT from the
holdings their sponsors publish on their own sites, and, for a fund with no
holdings yet, its prospectus.
list_etfs returns the universe and its counts, the sources apart, and how
many of the US-listed ETFs that is. This README gives no count, because it is
published far less often than the data moves: the counts of the day are in
the coverage object of https://tickerinside.com/api/v1/index.json. US stocks with three years of price history are
covered as instruments too, with sector, valuation, returns, risk and 156
weekly returns each, which is what compare_stocks runs on. So is a US stock
with a shorter history when a fund read from an issuer file or a stock ETF
from SEC filings holds it in a file dated since it listed, the price data has
its closes since its listing, or a year of them, the last at most five
sessions old, and Nasdaq Trader's directory lists it under its name. Such a stock comes with its holders and
last close, and with its one-year return once its weekly closes cover a
year. Its three- and five-year figures and its correlation are null until it
has the weekly series. It covers ETFs:
mutual funds and exchange-traded notes are not part of it.
The npm package reads the public API at https://tickerinside.com/api/v1 and
keeps each file for an hour, since the data changes every weeknight. It
fetches the files of the funds and stocks you ask about (/fund/<ticker>.json,
which answers for every fund, and /sec/<ticker>.json; /etf/<ticker>.json
for a fixed income, multi-asset, derivative-based, trust, pool, sponsor-file
or prospectus fund when /fund/ does not answer for it, which the index below says),
the index of what is covered (/index.json, read for that and once when the
server starts, for the fund count), the list of funds with
their names and pages (/funds-columns.json, or /funds.json where the site
has no such file, and /funds.json for a search of list_etfs), and, for a stock without a file of its
own, the shard of the reverse index its first letter points to
(/holders/<letter>.json), SPY's file (/fund/spy.json), the benchmark of
the one-year beta, for get_etf_ownership the ledger's summary
(/ownership.json), for get_etf_holdings_history and get_etf_holdings_changes the fund's
history file (/history/<ticker>.json), and for get_etf_flows the flows
(/flows.json and /flows/<ticker>.json), which are under the history terms
of https://tickerinside.com/legal/#history rather than CC BY 4.0. Every request carries a User-Agent naming the
package and its version, and nothing else is sent: the amounts passed to
get_etf_portfolio_lookthrough or get_etf_portfolio_risk never leave your machine. When a file
cannot be read, the answer to the model says so in one line and the reason is
written to stderr, which your client keeps in its log for the server.
The same data as a free JSON API
Every answer is computed from static JSON files anyone can read from their own code, with no key and no sign-up, CORS open:
curl -s https://tickerinside.com/api/v1/fund/voo.jsonThe reference, with recipes for Python, JavaScript and Excel, is at https://tickerinside.com/api/, the same reference as one text file for coding agents at https://tickerinside.com/llms-full.txt, and the OpenAPI 3.1 description at https://tickerinside.com/api/openapi.json. What last night's build did is in https://tickerinside.com/api/v1/status.json, and the live checks of the site and of the remote server, made every five minutes, in https://tickerinside.com/api/v1/uptime.json.
Terms
Data under CC BY 4.0: credit TickerInside by name, in text or with a link; both are accepted. Code under MIT. Derived from issuers' public holdings files, the SEC's public Form N-PORT data sets, the shares outstanding companies report to the SEC in XBRL, and end of day prices, provided as is with no warranty of accuracy.
This is a measurement of what funds hold and how they have behaved. It is not investment advice, and it does not know your situation.
Errors and data requests: [email protected]
