MCP HeartbeatTHE MCP OBSERVATORY
Public workspace

Explore

Evidence for your next connection.

Independent measurements of remote MCP servers. Every observation has a timestamp.

Read-only probes

MCP server Β· Other

Ava Advisor

Your AI watches the markets so you can live your life. Financial intelligence for everybody.

Checks passed
15 / 22

0 failed Β· 7 not measured

Median response
642 ms

Median of successful probes over 7 days

30-day uptime
Not measured

Share of countable probes over 30 days, including daily rollups. Auth challenges are excluded.

Discovered tools
37

Tool definitions returned by this server

Independent monitoring

Health & checks

Status history

Responded

The server completed its last measured handshake. This is an observation, not a guarantee.

Last checked
Check summary by test group
Test areaPassedFailedUnmeasured
ConnectionCan a client connect and discover tools?
500
Reliability & speedDoes it respond consistently and quickly?
103
Access & authenticationWhat is required to use this server?
102
Tool qualityAre the tool definitions usable by an agent?
400
Publisher identityCan the publisher be traced to its source?
402

Unmeasured means there is not enough evidence to decide. How these checks work

Inspect individual checks 22 recorded

Core

  • Pass
    Reachable

    Latest probe returned HTTP 200 in 649 ms.

  • Pass
    Valid handshake

    protocolVersion 2025-11-25, serverInfo.name ava-advisor.

  • Pass
    Lists tools

    tools/list returned 37 tools.

  • Pass
    Current protocol

    Negotiated 2025-11-25. The bar is 2025-06-18 or newer.

  • Pass
    HTTPS

    The endpoint URL is https.

Performance

  • Not measured
    Fast (p50)

    Median latency 642 ms over 2 samples in 7 days. The bar is 1000 ms. Need at least 5 samples.

  • Not measured
    Consistent (p95)

    95th percentile 648 ms over 2 samples in 7 days. The bar is 3000 ms. Need at least 20 samples.

  • Not measured
    Reliable (uptime)

    2 of 2 attempts returned a tool list in 30 days (100%). The bar is 99%. Need at least 30 samples.

  • Pass
    Stable tool list

    No tool was removed and no required parameter was added in the last 30 days.

Access

  • Pass
    Open access

    tools/list succeeded with no credential, and the record declares none.

  • Not measured
    Standard auth

    Auth is not required, so the OAuth metadata check does not apply.

  • Not measured
    Free tier cited

    No publisher quote has been checked.

Tools

  • Pass
    Tools described

    Every tool description is at least 20 characters.

  • Pass
    Valid input schemas

    Every inputSchema is a JSON Schema object.

  • Pass
    Parameters documented

    220 of 220 parameters have a description (100%). The bar is 80%.

  • Pass
    Safety hints

    Every tool sets readOnlyHint or destructiveHint.

Publisher

  • Pass
    Verified namespace

    Listed in the Official MCP Registry.

  • Pass
    Website matches publisher

    The website host matches the reverse-domain namespace.

  • Pass
    Source repo linked

    A repository URL is on file.

  • Not measured
    Repo owner matches

    This namespace is not an io.github login, so the owner comparison does not apply.

  • Pass
    Recently updated

    Updated 2026-11-05T16:56:30.428245Z, within 180 days.

  • Not measured
    Open-source licence

    The GitHub licence lookup has not returned an OSI result yet.

Start using Ava Advisor

Connect to this server

Choose your client, copy the configuration, then enable the server in your client’s MCP settings.

Run this command in your terminal, then restart Claude Code.

Claude Code

claude mcp add --transport http ava-advisor https://mcp.ava.fund/mcp

Capabilities

Tools 37

add_to_playlist

πŸ”΄ WRITE β€” add one or more STOCKS/assets to a playlist (batch, idempotent). Each entry may be an exact Ava Advisor ticker OR a name/symbol the server resolves (any asset class: stock/ETF/commodity/crypto/FX). An ambiguous name (e.g. same name across markets) returns a `needs_confirmation` reconfirm β€” pick the exact ticker and re-call. `playlist_id` from `list_playlists`. Re-adding an existing ticker is a harmless no-op. Returns `{added, skipped, item_count}` β€” ⚠️ RELAY any `skipped` to the user; never drop it silently.

Discovered
brief

The generalized ANALYST BRIEF β€” one composed "how is <scope> doing right now?" picture (pulse + net direction, top_stories, winners/losers, aspect_heatmap, top_entities, top_assets) for any AND-combination of scopes. ⭐ Use to SUMMARIZE a scope (theme / news category / country / sector / aspect) β€” NOT a raw article list (that's search_news/news_feed). β›” NOT for a single COMPANY or market INDEX ("how is AAPL / the S&P doing?" β†’ options_sentiment + stock_impact/news_feed; an index maps to an ETF, not a brief scope). For a sectorΓ—region the quickest path is pulse(kind='theme', target='banks', country=…); use brief for one precise GICS cohort or an AND-combo. Scope by β‰₯1 of (CSV for several) β€” REQUIRED (never whole-market): β€’ `news_type` β€” a category; use ONLY these EXACT names: product_tech, ma_partnership, industry_thematic, earnings_results, corporate_action, management_governance, analyst_rating, macro_economic, geopolitics, commodity_supply, regulatory_legal, cybersecurity_digital_trust, digital_finance_tokenization, price_action_technical, crypto_related, forex_related, analyst_forecast. (commodityβ†’commodity_supply; central-bank/ratesβ†’macro_economic β€” there is NO 'monetary_policy'.) β€’ `country` (ISO-2) Β· `aspect` (impact channel) Β· `gics` (code or plain English) Β· `megatrend` (theme name/id). ⚠️ News coverage starts 2026-01-01. `node`+`ripple` appear only when a SINGLE megatrend anchors the brief.

Discovered
cot_extremes

⭐ FUTURES / CFTC-COT speculative positioning extremes β€” which commodity / FX / rate / equity-INDEX FUTURES have the CROWD at a 3-year extreme right now (NOT single-stock equity options β†’ for 'stretched put/call' or crowded STOCK names use options_scan). The discovery scan across every tracked futures market at once. COT / FUTURES lens ONLY. Surfaces stretched positioning (β‰₯90th or ≀10th percentile of its own 3y history) that could unwind hard on a shock β€” a contrarian-RISK map, NOT buy/sell calls (an extreme can persist). Use for 'where is FUTURES positioning most crowded / stretched right now?'. πŸ”΄ WRONG TOOL for single-STOCK options crowding β€” 'stretched put/call', 'one-sided / crowded equity names', 'most extreme options positioning across stocks': for those use options_scan (pattern='crowded / one-sided' β€” the equity-options opana lens across ~557 US optionable names). Narrate each `read` plainly.

Discovered
create_playlist

πŸ”΄ WRITE β€” create a new feed playlist (owner-scoped). Do NOT auto-create from a possible typo: call `list_playlists` FIRST and only create when the name genuinely doesn't exist, or the user confirms a new one. Returns the created playlist {id, name, …}.

Discovered
edit_screen

CHANGE a screener formula you already have β€” add, remove or replace conditions as ops; the server places, resolves and merges them and checks the result (no engine JSON to write). Use it for EVERY change while building a screen with the user; use screen_unified (mode 'run') when the user wants to SEE the stocks of a formula. Returns {ok, criteria (the new formula, saved shape β€” screen_unified takes it verbatim in `criteria`), changes (what each op became: status resolved|snapped, value, snaps / dropped / assumed = what the engine read differently), issues (what did not go in: code, and `nearest` / `candidates` = alternatives ready to send back as an op's value), keep (the user-set paths after the change), reset, charts (when conditions were split across charts), count?}. Nothing is saved β€” the client decides what to apply.

Discovered
etf_profile

What a US ETF / fund HOLDS: top holdings with % of NAV, sector (GICS) and country weights, plus the fund facts β€” AUM, expense ratio, benchmark / index or active, holdings count, top-10 concentration, tracking difference (SEC N-PORT / N-CEN filings; `as_of` dates say how fresh). Use it for "what does SCHD hold", "how concentrated is QQQ", "SPY vs VOO fees", "sector mix of XLE". ETFs rarely have news of their own β€” for "why is it moving" pair this with stock_impact / pulse on the top holdings. Non-fund tickers β†’ `not_a_fund`.

Discovered
financials

⭐ Company FINANCIAL STATEMENTS β€” income / balance / cash-flow + auto-detected abnormality signals. Read ONE company or COMPARE up to 8 (revenue, growth, margins, ROE, FCF…), on a clean normalized feed uniform across every industry (banks, insurers, REITs). πŸ”΄ To compare SEVERAL, pass them ALL in ONE call (tickers='TSLA.US,MSFT.US') β€” a single call aligns them on a common basis+currency and costs a fraction of N calls. Pick ONE `period` (quarterly already carries YoY). 🎚 `fields`: leave EMPTY for the DIGEST (small default β€” headline + ratios + capital-return + signals; covers most compares); set it for specific line items, a whole statement ('income'|'balance'|'cashflow'), or 'all'. ⏱ `period` = the window (5y / 2022 / 2022-2023 / 5q / 2024Q2), mapped to each fiscal year. 🌐 currency=USD (auto for multi-company) converts totals at each period's date. πŸ—£ The digest carries a plain `read` (facts, not advice) and may carry `_notes` (per-period comparability flags β€” the warning is FACT, each `likely_causes` is an inferred lead to VERIFY). πŸ“ LIMITS: ≀8 companies Β· ≀20 fields Β· ~4–5y history. A non-equity/unlisted entry β†’ `ok:false`. πŸ”΄ pulse(kind='asset') on a stock ALREADY embeds this digest β€” call financials only for a dedicated read/compare or a specific fields/statement pull, not right after pulse(kind='asset').

Discovered
fred_series

"What is <macro indicator> / is it high vs history / how has it moved" β€” ONE FRED series, feature-extracted. Pass a macro CONCEPT (the server resolves it to the canonical series_id + the right transform) or an exact id. Returns `series` (transformed points) + an `analysis` block: `latest` (+date β€” always say as-of-when), `trend`, `change` (vs prior/YoY/window), `peak`/`trough`, and πŸ”‘ `percentile`+`z_score` vs the window's own history (the money-shot for "high or low?" β€” e.g. unemployment 8th pct = historically very low), `volatility`, a one-line `read`. πŸ”΅ `transform` matters and is auto-picked from the resolved series ("inflation" = pc1 YoY % of a price index, a rate = lin) β€” override only deliberately. QUOTE the `read`; narrate the percentile. Compare two = call once per concept and diff. A concept that isn't a FRED series (ISM/PMI, a commodity SPOT price β†’ pulse(kind='commodity')) β†’ honest no_match, not a fabrication. US-govt series are public domain (`_license_note`).

Discovered
get_note

The FULL saved note (including its `body`) by id β€” owner-scoped. Use after `query_notes` when you need the complete content, not just the summary.

Discovered
latest_quote

The LATEST TRADED PRICE today for US stocks / ETFs β€” a DELAYED intraday quote (typically ~15 minutes behind), with today's change vs the previous close. Use it when the user asks about TODAY during the US session ("why is UBER down today", "where is NVDA trading"): every other price tool is END-OF-DAY (last close). US listings only β€” any other market returns `not_covered` (use stock_prices). Pair the move with today's news (stock_impact / search_news) for the why. State the quote time and that it is delayed; it is not a live tick.

Discovered
list_playlists

List the user's OWN feed playlists (id, name, emoji, item_count, items[{kind,ref_id,label}]). πŸ”΄ Call this FIRST whenever the user refers to a playlist BY NAME ("add X to My Tech List") β€” you match the (possibly mistyped / mis-spaced) name against the REAL names yourself. If the user didn't say WHICH and they own more than one, ASK which one (show the names). If they own NONE, offer to create one. Owner-scoped β€” only ever the user's own playlists. A playlist drives their news Feed.

Discovered
list_portfolios

List the user's OWN portfolios (id, name, base_currency, account_type, nav, total_return_pct, unrealized_pnl, position_count, …) so you can pick one to analyze. Call this FIRST whenever the user says 'my portfolio' without a number β€” show the names, then pass the chosen `id` to `portfolio_context`. Owner-scoped: only ever the user's own portfolios. If `count` is 0 (they own none), the response carries a `note` with a create link β€” relay THAT (invite them to create a portfolio) instead of saying an empty 'you have no portfolios'.

Discovered
list_themes

Browse / discover the megatrend taxonomy (25 tier-1 families + sub-nodes) β€” resolve a theme id.

Discovered
news_feed

The filtered impact feed β€” news by megatrend/country/aspect/direction/news_type, across stocks, FX, crypto, COMMODITIES (metals/energy) and private cos. Use for 'negative tariff news on Semiconductors', 'macro news moving European stocks', 'copper / metals news', etc. Near-duplicate stories are MERGED by default (+`dup_count`); `collapse=false` for the raw feed. `limit` = how many (default 20, max 50); narrow the filters rather than paging deep. TIME-SCOPE with `from_`/`to` (ISO) or a `window` ('90d','qtd','ytd','1y'). To COMPARE periods, call once per period and compare the results. ⚠️ News starts 2026-01-01 β€” older ranges return nothing (no coverage, not 'no news'). `megatrend` accepts a plain name/slug/concept ('foundry', 'AI chips') β€” resolved server-side to node id(s).

Discovered
options_scan

Find STOCKS by an options-behaviour pattern (opana lens) across the ~557 US optionable names — returns ranked UNDERLYINGS each with a plain-language `because` + `metrics` (value, and prev→delta for a trend/flip). STOCK scanner only: it does NOT pick option contracts/strikes/expiries (for one named stock's detail use `options_sentiment`). The `pattern` is a key OR plain English (the server resolves it) — its `temporal_mode` decides the read (level = now, rising/falling = ~2-week trend, flip = reversal). A `supported:'no'`/`'future'` pattern returns an empty list + an honest note (say so, don't substitute). US-capped — state that in the answer.

Discovered
options_sentiment

What the US OPTIONS MARKET is saying β€” the POSITIONING lens (~547 popular US optionable names, stocks + ETFs). Pairs with the newsβ†’impact read: for "how is <X> doing?" fetch THIS *and* `stock_impact`/`news_feed` and fuse them (news = what's happening + WHY; options = how the market is positioned β€” direction lean via put/call, fear/greed via skew, IV level, dealer-gamma stability, max-pain pinning, notable expiries). For a name the user HOLDS it shows how the market is hedging that position. Broad-INDEX question β†’ pass the liquid ETF proxy: S&P 500β†’`SPY`, Nasdaq 100β†’`QQQ`, Dowβ†’ `DIA`, Russell 2000β†’`IWM`, 20y Treasuriesβ†’`TLT`, Goldβ†’`GLD`. Tickers = bare US symbol or `SYMBOL.US` (`NVDA`/`NVDA.US`); US-only. `style` = `plain` (everyday language, default) | `technical`. TWO MODES: β€’ SINGLE deep read β€” pass `ticker=<one>` (+ optional `as_of`). Returns the FULL narrative payload (horizons, buckets, per-signal `read`+`because`, `_guide`). Use for a focused "how is NVDA doing". β€’ BATCH / COMPARE β€” pass `tickers=[...]` and/or `dates=[...]` β†’ ONE call returns a COMPACT grid, one small row per (ticker Γ— date) cell: `spot`, `positioning_score` ([-1,+1], + bullish), per-horizon positioning, and medium-term signal `reads`. THIS is how you answer "NVDA vs AAPL, last week vs this week" β€” do NOT fire the single tool NΓ—M times. `dates=[]` (omit) β†’ a single "latest" column. πŸ“… HISTORICAL: `as_of`/`dates` = ISO date/timestamp; the snapshot AT-OR-BEFORE that instant. A bare date (`2026-07-15`) is read as END of that day. Every response carries `available_from`/`available_to` (the stored window); a cell whose date predates it comes back `covered:false` with the range β€” relay THAT honestly (say history only goes back to `available_from`), never invent an older reading. ⚠️ Narrate from `read`+`because` (or the batch `reads`); DON'T recompute, DON'T compare raw O/S or IV across assets, `baseline_pending`/`level` β‰  "unusual" (only a `_percentile`/`_rank` read flags unusual), and the VERDICT is YOURS (opana stops at interpretation). Not covered β†’ `{covered:false}`: say options data isn't available and use the news/impact read instead β€” never fabricate.

Discovered
portfolio_context

An LLM-ready snapshot of ONE of the user's OWN portfolios (owner-scoped) β€” analyze it directly. NO window β†’ default: `meta` Β· `summary` Β· a `lifetime`(all-time) + `recent`(~12mo) block, EACH with `performance` (return/cagr/sharpe/sortino/calmar/drawdown/vol/win_rate) + `attribution` Β· `positions` Β· `closed_positions` (realized_pnl) Β· `composition` (point-in-time holdings) Β· `allocation` Β· `concentration` (HHI) Β· `inferred_behavior` Β· `flags`. `portfolio_id` from `list_portfolios`; 404 if not the user's. TIME WINDOW β€” `from_`/`to` (ISO) or `window` (`7d|30d|90d|180d|1y|mtd|qtd|ytd`): REPLACES lifetime+ recent with ONE `window` block (that span's `performance` + `attribution` + `nav_trend`) and scopes `composition` to match. So ANY period's return + drivers is answerable. `snapshots` = composition granularity only (`year|quarter|month|week|day|off`). πŸ”΄ MANDATORY for period questions: the default / `lifetime` / `recent` blocks DO NOT contain the performance or attribution of an arbitrary period (e.g. Q1-2025, "H1 2024"). To answer ANY specific period β€” or to COMPARE periods (Q1/25 vs Q1/26, 2023 vs 2025) β€” you MUST call this tool AGAIN with `from_`/`to` (or `window`) for EACH period, then compare the returned `window` blocks. NEVER derive a period's return/sharpe/drawdown/attribution from the default view β€” those numbers aren't in it; making them up is a hard error. If you haven't fetched a period's window, say you need to fetch it, don't guess. HOW TO ANALYZE (research-analyst framing β€” see avaadvisor://policy): β€’ Lead with the sharpest thing: a non-empty `flag`, or the biggest concentration / drawdown / tilt. β€’ "What drove the return / drawdown / strengths & weaknesses" (for the default OR a window) β†’ read `attribution.contributors[]` (per-holding `pnl_contribution` + `pct_of_nav_change` + `held` window; reconciles to `nav_change` to the cent, INCLUDES since-sold names). Don't estimate it yourself. β€’ "What did I hold on date X / how did the book evolve" β†’ `composition` (set `snapshots` + a window). β€’ ⚠️ TRUST THE EDGE NOTES, never fabricate: a window before the portfolio's `inception_date` returns `window.empty=true` + a note (or clamped) β€” say "the portfolio didn't exist then". If `composition.coarsened` is true, the step was widened to stay bounded β€” for finer, narrow the window. β€’ NEWS-AWARE: fuse `stock_impact` / `news_feed`/`search_news` on the holdings' `theme` paths for the WHY (⚠️ news only covers 2026+; portfolio history goes back to inception, further than news). β€’ Facts, not advice. Observe; do NOT tell them to buy/sell/rebalance/time β€” hand the judgment back.

Discovered
positioning

⭐ How the FUTURES market is POSITIONED β€” the CFTC Commitment of Traders lens for commodities, FX, rates and equity indices (the non-equity TWIN of options_sentiment; the two together cover positioning for every asset class). Answers 'is this trade crowded?', 'is the smart money leaning the other way?', 'is the good news already priced into positioning?'. Returns: `crowding` (the speculative crowd at a 3-year extreme = a contrarian RISK, NOT a timing call), `smart_vs_crowd` (are commercial hedgers β€” who know the physical/fundamental side β€” leaning against the crowd), `momentum` (building or unwinding; a flip = regime change), `fragility` (a few big traders holding it = reverses fast), and ⭐ `news_vs_positioning` (does recent news CONFIRM the crowd β†’ priced-in, or CONTRADICT a crowded position β†’ unwind risk). Weekly, as of the prior TUESDAY. For a RATE/YIELD asset (`.GB`/`.MM`) a long futures = positioned for LOWER yields (the reads already say it that way). πŸ—£ Every feature carries a PLAIN `read` β€” narrate it in EVERYDAY language for a beginner (no 'net'/'percentile'/'basis' jargon); say what it MEANS for risk. Facts, not advice β€” the verdict is yours. A stock / uncovered asset β†’ `__notfound`: say futures positioning doesn't apply and use options_sentiment / the news read instead.

Discovered
price_series

A SMALL, bounded price SERIES for drawing a chart (a device screen, a sparkline) plus headline numbers β€” the counterpart of `stock_prices`, which is a digested read with no series. Returns ticker, name, metric_kind (`yield` = a bond yield / rate: levels in %, moves in bps via period_change_bps / change_bps_by_period), currency, range, interval (`day`|`week`|`month`), period_start_date / period_end_date, last_close, period_change_pct, period_high / period_low (+ their dates), last_volume, average_daily_volume, change_pct_by_period {1w, 1mo, 3mo, ytd, 1y}, and `series` {dates, closes[, volumes]} as parallel arrays (≀ 65 points). EOD daily data, split/dividend-adjusted closes β€” the last point is the LAST CLOSE, not an intraday quote. Weekly/monthly points are each period's last close. Use this when a chart or a few chart numbers are needed; for "is it cheap / extended / why is it moving" use `stock_prices` or `pulse(kind='asset')`.

Discovered
private_movers

Off-coverage / private companies the news moved within a theme β€” the 'beyond tickers' surface. `limit` = how many (default 20, max 50). Returns {companies, count, total, note?} β€” honor `note` when `total` > `count` (it's a top slice, not the whole set).

Discovered
pulse

ONE market-pulse read across every subject type β€” a news + market lens on an asset, a theme/sector, a commodity, a bond/rate/curve, a macro dashboard, or your portfolio. Pick `kind`, put the subject in `target`. Replaces the per-type asset/theme/commodity/bond/macro/portfolio pulse tools.

Discovered
query_notes

Recall the USER'S OWN saved notes β€” their personal investment knowledge base (owner-scoped, only ever their notes). Two combinable ways: β€’ SEMANTIC recall via `q` β€” natural language ("what did I say about foundry manufacturing?"); results are ranked by MEANING with a `similarity` score (cross-language OK). β€’ Structured filters: `stock` (a ticker β†’ their notes about it), `theme` (a sector/trend NAME β†’ resolved to the megatrend, subtree included), `gics` (6-digit code), `tag`, `note_type` (reference/tracking/thesis/decision), `since` (e.g. '30d'). πŸ“Œ `stock` + `relation` (direct|indirect|any, default any) splits how a note relates to that ticker β€” same idea as newsfeed direct/indirect: `direct` = the note is ABOUT it (a subject); `indirect` = it's only REFERENCED (e.g. a peer named in a note about ANOTHER stock β€” a "NVDA vs peers" note surfaces under AMD as indirect). Every returned note carries a `relation` label when you filter by `stock`, so you can say "1 note about AMD + 1 that only mentions it". Use `relation="direct"` for "notes really about X". Returns note SUMMARIES + linked entities + `similarity` β€” NOT the full body (call `get_note(id)` for that). `limit` default 10 (max 50). πŸ”΄ FUSE personal + live: when the user asks about something they've likely noted, pair this with the live read β€” e.g. `pulse(kind='asset', target=NVDA)` AND "your NVDA thesis from last week said …". That personal- knowledge + live-graph combination is the whole point of the notes layer.

Discovered
relationships

Competitors + peers of a company (news-derived relationship graph). `limit` caps EACH list (default 15, max 50). Each side carries `total`/`count`/`note` β€” a big `total` (peers often run to hundreds) means you're seeing a TOP slice; say so rather than implying it's the complete set.

Discovered
remove_from_playlist

πŸ”΄ WRITE β€” remove one or more stocks (by ticker) from a playlist (batch). `playlist_id` from `list_playlists`. Returns `{removed, not_found, item_count}` β€” relay `not_found` (a ticker that wasn't in the playlist) to the user.

Discovered
screen_dividends

πŸ’° THE income screener β€” "which stocks pay a high / reliable / growing DIVIDEND?" Ranks the DIVIDEND-PAYING universe (all payers, not just news-covered) and hands you the raw pieces to tell a real income name from a YIELD TRAP (don't trust a headline yield). πŸ”΄ A multi-metric ask that also needs P/E / financial-health (dividend AND low P/E AND healthy) belongs in screen_unified (a `fundamental` leg + `dividend_min_streak_years`/`dividend_min_cagr` gate). THIS tool is the dividend specialist (no P/E filter) but it both INCLUDES (`gics`) and EXCLUDES (`exclude_gics`) a sector. Scope (country/gics) is OPTIONAL β€” omit both for a fast whole-market rank. πŸ”΄ `no_cut_streak_yrs` is a bounded RELIABILITY signal, capped at 10 (clean across the tracked decade incl. 2020/ 2022 stress) β€” NOT the dividend's full age; never state a multi-decade "aristocrat/king" streak, say "clean 10y+". Each row's `dividend` block decomposes the yield: `yield_pct` (forward/sustainable β€” quote this), `yield_trailing_pct` (>> yield_pct β‡’ a special inflated it), `payout_ratio` (>1 = unsustainable), `ttm_div_yoy_pct`, `no_cut_streak_yrs`, `last_cut_year`, `cagr_5y_pct`, plus `week52_high/low` + `pe_ratio`/`pb_ratio`/`eps` + a `news` block. πŸ”΄ Never rank on yield alone: high yield + recent `last_cut_year` + negative yoy + high payout + bad news = TRAP; high yield from a price drop + intact/growing dividend + long streak = possible VALUE. Read the payload's `_guide`. limit default 15 (max 50).

Discovered
screen_stocks

⭐ The cohort SCREENER: "which stocks in <a group> are interesting / winning / losing / most-talked-about, and how cheap or expensive do they trade?" Ranks the companies in a scope by how news is hitting them (lead with the winners-vs-losers split), and EVERY row carries its VALUATION (P/E, P/B, dividend yield, 52w) β€” so this is also the tool for "which in <group> are cheap / worth investing" (pulse(kind='theme')/brief are news-only, no valuation β€” pull P/E from here; P/B leads for banks/insurers). ⚠️ Rows are a NEWS-RANKED, CAPPED SUBSET, not the full cohort β€” do NOT compute a sector/peer AVERAGE from them (biased sample). For "cheaper/richer than the sector average / below-above the group / undervalued vs peers" use screen_unified with a `below_average`/`above_average` pattern (proper cap-weighted, outlier-cleaned benchmark). Scope β‰₯1 REQUIRED (never whole-universe): megatrend / gics / country β€” combine freely. Each row = {symbol, name, country, gic_code, market_cap_usd, impact:{news_count, pos, neg, ambiguous, net_direction, top_relevance, aspects, top_reason}, fundamentals:{pe_ratio, pb_ratio, dividend_yield_pct, week52_high, week52_low}}; `direction_split` pre-tallies winners/losers. ⚠️ per-stock impact scoring exists only from ~2026-07-03 β€” an earlier window returns empty (say so, not "nothing happened"). One ticker β†’ pulse(kind='asset'); a group's overall pulse β†’ pulse(kind='theme'); a sector-average benchmark β†’ screen_unified.

Discovered
screen_unified

EXECUTE a unified screen = universe ∩ fundamental ∩ technical ∩ options (any leg optional; each grammar resolved server-side β€” key or plain English). Returns {universe, count, sort, executed_criteria (the resolved request that ran β€” save/re-run it verbatim), results:[{head_listing_id, ticker, name, score, matched_legs, matched:{ta, fundamental:{<metric>:{value, basis, window?, series?, periods?}}}, context}], notes}. Evidence keys == the leg name you sent (TAβ†’matched.ta, fundamentalsβ†’matched.fundamental, NOT technical/financial); `matched_legs` lists which leg(s) a row passed. A thin intersection adds partial:true + per-leg near-misses β€” never present a partial/one-leg row as a full match; read `notes` (names the tighter leg + how to broaden). Time windows are PER-LEG: TA 'within last N bars' = top-level `window_bars`; a fundamental trend's span = that condition's `N`. Options leg is US-optionable only (~557 β†’ US-capped); sort='options' ranks by it; an options-vs-price divergence = just send the phrase in `options`. FAILS LOUD: an unsupported pattern/operand/concept returns a 400, so count:0 with NO error = a VALID query that matched zero now (loosen / widen window_bars, don't say 'can't do X'); `notes` may say 'insufficient history' (not a no-match) or which basis was screened. Over-fetches a ~4Γ— buffer (cap 100) so 'show me more' is served from these rows β€” don't re-call.

Discovered
search_news

SEMANTIC news search across ALL covered asset classes β€” stocks, FX, crypto, COMMODITIES (metals like copper/gold, energy like oil), and private companies. Articles matched by MEANING, impact-labeled (title, publisher, entities, direction, why). USE THIS for 'copper news', 'metals', 'gold', etc. instead of a web search. `entity_type` keeps only stock/forex/crypto/commodity/private hits. For a FILTERED feed by aspect/direction/country use `news_feed`. `limit` = how many (default 20, max 50). TIME-SCOPE with `from_`/`to` (ISO dates, e.g. '2026-04-01') or a `window` ('90d','qtd','ytd','1y'). ⚠️ News coverage starts 2026-01-01 β€” older ranges return nothing (that's no COVERAGE, not 'no news'). Returns {match_quality, top_similarity, note, results}. If match_quality is 'weak'/'none', the corpus has no strongly relevant news β€” do NOT present these results as evidence; say so and use another route.

Discovered
stock_impact

How news moved a specific company/asset (incl commodities like GOLD.COMM) β€” per-article impact (direction + aspect + why), most recent first. Near-duplicate stories are MERGED by default (each row = one story + `dup_count`); `collapse=false` for the raw feed. `limit` = how many (default 20, max 50). Ordered by how hard each story hits this entity (`relevance`, 1.0 = directly about it; a market wrap that touches it ranks lower), then recency; `companies_in_story` says when it is one of several β€” heavily-covered assets have HUNDREDS, so keep it small + narrow. TIME-SCOPE with `from_`/`to` (ISO) or `window` ('90d','qtd','1y'); to COMPARE periods, call once per period. ⚠️ News starts 2026-01-01 β€” older ranges return nothing (no coverage, not 'no news'; price/volatility history goes back decades). πŸ”΅ BONDS/RATES: a specific tenor/rate (`US-2Y.GB`, `SOFR.MM`) with no news of its own returns the country's benchmark-10Y macro news tagged `scope:'curve_macro'` + `macro_source` β€” narrate those as curve-wide central-bank context, not tenor-specific. πŸ“ MAGNITUDE: for a listed, priced asset each story has `price_move` = close-to-close % of the session it landed in (`day_pct`) and of the next one (`next_day_pct`) β€” the market's reaction next to the direction. It is the WHOLE day's move (other news counts too), not the story's isolated effect; say so. End-of-day prices: a story from today has no session close yet.

Discovered
stock_prices

Price context for a tradable ticker (stock / ETF / index-ETF / forex / crypto / commodity), split & dividend-ADJUSTED β€” a DIGESTED read, NOT a raw bar series: windowed changes (1w/1mo/3mo/ytd/1y), 52-week range + `drawdown_from_52w_high_pct` (how far below the peak), realized vol + `realized_vol_percentile_1y` (is today's vol high vs its OWN year), trend vs SMA50/200, volume conviction (`up_down_volume_ratio_1mo`, rvol). `*_read` fields are ready plain-language labels β€” quote them, don't re-derive. Reach for this on "is it cheap/extended / how has it moved / why is it dropping" β€” the LEVEL that makes a news+options read actionable (or use `pulse(kind='asset')` to get price + news + options in one). `to` = as-of date (point-in-time, YYYY-MM-DD, features as of that day); `from_` bounds history (narrowing below ~1y nulls the long windows). For a SECTOR/theme (not one ticker) use `pulse(kind='theme')`, not this. πŸ”΅ BONDS/RATES: if `metric_kind` == "yield" (a `.GB` govt-bond yield like US-10Y.GB or a `.MM` rate like SOFR.MM) the stored value is a LEVEL, not a price β€” narrate each window's `change_bps` in BASIS POINTS, NOT `change_pct` (a % of a yield is sign-inverted + the wrong unit; e.g. US-10Y 1y = "+52 bps", not "+12%"). Bonds also carry per-window `price_proxy_pct` + top-level `mod_duration` = an L1 bond-PRICE estimate (β‰ˆ βˆ’ModDurΓ—Ξ”y) for "the bond fell ~4%" narration (label it an ESTIMATE; for an exact bond return point to a bond ETF like TLT/IEF). Volume fields (`rvol`, `up_down_volume_ratio_1mo`, …) are `null` for a yield β€” don't present volume conviction; and yield↑ β‡’ bond price↓.

Discovered
stock_prices_batch

The same digested price context for UP TO 50 tickers in ONE call β€” a watchlist / cohort snapshot ("which of these names are most extended, or deepest in drawdown"). Returns `results` (in input order) + `unresolved` (unknown / no-price-history tickers). `to`/`from_` as in `stock_prices`.

Discovered
suggest_cta

After answering, propose 1-2 data-backed 'explore further' hooks that pull the user into the graph's moat (ripple/relations/commodity/off-coverage). Server-side: theme_summary(has ripple/ entities/aspects) + a semantic news search, then deepseek curates ONLY data-backed hooks. Validated in /tmp/mcp-gate/cta_tool.js (there via direct probes; here via the summary composite).

Discovered
theme_players

THE roster tool: investable MEMBER companies of a theme (curated membership). Rolls up sub-themes (a parent node returns its children's members too). Use this β€” not screen_stocks β€” for 'who are the players / real names in <theme>' (screen_stocks is a NEWS-ranked subset gated to news-epicenter members). `country='all'` (default) gives the complete cross-market list; an ISO-2 scopes to one trading venue. Different from top_entities (news-derived). `limit` = how many (default 20, max 50; big themes have many). Returns {stocks, count, total, note?} β€” if `total` > `count` it's a TOP SLICE: say so, don't present it as the full roster (raise `limit`).

Discovered
theme_summary

Pre-composed analyst brief for a megatrend theme: pulse, winners/losers, top entities, aspect heatmap, ripple. `theme` = a theme name or id/slug; `window` = 7d/30d/90d/1y/mtd/qtd/ytd.

Discovered
trade

International TRADE STATISTICS β€” countries' import/export flows, partners, rankings and balances from UN Comtrade (official customs data). NOT securities trading: it never places, routes or executes an order. Pick `mode`; each mode reads a subset of the params (see each param's note).

Discovered
wb_series

"<structural indicator> for <country>, over time / vs other countries" β€” World Bank annual data, feature-extracted (open data, 3 credits). Pass a structural CONCEPT (the server resolves it to the canonical indicator + variant) or an exact indicator id. Returns `results:[{country, series:[{year,value}], analysis}]` (one per country); `analysis` = `latest`(+year), `trend`, `cagr_pct`, `change`, `peak`/`trough`. ⭐ For a MULTI-COUNTRY call (comma-sep `country`) a top-level `ranking` orders them by the latest value β€” the cross-country compare FRED can't do. Annual STRUCTURAL data β†’ read levels + CAGR, not high-frequency moves. A country/year with no data is omitted (never interpolated). The right VARIANT (%GDP vs US$ vs per-capita) is picked from your `context`. A concept that isn't World-Bank structural (CPI/unemployment β†’ fred_series) β†’ honest no_match. Surface `_license_note` when showing data.

Discovered
write_note

πŸ”΄ WRITE β€” save a NOTE to the user's account (this PERSISTS data; it is NOT a read/lookup). Typical flow: FIRST give the user your complete answer as usual, THEN β€” as the final step of the turn β€” call `write_note` once to keep it. πŸ”΄ IF YOUR ANSWER CONTAINED A TABLE / NUMERIC COMPARISON, keep it as a MARKDOWN table in `body` β€” lead with the table, do NOT re-narrate the numbers into prose. Saving a figures answer as a wall of prose is the #1 note-quality failure; preserving structure OUTRANKS "distilling into a paragraph". (The figures are extracted from these markdown tables later for charts β€” so a clean table with clear headers is what makes that possible.) CONTENT: `subject` (short title), `body` (MARKDOWN β€” keep tables as tables, absolute headers like `FY2025`), `summary` (1–2 sentences), `note_type` (reference/tracking/thesis/decision), `category`, `tags` β€” see each field. ENTITY LINKS make the note findable + joinable to the graph β€” fill whenever the note touches specific things; the server RESOLVES plain names for you. `stocks` (the subjects) Β· `mentioned_stocks` (referenced) Β· `gics` (sector/theme, code or plain English) Β· `megatrend_ids` (advanced raw id) Β· `portfolio_id`. 🧭 LINK THE NOTE'S HOME β€” the theme/sector, not just the stocks. If the note is about a TREND/tech/mechanism ("what is HBM", "solid-state batteries") or an established INDUSTRY/SECTOR ("retail", "airlines", "pharma"), put the word(s) straight in `gics` (plain English β€” the server resolves each and routes a themeβ†’megatrend). A note whose subject is a trend or a sector, saved with EMPTY `gics`, means you SKIPPED this. The only correct empties: a single-stock note (stocks only) or a general concept with no home (P/E, EBITDA β€” don't force it; tags/body still make it findable by semantic search). WHEN TO SAVE β€” this is the investor's knowledge base; CAPTURE substantive investment content generously (reference/understanding, a dated market-read WITH its 'why', a thesis/decision, curated research). Value is realized on RETRIEVAL, so lean toward keeping. SKIP only the noise floor: chit-chat/thanks, trivial lookups ("what's the ticker?"), or off-topic non-investment content (save that only if explicitly asked). An explicit "save this / ΰΈˆΰΈ”ΰΉ„ΰΈ§ΰΉ‰" β†’ always save. Otherwise, if the content is note-worthy, briefly OFFER to keep it β€” don't nag on every turn, and don't save pure filler. 🏷️ `agent` β€” ALWAYS set this to the app you are running in, chosen from the fixed list: `Claude` (Claude apps / claude.ai / Desktop), `Claude Code`, `Claude Coworks`, `ChatGPT`, `Codex`, `Gemini`, or `Other` (anything not listed). It stamps WHICH surface authored the note (provenance in the user's knowledge base). Pick the single closest match; if genuinely unsure, use `Other`. Do not invent values β€” only these are accepted. Owner-scoped. Returns `{id, created_at, linked}` where `linked` confirms what was tied to the graph (resolved ids + any `unresolved` names).

Discovered

Recent measurements

Probe history

View status
Latest stored probes. Raw probe rows are kept for 14 days.
CheckedResultResponseTools
Connected649 ms37
Connected634 ms37