Skip to content

ETFIQ

by etfiq.com · remote · no sign-in to list tools · v0.2.0 · published by com.etfiq

Independent US ETF data and benchmarks for model portfolios, each figure with its source and date.

Changes · 14

20 tools: 14 change things and 6 only read.

Scanned Oct 21, 2026

3 checks matched something in the tool definitions. No finding is not a safety guarantee. How the checks work.

claude mcp add --transport http etfiq https://mcp.etfiq.com

Findings

Matches of fixed checks, with the text they matched.

2 warn1 info
  • The description contains "every other tool", wording about other tools or servers.

    Matched text

    description: "...needs to stay true after it is quoted: every other tool here answers about today and today move..."

    What this check looks for
  • The server marks "compare_to_benchmark" read-only (readOnlyHint: true), and its own name, description or input give the class "write".

    Matched text

    annotations: {"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}; The name "compare_to_benchmark" says "compare": a word for reading.

    What this check looks for
  • The description is 3,014 characters long, over the 2,000 this check looks for.

    Matched text

    description ends: "...y response carries the not-advice line in not_advice: show it with the portfolio."

    What this check looks for

Tools

Open a tool for its reasons and full description. Descriptions are the publisher's own words, shown as they are.

20 tools

Changes things 14Claude Code: ask
  • build_portfolioBuilds a custom portfolio of US listed ETFs from construction choices about the PORTFOLIO, and shows the rule it applied.1 finding

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    • The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.

    Findings

    • Info

      The description is 3,014 characters long, over the 2,000 this check looks for.

      Matched text

      description ends: "...y response carries the not-advice line in not_advice: show it with the portfolio."

      What this check looks for
    Description, as the server wrote it
    Builds a custom portfolio of US listed ETFs from construction choices about the PORTFOLIO, and shows the rule it applied. TWO FORMS. Weights (ETFIQ custom construction rule, version 2): pass weights, the user's own percent for each asset class, adding to exactly 100, for example {"us-stocks": 40, "international-stocks": 15, "us-bonds": 25, "gold": 10, "reits": 10}. The asset classes: us-stocks, us-small-stocks, international-stocks, emerging-markets-stocks, reits, us-bonds (core, intermediate), us-bonds-short, us-bonds-long, us-corporate-bonds, government-bonds-short, government-bonds-intermediate, government-bonds-long, tips, high-yield-bonds, cash (Treasury bills), gold, commodities (broad), alternatives. Defaults: cheapest funds, one fund per asset class, no fee ceiling; the answer's defaults.line names the ones used. Band (version 1): pass band, include and funds, and the rule sets the weights (stocks at the band's point, international 40% of stocks outside themes, themes 10% of stocks, commodities and alternatives 5% each from bonds, US bonds the rest). In each asset class or sleeve the cheapest (or largest) funds that file N-PORT (a gold trust: its 10-Q or 10-K), hold at least $100 million and have three years of prices, each fund's fee with its filing date. WHEN THE USER GIVES WEIGHTS, call the weights form at once, mapping their words to the ids above; ask at most ONE follow-up, and only for what has no default: weights that do not add to 100 (kind weights-total), or an asset class with no id here (kind unknown-class). When the user gives neither weights nor a band, ask once for one of them; the bands by stock share are conservative: more than 15% and up to 30% stocks; moderately-conservative: more than 30% and up to 50%; moderate: more than 50% and up to 70%; moderately-aggressive: more than 70% and up to 85%; aggressive: more than 85%. NEVER ask about, and never pass, the person's age, income, savings, net worth, goals, time horizon, tax situation, risk tolerance, employment or family, and never turn what someone says about themselves into weights or a band: those are the user's choices about the portfolio. If asked whether a portfolio suits someone, or whether to buy or sell it, say that ETFIQ does not answer that and give the not-advice line. Its returns field carries the portfolio's hypothetical returns (ETFIQ custom rule, version 3: the weights reset at every month end, as the ETFIQ benchmarks are): total return, return a year, volatility and month-end drawdown over 1Y, 3Y, 5Y, 10Y and since the first month end all its funds share, a window given only where every fund has prices across it; returns.common.sentence says where the history starts and why. Show them as hypothetical, never extend a window, and never estimate a return the answer does not give. To set the portfolio beside an ETFIQ benchmark, call compare_to_benchmark with the answer's compare.arguments. Every response carries the not-advice line in not_advice: show it with the portfolio.

    Annotations the server declares

    • title: Build a portfolio from construction rules
    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • compare_to_benchmarkSets an allocation ETF, or a portfolio build_portfolio builds, beside an ETFIQ benchmark.1 finding

    Why it is in this group

    • The name "compare_to_benchmark" says "compare": a word for reading.
    • The description's first verb is "set": a word for a change.
    • The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.

    Findings

    • Warn

      The server marks "compare_to_benchmark" read-only (readOnlyHint: true), and its own name, description or input give the class "write".

      Matched text

      annotations: {"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}; The name "compare_to_benchmark" says "compare": a word for reading.

      What this check looks for
    Description, as the server wrote it
    Sets an allocation ETF, or a portfolio build_portfolio builds, beside an ETFIQ benchmark. With ticker (such as AOR): how the fund did against the benchmark for its band (set by its look-through stock share), over the same dates, as ETFIQ published it: total returns by window and the difference, risk and cost. With portfolio (the arguments build_portfolio took, its answer's compare.arguments.portfolio): the same portfolio built again beside an ETFIQ benchmark, the benchmark's own 1Y, 3Y, 5Y, 10Y and since-inception windows exactly as published, each with its dates and basis (hypothetical before the freeze date), and the differences in stock share and weighted fee in percentage points; and, in portfolio_returns, the portfolio's hypothetical returns beside the benchmark's over the same months, window by window, with each difference in percentage points. WHICH BENCHMARK: without benchmark, the default rule's (the ETFIQ strategic benchmark nearest the portfolio's looked-through stock share, the lower on a tie; for the band form, its band's), and choice.line says why in one line. When that one is more than 5 percentage points from the stock share, or the share is as near another strategic benchmark, the next-nearest is set beside it in also, with the same windows and differences, and choice.gap.line says so. When the reader names another ETFIQ benchmark ("compare it to Strategic 80 instead"), pass benchmark with their words or its id (etfiq-strategic-80): any benchmark list_benchmarks returns. That one is used, and choice.line still names the default and why. A name that matches no benchmark is refused (kind unknown-benchmark) with the list. Refuses, and estimates nothing, when ETFIQ has not published what is asked.

    Annotations the server declares

    • title: An allocation ETF or a built portfolio against an ETFIQ benchmark
    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • etf_flowsFund flows as ETFIQ publishes them, computed from each fund's daily change in shares outstanding times its NAV.No findings

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    • The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
    Description, as the server wrote it
    Fund flows as ETFIQ publishes them, computed from each fund's daily change in shares outstanding times its NAV. With ticker: that fund's net flow over 1D, 1W, 1M, 3M, YTD and 1Y, each with its dates and its share of net assets at the window's start, its streak, and its filed N-PORT months. Without ticker: the biggest inflows and outflows among every fund with a daily figure for window (1D, 1W, 1M, 3M, YTD or 1Y; default 1W), how many funds were counted, each row with the last day its figures reach (through; a row short of the window counts fewer days), and the latest weekly flows report (Monday to Friday) with its own top inflows and outflows, each with its days. Filter by desk, category (Stocks, Bonds, Commodities, Allocation) or issuer. USE THIS for any question about money going into or out of ETFs.

    Annotations the server declares

    • title: ETF fund flows
    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • etf_holdersWhich US listed ETFs hold a given company, ranked by how much of each fund it is.No findings

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    • The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
    Description, as the server wrote it
    Which US listed ETFs hold a given company, ranked by how much of each fund it is. USE THIS for any "which ETFs hold X", "which fund holds the most X", or "how do I get exposure to X" question, where X is a company rather than a fund, and for "which bond ETFs hold X's debt". Takes a company name or its ticker. Returns every fund holding its shares with the weight its issuer published and the date that book was filed, and separately every fund holding its bonds or other debt. Covers 31,019 companies.

    Annotations the server declares

    • title: Which ETFs hold a company
    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • etf_holdingsWhat a fund holds, by weight, and how old that is.No findings

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    • The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
    Description, as the server wrote it
    What a fund holds, by weight, and how old that is. ALWAYS read lag_days before presenting it: an issuer file read today and a filing from two months ago both come back here and are not the same answer.

    Annotations the server declares

    • title: Holdings of one ETF
    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • etf_overlapHow much of their weight two funds hold in common, as ETFIQ published it on the comparison page for that pair.No findings

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    • The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
    Description, as the server wrote it
    How much of their weight two funds hold in common, as ETFIQ published it on the comparison page for that pair. Use when asked whether two ETFs are the same thing, or whether owning both adds anything. Refuses rather than estimating when the pair is not compared or either holdings book is incomplete.

    Annotations the server declares

    • title: Holdings overlap of two ETFs
    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • etf_profileEverything ETFIQ publishes about one fund: issuer, category, and each figure with its source and as-of date, plus a one sentence verdict on how it did against what its own label pr…No findings

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    • The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
    Description, as the server wrote it
    Everything ETFIQ publishes about one fund: issuer, category, and each figure with its source and as-of date, plus a one sentence verdict on how it did against what its own label promises. benchmark is the fund's own benchmark as its page names it: its name, how it was set, and the fund's return, the benchmark's and the gap for each window (periods is the page's whole window table). A closed fund answers with closed (the day and the page's words); a former ticker answers as the fund it trades as now, and says so. The ETFIQ benchmarks for model portfolios (list_benchmarks) are a different thing.

    Annotations the server declares

    • title: Everything about one ETF
    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • etf_rankingsThe ranked lists ETFIQ publishes, or one of them.No findings

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    • The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
    Description, as the server wrote it
    The ranked lists ETFIQ publishes, or one of them. Each ranks ONE published figure inside a stated set: the cheapest funds in a theme, the leveraged funds furthest from their stated multiple, the buffer funds closest to their cap. Call with no argument for the list.

    Annotations the server declares

    • title: Published rankings
    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • etf_screenEvery fund matching some filters, each with its net assets and the source and date that figure came from.No findings

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    • The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
    Description, as the server wrote it
    Every fund matching some filters, each with its net assets and the source and date that figure came from. Filters: desk, issuer, max_fee_pct, min_assets_usd; and, from the ETFIQ screener, tracks (the index the funds track, such as "S&P 500"), min_yield_pct (12-month yield of at least that percent), pays (payout frequency: weekly, monthly, quarterly, semiannual or annual, published for income ETFs) and sort (assets, largest first; fee, lowest first; yield, highest first). count is the WHOLE matching set: when fewer rows come back, truncated and note say so, and the rows must never be presented as the whole set. first names every fund tied at the top of the order. Use for "find me all X" and "cheapest X" questions rather than repeated searches. Fees are percentages, not basis points. Funds with no published figure for a filter are set aside and counted, not treated as failing it.

    Annotations the server declares

    • title: Screen ETFs by filters
    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • etf_themeEvery US listed fund in a theme, largest first, with what each charges and how much of it is already in the S&P 500.No findings

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    • The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
    Description, as the server wrote it
    Every US listed fund in a theme, largest first, with what each charges and how much of it is already in the S&P 500. USE THIS for any "what X ETFs are there" or "top X ETFs" question: it returns the whole published set rather than a sample.

    Annotations the server declares

    • title: Every fund in a theme
    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • etf_themesEvery theme ETFIQ publishes and how many funds each holds.No findings

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    • The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
    Description, as the server wrote it
    Every theme ETFIQ publishes and how many funds each holds. Call when unsure what a theme is called, then etf_theme.

    Annotations the server declares

    • title: All themes
    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • etfiq_as_ofWhat ETFIQ published on a given date, from its frozen dated archive.1 finding

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    • The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.

    Findings

    • Warn

      The description contains "every other tool", wording about other tools or servers.

      Matched text

      description: "...needs to stay true after it is quoted: every other tool here answers about today and today move..."

      What this check looks for
    Description, as the server wrote it
    What ETFIQ published on a given date, from its frozen dated archive. Use when a question is about a past date, or when a figure needs to stay true after it is quoted: every other tool here answers about today and today moves overnight. Takes YYYY-MM-DD. Covers the pieces written that night, not an arbitrary per-fund figure on an arbitrary day.

    Annotations the server declares

    • title: What ETFIQ published on a date
    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • etfiq_methodologyHow ETFIQ computes a figure, from the methodology page that says so: one page per desk (income, buffer, leverage, crypto, alternatives, themes), flows, scores, categories (how stoc…No findings

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    • The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
    Description, as the server wrote it
    How ETFIQ computes a figure, from the methodology page that says so: one page per desk (income, buffer, leverage, crypto, alternatives, themes), flows, scores, categories (how stock and bond funds are placed and which benchmark each is measured against), portfolio look-through, and the ETFIQ benchmarks for model portfolios. Pass topic, the reader's question in their words; the answer names the page, quotes the paragraphs that answer it and gives the page's text. A single fund's own benchmark follows its desk's rule (an income fund's is on the income page), never the model-portfolio benchmarks. Call with no topic for the list of pages.

    Annotations the server declares

    • title: How ETFIQ computes a figure
    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • etfiq_sectionsWhat ETFIQ publishes, section by section, with a page count for each, and start_here: the main pages (fund flows, the weekly flows report, ETF model portfolios and benchmarks, the …No findings

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    • The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
    Description, as the server wrote it
    What ETFIQ publishes, section by section, with a page count for each, and start_here: the main pages (fund flows, the weekly flows report, ETF model portfolios and benchmarks, the filed prediction-market and sports-team funds, issuers, methodology, rankings, the screener) with what each holds. Start here when the question is not about one fund.

    Annotations the server declares

    • title: What ETFIQ publishes
    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
Only reads 6Claude Code: allow
  • etfiq_listThe pages inside one section, optionally filtered to those whose address contains a word.No findings

    Why it is in this group

    • The name "etfiq_list" says "list": a word for reading.
    Description, as the server wrote it
    The pages inside one section, optionally filtered to those whose address contains a word. Use after etfiq_sections to find a page, then etfiq_page to read it. The count returned is the whole matching set even when the list is capped.

    Annotations the server declares

    • title: Pages in one section
    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • etfiq_pageRead ANY published ETFIQ page as text: a theme hub, a ranking, a comparison of two funds, an issuer, a methodology note, a dated study.No findings

    Why it is in this group

    • The description's first verb is "read": a word for reading.
    Description, as the server wrote it
    Read ANY published ETFIQ page as text: a theme hub, a ranking, a comparison of two funds, an issuer, a methodology note, a dated study. Takes a path like /themes/cyber or a full etfiq.com URL. This reaches all 40,000 pages, including everything the typed tools above do not cover, and returns the page content rather than its navigation.

    Annotations the server declares

    • title: Read any ETFIQ page
    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • find_pageThe designed ETFIQ pages that answer a question, best first, at most three: a fund, a comparison of two funds, the ETFs that hold a company, a ranking, a theme, a category, an issu…No findings

    Why it is in this group

    • The name "find_page" says "find": a word for reading.
    Description, as the server wrote it
    The designed ETFIQ pages that answer a question, best first, at most three: a fund, a comparison of two funds, the ETFs that hold a company, a ranking, a theme, a category, an issuer, the weekly flows report, a flows ranking, a dividend calendar, a screen, a benchmark, a model portfolio comparison, an FAQ answer or a methodology page. CALL THIS FIRST whenever the question could be answered by one ETFIQ page ("who holds NVDA", "SCHD vs VYM", "highest yielding covered call ETFs", "biggest ETF inflows this week"). Each page comes with its title, its address, its dated lead sentence exactly as the page prints it, and figures from its own .json twin (a fund's key facts, or the dated answers in the page's FAQ), with the match score (0 to 100) and the reason. answered is false when no page reaches the threshold: then answer with the other tools. Matching is deterministic: an exact phrase, an exact pair or a named entity with the intent its page answers, then word overlap. Pass path instead of query to read one page's card by its address.

    Annotations the server declares

    • title: Find the ETFIQ page that answers a question
    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • get_benchmarkOne ETFIQ benchmark in full: its rule as the methodology states it, the funds and weights in force (with SEC series ids and each fund's expense ratio and its date), and every stati…No findings

    Why it is in this group

    • The name "get_benchmark" says "get": a word for reading.
    Description, as the server wrote it
    One ETFIQ benchmark in full: its rule as the methodology states it, the funds and weights in force (with SEC series ids and each fund's expense ratio and its date), and every statistic ETFIQ computes for it by window (total return, return a year, volatility, maximum drawdown, Sharpe ratio, turnover, factor loadings, weighted expense ratio), each with its dates and its basis. ALWAYS read basis: a figure from before the freeze date is hypothetical. Takes an id such as etfiq-strategic-60 or strategic-60. Serves the published benchmark only; it cannot be customised.

    Annotations the server declares

    • title: One ETFIQ benchmark
    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • list_benchmarksThe ETFIQ benchmarks: published, rules-based yardsticks for model portfolios, each a written rule over broad, low-cost ETFs, grouped in families (strategic, tax-aware, factor, inco…No findings

    Why it is in this group

    • The name "list_benchmarks" says "list": a word for reading.
    Description, as the server wrote it
    The ETFIQ benchmarks: published, rules-based yardsticks for model portfolios, each a written rule over broad, low-cost ETFs, grouped in families (strategic, tax-aware, factor, income, tactical, thematic) by stock share. Filter by family, or by band (a name such as moderate, a stock share such as 60, or "all stocks"). Use when asked which benchmark measures a kind of model portfolio, then get_benchmark for one. These are not a single fund's own benchmark: that is in etf_profile (benchmark), and how it is chosen is in etfiq_methodology. A benchmark is identical for everyone and never a recommendation: a request to customise one or to say what to buy is refused, and a request to build a custom portfolio is for build_portfolio.

    Annotations the server declares

    • title: ETFIQ benchmarks for model portfolios
    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false

This is not a safety rating, and no finding is not a safety guarantee. The groups and findings come from fixed checks of the tool definitions the server returned on the date shown, not from its code or what it does when called. How the checks work.

Install

Pinned to version 0.2.0. Values in angle brackets are yours to fill in.

claude mcp add --transport http etfiq https://mcp.etfiq.com

Run in a terminal.

Claude Code permissions

Allow the reads, ask before a change, deny the deletes. Paste into .claude/settings.json.

.claude/settings.json
{
  "permissions": {
    "allow": [
      "mcp__etfiq__etf_search",
      "mcp__etfiq__etfiq_page",
      "mcp__etfiq__etfiq_list",
      "mcp__etfiq__find_page",
      "mcp__etfiq__list_benchmarks",
      "mcp__etfiq__get_benchmark"
    ],
    "ask": [
      "mcp__etfiq__etf_profile",
      "mcp__etfiq__etf_holdings",
      "mcp__etfiq__etf_theme",
      "mcp__etfiq__etf_themes",
      "mcp__etfiq__etfiq_sections",
      "mcp__etfiq__etf_screen",
      "mcp__etfiq__etf_overlap",
      "mcp__etfiq__etfiq_as_of",
      "mcp__etfiq__etf_holders",
      "mcp__etfiq__etf_rankings",
      "mcp__etfiq__etf_flows",
      "mcp__etfiq__etfiq_methodology",
      "mcp__etfiq__compare_to_benchmark",
      "mcp__etfiq__build_portfolio"
    ],
    "deny": []
  }
}

Tools that only read are allowed, tools that change things ask first, tools that delete or cancel are denied. It assumes the server is installed as etfiq. Review it before you use it.