RiskModels
Use this read-only MCP server to query US equity risk, returns, hedging, and portfolio analytics.
Single-stock risk: get latest risk snapshot, decompose risk by market/sector/subsector/residual, compute ETF hedge ratios and dollar hedges.
Multi-stock comparison: compare 2–100 tickers on risk layers.
Returns & attribution: fetch daily dividend-adjusted total returns, split returns into factor and residual components, get residual returns and recommended hedge depth.
Signals: compute basket residual mean-reversion signals.
Macro & factors: get macro factor correlations and macro/sector ETF factor returns.
Fundamentals: retrieve point-in-time quarterly fundamentals, valuation betas, cost of debt, WACC, economic profit.
Portfolio analytics: analyze long-only portfolios (hedge levels, ETF hedges), get full portfolio risk snapshots, long/short exposure and neutralizing trades, and selection-vs-drift attribution.
Brokerage: read linked brokerage positions.
Rankings & screening: get single-stock percentile ranks, screen ranked universe, cohort statistics, and peer groups.
Search & reference: resolve tickers/ETFs/funds/13F filers, get fund/filer/ETF profiles, and benchmark fit.
Pricing: pay-as-you-go per call (most $0.005–$0.25; portfolio risk snapshot $1.25; some free).
This server has a remotely hosted endpoint. Open its connector listing for connection details, authentication requirements, and setup instructions:
RiskModels provides clean dividend-adjusted total returns, factor risk decomposition, return attribution, and ETF-executable hedge ratios for US equities — over REST, a typed SDK, and a built-in MCP server. The dataset is simulation-grade: it covers on the order of 16,000 US stocks across the full historical panel, while at each month end the model’s headline universe is the largest ~3,000 by market cap—the set the API surfaces for everyday returns, risk, and hedging.
Post-regression outputs (hedge ratios, explained-risk decompositions, and related L1–L3 series) are served from the first date whose full estimation window is covered: hedge ratios from 2010-12-08, explained-risk shares and stock variance from 2011-12-07, L* residual levels from 2013-01-01. Split- and dividend-adjusted returns (the inputs to the rolling regressions) begin 2006-01-04. The API is AI-agent ready, including a built-in Model Context Protocol (MCP) server for seamless integration with LLMs.
RiskModels API Developer Portal
This repository is the authoritative public API reference for the RiskModels equity risk model API, featuring:
📖 Model methodology — ERM3 overview (canonical; also mirrored on riskmodels.net)
📚 Comprehensive API Documentation — OpenAPI 3.0.3 specification, guides, and examples
🌐 Developer Portal — Beautiful Next.js site (this repo) deployed at riskmodels.app
🐍 Python & TypeScript Examples — Production-ready code in
examples/🤖 AI Agent Integration — MCP server, OAuth2, and agent manifest
Use in Cursor (Agent Plugin)
This repository is an Agent Plugins package: plugin.json and mcp.json at the repository root. The plugin connects Cursor to the hosted RiskModels MCP server. It contains no code that runs on your machine and no credentials.
File | What it declares |
Plugin | |
One server, |
Install
In Cursor, open the Marketplace and search for RiskModels.
Install it for your user or for the current project.
Cursor adds the
riskmodelsMCP server. Its tools appear once you sign in.
Sign in
The server uses OAuth 2.1 with PKCE. Cursor handles the flow, and nothing goes in the plugin files:
When Cursor first connects to the
riskmodelsserver, the server asks for sign-in and Cursor opens a browser at riskmodels.app.Sign in with Google or an email link, or choose Sign in with a password instead.
The consent screen shows Signed in as <email>. If that is the wrong account, click Use a different account first, then Allow.
Cursor stores the token. The tools are read-only: they return data and never place orders or change your account.
Pricing and account
A RiskModels account is required. New accounts start with $20 of prepaid credit. A payment method is collected at signup for verification and is not charged until you top up.
Usage is pay-as-you-go and billed per tool call against that balance. Most single-stock calls cost $0.005; fundamentals cost $0.02, and a full portfolio exposure report costs $0.25. Rates and plans: riskmodels.app/pricing.
Optional: link a brokerage account (Alpaca, Connect Trade or Plaid) in riskmodels.net Settings, and
riskmodels_get_my_positionsreads that book.
Example: NVDA
Ask in Cursor's agent chat:
Decompose NVDA's risk with RiskModels and give me the ETF hedge for a $100,000 position.
The agent calls riskmodels_decompose for the market / sector / subsector / stock-specific split of NVDA's variance and the hedge ratio at each level. Then it calls riskmodels_decompose again with a dollar amount to turn those ratios into dollar trades in SPY and the sector and subsector ETFs. The numbers are live model output as of the latest trading day.
The Claude plugin (claude-plugin/) and the local developer MCP server (.cursor/mcp.json, mcp/) are separate and unchanged.
Related MCP server: QuantRisk-MCP-Server
🚀 Quick Links
Python SDK — AOM quickstart (Google Colab): Open notebook · source:
sdk/notebooks/riskmodels_aom_colab.ipynbDeveloper Portal: riskmodels.app
Live API Docs: riskmodels.net/docs/api/erm3
ERM3 methodology: riskmodels.app/docs/methodology
Get API Key: riskmodels.app/get-key
API Terms: riskmodels.net/terms/api
PyPI (Python SDK): riskmodels-py
Canonical URLs (REST, OpenAPI, and docs)
Use these only for integrations and tooling:
What | URL |
REST base (OpenAPI |
|
Deployed OpenAPI JSON (same spec as |
|
Interactive API reference (this portal) |
Important: The hostname api.riskmodels.app is not used for the public API or machine-readable docs. Older links or docs that mention it should be treated as obsolete; use riskmodels.app (apex) as above.
📖 API Overview
The RiskModels API provides institutional-grade equity risk analysis:
Daily factor decompositions — market, sector, subsector explained-risk fractions for the headline ~3,000 largest US stocks by market cap (month-end universe)
Hedge ratios — dollar-denominated ETF hedge amounts (L1/L2/L3) designed to remain executable with liquid raw ETFs
Historical time series — split- and dividend-adjusted returns (2006-01-04–present) plus rolling hedge ratios (2010-12-08–present) and ER (2011-12-07–present; factor outputs need a full regression window)
AI-agent ready — OAuth2, per-request billing, machine-readable manifests
Data coverage: ~16,000 US stocks in the historical panel; ~3,000 largest by market cap at each month end for headline outputs. Updated daily. Hedge ratios: 2010-12-08 through present. Explained risk: 2011-12-07 through present. L* levels: 2013-01-01 through present. Adjusted return series: 2006-01-04 through present.
Why The Engine Matters
RiskModels is designed to be useful for real portfolio work, not just descriptive analytics:
Built to be time-safe — the engine is designed to avoid common sources of forward contamination such as recycled tickers, snapshot shares, and retroactive universe contraction
Grounded in a real Security Master — ticker-level outputs sit on top of a point-in-time identity layer built for identifier continuity, symbol changes, and historically defensible shares data
Hierarchical by design — the model separates market, sector, and subsector structure rather than collapsing everything into a flat beta view
Tradeable in practice — the published hedge ratios are designed to work with liquid ETFs at execution time, not only with synthetic or orthogonalized factors
Built on adjusted return series — split- and dividend-adjusted returns make the decomposition and hedge ratios more economically consistent over long horizons
For a deeper explanation of the engine design choices behind these claims, see the methodology docs and API reference.
🐍 Python SDK (riskmodels-py)
Prefer the Python SDK over raw REST for agent-native workflows — ticker resolution, semantic field normalization, validation with instructional errors, and LLM-ready context formatting are built in.
Install (PyPI):
pip install riskmodels-py
# Optional — xarray cube from batch Parquet/CSV:
# pip install riskmodels-py[xarray]
# Optional — snapshot PDF rendering:
# pip install riskmodels-py[pdf]Quickstart:
from riskmodels import RiskModelsClient, to_llm_context
client = RiskModelsClient.from_env()
pa = client.analyze({"NVDA": 0.4, "AAPL": 0.6})
print(to_llm_context(pa))Snapshot generation (institutional PDF reports):
from riskmodels.snapshots import get_data_for_r1, render_r1_to_pdf
client = RiskModelsClient.from_env()
data = get_data_for_r1("NVDA", client) # fetch → R1Data (caches to JSON)
render_r1_to_pdf(data, "NVDA_R1_Risk.pdf") # render → PDF (~0.3s, no API)Documentation:
Package README — install, methods, agent-native helpers
Quickstart — 60-second setup path
API Docs — agent-native helpers reference table
Risk intelligence
Charts below are generated from live API data (get_rankings + MAG7 L3 batch metrics) via scripts/generate_readme_assets.py. Set RISKMODELS_API_KEY (free tier is sufficient), run the script from the repo root, then commit ./assets/ and ./public/docs/readme/.
MAG7 — L3 σ-scaled decomposition
Cross-sectional rankings
🤖 MCP Server (v3.0.0-agent)
RiskModels includes a first-class MCP (Model Context Protocol) server, enabling AI agents to directly query risk data and perform factor analysis.
MCP Connection (hosted API):
Endpoint (Streamable HTTP, POST):
https://riskmodels.app/api/mcpNamed endpoints:
/api/mcp/openaiand/api/mcp/sseremain supportedAuthentication: Bearer token (API key or OAuth2 JWT)
Discovery:
https://riskmodels.app/.well-known/mcp.json(see OPENAPI_SPEC.yaml)
Local MCP server (mcp/ in this repo, @riskmodels/mcp 2.0.0) — stdio transport for Cursor / Claude Desktop / Zed. Tool set 2.0 is one registry shared with the hosted endpoints: 25 tools locally, 26 hosted (adds riskmodels_render_artifact):
riskmodels_get_stock_snapshot, riskmodels_decompose, riskmodels_compare, riskmodels_get_returns, riskmodels_get_return_attribution, riskmodels_get_residual_returns, riskmodels_get_residual_signal, riskmodels_get_macro_correlation, riskmodels_get_fundamentals, riskmodels_analyze_portfolio, riskmodels_get_portfolio_risk_snapshot, riskmodels_portfolio_exposure, riskmodels_decompose_selection_vs_drift, riskmodels_get_my_positions, riskmodels_get_rankings, riskmodels_screen_rankings, riskmodels_get_cohorts, riskmodels_get_peers, riskmodels_search, riskmodels_resolve_security_identity, riskmodels_get_filer, riskmodels_get_fund, riskmodels_get_etf, riskmodels_get_benchmark_fit, riskmodels_get_factor_returns.
The REST catalog, response schemas and OpenAPI spec are MCP resources (riskmodels:///capabilities, riskmodels:///schemas/{path}, riskmodels:///openapi). Tool list, prices and the 1.x → 2.0 migration table: mcp/README.md. Outside MCP, call the REST API or the Python SDK (riskmodels-py).
See mcp/README.md for install and config.
Anthropic Claude (Managed Agents vs Messages API): internal engineering design for optional cloud-hosted agents, billing, and compliance — see docs/ANTHROPIC_CLOUD_AGENTS.md.
⌨️ Command-line CLI (riskmodels)
The npm package in cli/ installs the riskmodels binary: config, SQL query (billed API or direct Supabase), schema introspection, balance, and static agent manifests.
Install from npm:
npm install -g riskmodels
riskmodels --helpDevelop from this repo:
cd cli
npm ci
npm run build
npm run install:global # optional: npm link for local testingPublish to npm (maintainers): procedure is documented in the private BWMACRO monorepo (docs/RISKMODELS_CLI_NPM_PUBLISHING.md), not here. Only publish from the cli/ directory — the repo root Next.js app is not published to npm.
💻 Developer Portal (This Repo)
This repo now includes a Next.js developer portal with:
✨ Hero landing page with feature highlights
📚 MDX-powered documentation (README_API.md, AUTHENTICATION_GUIDE.md)
🔍 Interactive API reference (Redoc OpenAPI viewer)
💡 Code examples with syntax highlighting and copy buttons
🎯 Step-by-step quickstart guide
Local Development
# Install dependencies
npm install
# Option A: Copy env template and fill in Supabase/Stripe keys manually
cp .env.example .env.local
# Option B: Use Doppler (recommended for team consistency)
# Ensure `doppler login` is done, then:
doppler secrets download --no-file --format env > .env.local
# Generate OpenAPI JSON for Redoc
npm run build:openapi
# Run dev server
npm run devScreenshot Capture Hygiene:
When capturing site screenshots for audit or documentation:
Ensure the build passes first:
npm run buildmust complete without errorsVerify the dev server serves HTTP 200: Visit
http://localhost:3000and confirm pages render (not "Internal Server Error")Run the capture script:
python3 capture_site.py(requires Playwright)
The script will skip pages returning HTTP 500 or containing "Internal Server Error" content. Screenshots with server errors should never be committed to the repository.
Environment Management with Doppler:
This repo uses Doppler for secrets management. The doppler.yaml is pre-configured for the erm3 project:
# Verify setup (should show project: erm3, config: dev)
doppler setup
# List all secrets
doppler secrets
# Get a specific secret
doppler secrets get STRIPE_SECRET_KEY
# Export dev secrets to .env.local for curl testing and local dev
npm run doppler:env
# Push production secrets to Vercel (requires vercel login + project link)
npm run vercel:sync-env:dopplerFor curl/API testing with Doppler secrets:
# 1. Export secrets to .env.local
npm run doppler:env
# 2. Source them for your shell session
source .env.local
# 3. Use in curl commands
curl -H "Authorization: Bearer $RISKMODELS_API_SERVICE_KEY" \
https://riskmodels.app/api/healthSee DEPLOYMENT.md for detailed Vercel/Doppler integration.
Visit http://localhost:3000
Build & Deploy
# Build for production
npm run build
# Start production server
npm startDeployment: See DEPLOYMENT.md for Vercel setup, env vars, and Supabase/Stripe config.
📂 Repository Structure
RiskModels_API/
├── app/ # Next.js app
│ ├── api/ # API routes (REST)
│ ├── page.tsx # Hero landing page
│ ├── layout.tsx # Root layout with Navbar/Footer
│ ├── docs/[[...slug]]/ # MDX docs renderer
│ ├── api-reference/ # Redoc OpenAPI viewer
│ ├── examples/ # Code examples showcase
│ └── quickstart/ # Quickstart guide
├── components/ # React components (new)
│ ├── Navbar.tsx
│ ├── Footer.tsx
│ ├── Hero.tsx
│ ├── CodeBlock.tsx
│ └── Logo.tsx
├── content/docs/ # MDX content (new)
│ ├── api.mdx
│ └── authentication.mdx
├── cli/ # Command-line CLI (`riskmodels`)
├── sdk/ # Python SDK (`riskmodels-py`) source
│ └── riskmodels/snapshots/ # Snapshot PDF pipeline (R1 shipped, R2–P4 planned)
├── examples/ # Runnable examples
│ ├── python/
│ └── typescript/
├── mcp/ # MCP (Model Context Protocol) server
├── public/ # Static assets (new)
│ ├── transparent_logo.svg
│ └── openapi.json # Generated from OPENAPI_SPEC.yaml
├── styles/ # Global styles (new)
├── lib/ # Utilities (new)
├── OPENAPI_SPEC.yaml # Canonical OpenAPI spec
├── README_API.md # API reference (source for content/docs/api.mdx)
├── AUTHENTICATION_GUIDE.md # Auth guide (source for content/docs/authentication.mdx)
├── SEMANTIC_ALIASES.md # Field definitions
└── package.json # Next.js deps (new)🛠️ Tech Stack (Developer Portal)
Framework: Next.js 15 (App Router)
Styling: Tailwind CSS 3.4, dark mode default
MDX: @next/mdx for documentation
API Reference: Redoc (OpenAPI 3.0 viewer)
Code Highlighting: Custom CodeBlock with copy button
Fonts: Inter (system-ui fallback)
Colors: Blue primary (
hsl(217, 91%, 60%)), zinc/slate dark palette
📄 Documentation Files
Document | Description |
Complete API overview, endpoints, key concepts | |
API Terms of Service (riskmodels.net/terms/api) | |
Plaid connection flow and holdings API user experience | |
Bearer token, OAuth2, Supabase JWT, rate limits | |
Process for adding new documentation | |
Field definitions, units, formulas | |
| |
Error codes and recovery patterns | |
OpenAPI 3.0.3 specification (v3.0.0-agent) | |
Snapshot suite roadmap, ADRs, and implementation phases | |
8-page content spec with wireframes and JSON schemas | |
Pure-Matplotlib rendering pipeline architecture |
🔗 Related
ERM3 — Python risk model computation engine (open source)
🤝 Contributing
We welcome pull requests, especially to improve the OpenAPI spec — clearer descriptions, better schemas, and more examples help everyone.
OpenAPI spec: CONTRIBUTING.md — PRs to
OPENAPI_SPEC.yamlare encouragedIssues: Open an issue for bugs or feature requests
Examples: Submit new examples via PR to
examples/Docs: Improve documentation by editing MDX files in
content/docs/
📧 Support
API Support: service@riskmodels.app
Status: riskmodels.net/status · API metrics riskmodels.app/api/status
📜 License
See LICENSE for details.
© 2026 Blue Water Macro Corp. All rights reserved.
Deploy trigger: Tue Jun 9 16:13:22 PDT 2026
Available Tools
24 toolsriskmodels_analyze_portfolioRiskModels Portfolio Hedge Levels and ETF HedgeARead-onlyInspect
Use when you have a long-only book of up to 100 names and want its holdings-weighted L1, L2 and L3 hedge ratios, or the ETF hedge notionals for dollar positions. Not for books with shorts or more than 100 names (use riskmodels_portfolio_exposure) or a variance decomposition with return attribution (use riskmodels_get_portfolio_risk_snapshot). Returns, from POST /batch/analyze, portfolio hedge levels at L1, L2 and L3 with per-ticker detail. Only when every position is given in dollars does it also return the ETF hedge notionals at hedge_level (set by level, default L3), by ticker and summed by ETF; with weights, level is ignored. End-of-day data, refreshed after each US market close. Price: $0.015 per position, minimum $0.03 per call.
| Name | Required | Description | Default |
|---|---|---|---|
| level | No | Hedge depth for the ETF notionals, used only when every position is in dollars, e.g. L2 (default L3) | |
| years | No | Lookback window in years, integer 1-30, e.g. 2 (default 1) | |
| positions | Yes | Long positions, each with weight or dollars, combined per ticker, e.g. [{"ticker":"AAPL","dollars":25000},{"ticker":"NVDA","dollars":15000}] |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover the read-only/no-destruction profile, and the description adds substantive behavior beyond them: conditional output (ETF notionals only when all positions are in dollars; level ignored with weights), data freshness (end-of-day, refreshed after US close), and pricing ($0.015/position, $0.03 minimum). These are exactly the traits an agent cannot get from the structured fields.
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?
Front-loaded with the use case, then exclusions, then returns, then cost/freshness. Dense and mostly waste-free, though the returning-behavior sentence is somewhat long and could be split for scanability.
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?
No output schema exists, but the description explains return values, the conditional branch that gates ETF notionals, defaults (level default L3), limits (100 names), data latency, and cost. An agent has everything needed to call and interpret it correctly.
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?
Schema coverage is 100% so baseline is 3, but the description adds meaning the schema does not: that 'level' is used only when every position is in dollars and is ignored when weights are supplied, and that the dollars-vs-weight choice gates which outputs appear. That conditional coupling of parameters to outputs is genuine added value.
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?
States a specific resource (long-only portfolio hedge levels / ETF hedge notionals) and the exact conditions (up to 100 names, holdings-weighted L1-L3). It explicitly names the siblings it is not for, so an agent can distinguish it from riskmodels_portfolio_exposure and riskmodels_get_portfolio_risk_snapshot without opening schemas.
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?
Gives explicit when-to-use ('long-only book of up to 100 names'), when-not ('books with shorts or more than 100 names'), and names the alternative tool for each excluded case. Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
riskmodels_compareRiskModels Multi-Ticker ComparisonARead-onlyInspect
Use when you want 2-100 stocks side by side on market, sector, subsector and residual risk. Not for one stock (use riskmodels_decompose) or a weighted portfolio (use riskmodels_analyze_portfolio). Returns, from POST /batch/analyze, each ticker's explained-risk shares and hedge ratios by layer, with chart-ready data. End-of-day data, refreshed after each US market close. Price: $0.015 per ticker, minimum $0.03 per call.
| Name | Required | Description | Default |
|---|---|---|---|
| tickers | Yes | 2-100 US stock ticker symbols, e.g. ["AAPL","NVDA"] |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnlyHint=true, destructiveHint=false), and the description goes well beyond them: the upstream endpoint (POST /batch/analyze), the exact return content (explained-risk shares and hedge ratios by layer, chart-ready), data freshness (end-of-day, refreshed after each US market close), and billing terms ($0.015 per ticker, $0.03 minimum). This is unusually rich behavioral context.
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?
Four tight sentences, front-loaded with usage and exclusions, then returns, then freshness and cost. Every sentence carries distinct information an agent needs; no 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?
There is no output schema, so the description must carry return-value disclosure, and it does: risk-share and hedge-ratio outputs by layer with chart-ready framing. Combined with cost, freshness, and routing guidance, an agent has everything needed to call and interpret this tool.
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?
With a single parameter at 100% schema description coverage, the schema already documents the ticker array including the 2-100 bounds. The description's '2-100 stocks' and ticker-symbol framing restate the schema rather than adding format, ordering, or validation nuance. 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?
States a specific operation (side-by-side comparison) on a specific resource (2-100 stocks across market, sector, subsector and residual risk layers). It explicitly names the siblings it is not (riskmodels_decompose for one stock, riskmodels_analyze_portfolio for a weighted portfolio), so an agent can select it without opening any schema.
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?
Opens with an explicit when-to-use condition (2-100 stocks side by side) and follows with two explicit when-not conditions paired with the correct alternative tools. Nothing about tool selection is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
riskmodels_decomposeRiskModels Single-Stock DecompositionARead-onlyInspect
Use when you want one stock's risk split into market, sector, subsector and residual layers, or the ETF hedge legs for a dollar position in it. Not for several stocks (use riskmodels_compare) or a portfolio (use riskmodels_analyze_portfolio). Returns, from POST /decompose, each layer's explained-risk share, hedge ratio and hedge ETF, chart-ready data and a one-line summary; with dollars it returns the ETF hedge notionals for that position at each level (hedge ratio times dollars). End-of-day data, refreshed after each US market close. Price: $0.005 per call.
| Name | Required | Description | Default |
|---|---|---|---|
| ticker | Yes | US stock ticker symbol, case-insensitive, e.g. NVDA | |
| dollars | No | Position size in US dollars, a positive number, e.g. 10000. Omit for the decomposition alone |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover safety (readOnlyHint=true, destructiveHint=false), yet the description adds substantial context beyond them: it discloses the POST /decompose endpoint despite being read-only, end-of-day freshness ('refreshed after each US market close'), and a concrete price of $0.005 per call. Cost and data-freshness disclosure go well beyond structured fields.
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?
Front-loaded with the use case, then exclusions, then return shape, freshness and pricing. Dense but every clause earns its place; slightly long, yet nothing is redundant with structured fields.
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?
No output schema exists, so the description carries the return-shape burden and does so clearly (explained-risk share, hedge ratio, hedge ETF, chart-ready data, one-line summary, hedge notionals when dollars is supplied). Combined with freshness, cost and endpoint disclosure, nothing material is missing.
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?
Schema coverage is 100%, so baseline is 3. The description adds value by explaining the semantic effect of the optional parameter ('with dollars it returns the ETF hedge notionals for that position at each level (hedge ratio times dollars)'), connecting an input to a concrete output beyond the schema's 'position size' wording.
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?
Names the specific resource (one stock's risk split into market, sector, subsector and residual layers, plus ETF hedge legs for a dollar position) and explicitly distinguishes from siblings by name (riskmodels_compare for several stocks, riskmodels_analyze_portfolio for portfolios). An agent can identify the tool without opening the schema.
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?
Unambiguous when/when-not: 'Use when you want one stock's risk...' followed by 'Not for several stocks (use riskmodels_compare) or a portfolio (use riskmodels_analyze_portfolio).' It even conditions the hedge-leg behavior on supplying dollars.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
riskmodels_decompose_selection_vs_driftRiskModels Selection vs DriftARead-onlyInspect
Use when you want a book's realized residual return over a date window attributed to stock selection versus drift. Not for current risk or hedges (use riskmodels_portfolio_exposure). Returns, from POST /cohorts/pnl-decomposition, selection (from holding names that beat their cohort's average residual) and drift (from net exposure to the cohort average), which sum exactly to the total; weights are held constant over the window and not normalized, a short is a negative weight, and positions that cannot be mapped to a cohort are listed in coverage.dropped. Historical attribution on end-of-day data. Price: $0.25 per call.
| Name | Required | Description | Default |
|---|---|---|---|
| level | No | Cohort level, e.g. market (default sector) | |
| end_date | No | Window end, format YYYY-MM-DD, e.g. 2026-06-30 | |
| min_names | No | Ignore cohort means on days the cohort had fewer members, integer, e.g. 20 | |
| positions | Yes | The book to attribute, 1-500 positions, e.g. [{"ticker":"MSFT","weight":0.1},{"ticker":"INTC","weight":-0.05}] | |
| start_date | No | Window start, format YYYY-MM-DD, e.g. 2026-01-02 | |
| include_series | No | true adds the daily selection and drift series (large), e.g. true (default false) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (which already convey read-only, non-destructive, open-world), the description discloses the backing endpoint (POST /cohorts/pnl-decomposition), that selection+drift sum exactly to the total, that weights are held constant and not normalized, that shorts are negative weights, that unmapped positions appear in coverage.dropped, that data is historical end-of-day, and that each call costs $0.25.
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?
Dense but front-loaded: the usage condition and the primary exclusion come first, then the return/behavioral detail. Every clause carries information, though the mid-sentence semicolon chain is heavy; sizing is appropriate for a paid, non-trivial analytics call.
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?
There is no output schema, so the description must explain the return contract, and it does: selection, drift, their exact summation, and the coverage.dropped list. Together with the pricing and historical-data note, an agent has everything needed to call and interpret it.
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?
Schema description coverage is 100%, so the baseline is 3. The description reinforces weight-sign semantics ('a short is a negative weight') and adds the non-normalization/constant-weight constraint, but it repeats the schema's weight definition and adds little on level, end_date, min_names, or include_series.
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 states a specific verb+resource: attributing a book's realized residual return over a date window to stock selection versus drift. It clearly distinguishes itself from the general riskmodels_decompose and from riskmodels_portfolio_exposure by naming what it does not cover, so an agent can select it without opening schemas.
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?
It leads with explicit 'Use when...' guidance for the target scenario and provides an explicit exclusion plus alternative: 'Not for current risk or hedges (use riskmodels_portfolio_exposure)'. When-to-use and when-not-to-use are both spelled out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
riskmodels_get_benchmark_fitRiskModels Benchmark Fit (active weights)ARead-onlyInspect
Use when you want to compare a fund, 13F filer or ETF portfolio with a benchmark: active share and the largest active weights. Not for the subject's own holdings (use riskmodels_get_fund, riskmodels_get_filer or riskmodels_get_etf). Returns, from GET /data/benchmark-fit, active share, active-weight RMS (a coarse tracking-error proxy), overlap, and the largest over- and underweights at a common date. Benchmarks: ff_own (free-float-cap weights of the subject's own holdings), the large and small style cells (cell_large-value, cell_large-blend, cell_large-growth, cell_small-value, cell_small-blend, cell_small-growth), or all (every available benchmark for the subject). Holdings dates follow the latest filings; weights use end-of-day prices. Price: $0.02 per call.
| Name | Required | Description | Default |
|---|---|---|---|
| top | No | Number of over- and underweights, integer 1-100, e.g. 20 (default 10) | |
| as_of | No | Upper bound on the subject's holdings date; the benchmark is taken at its latest date on or before it, format YYYY-MM-DD, e.g. 2026-03-31 | |
| subject | Yes | BW-* portfolio id (BW-FUND-…, BW-FILER-…, BW-ETF-…) or an ETF ticker, e.g. BW-FUND-S000019457 or SPY | |
| benchmark | Yes | ff_own, a large or small style cell, or all, e.g. cell_large-growth |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint/destructiveHint=false, but the description goes well beyond them: it enumerates the returned metrics, clarifies that weights use end-of-day prices and holdings follow the latest filings, explains the 'common date' alignment, and discloses the $0.02 per call price. That is substantive behavioral context an agent cannot derive from the annotations.
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?
Front-loaded with the use case and exclusion, then returns, then valid benchmark values, then price — a sensible information hierarchy. It is dense and long for a tool description, but each sentence carries concrete content, so little is wasted.
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?
There is no output schema, so the description takes on the burden of describing returns and does so (active share, RMS proxy, overlap, largest over/underweights). Combined with the enum breakdown and cost disclosure, an agent has everything needed to call this correctly.
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?
Schema coverage is 100%, so the baseline is 3; the description exceeds it by decoding the benchmark enum (ff_own as the subject's own free-float-cap weights, the large/small style cells, and 'all' meaning every available benchmark) and by explaining the common-date alignment between subject and benchmark. It does not, however, explain the interaction of top with the subject/benchmark selection beyond what the schema states.
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?
States a specific verb (compare) plus the exact resource (active share and largest active weights) for a named subject type (fund, 13F filer, ETF portfolio). It explicitly distinguishes itself from riskmodels_get_fund, riskmodels_get_filer and riskmodels_get_etf, so an agent can route without opening any schema.
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?
Opens with the triggering condition ('Use when you want to compare...with a benchmark') and supplies an explicit negative case with named alternatives ('Not for the subject's own holdings — use riskmodels_get_fund/filer/etf'). Both when-to-use and when-not-to-use are covered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
riskmodels_get_cohortsRiskModels Cohort StatisticsARead-onlyInspect
Use when you want cross-sectional residual statistics for SPY and the 11 GICS sector SPDR cohorts, on one date or as a time series. Not for one stock's peers (use riskmodels_get_peers) or one stock's rank (use riskmodels_get_rankings). Returns, from GET /cohorts (one date) or GET /cohorts/series (series=true), residual_mean, residual_sd, mean_pairwise_corr, n_names and n_effective by default, more on request. ERM3 residuals are fitted without an intercept, so residual_mean is not zero; link_fit_resid_sd is the residual standard deviation of the 252-day link regression, a fit-quality measure rather than a standard error. Subsector cohorts are not available. End-of-day data, refreshed after each US market close. Price: $0.04 for one date, $0.15 for a series.
| Name | Required | Description | Default |
|---|---|---|---|
| teo | No | Observation date for the one-date view (default latest), format YYYY-MM-DD, e.g. 2026-06-30 | |
| series | No | true returns a time series over start_date..end_date, e.g. true (default false: one date) | |
| cohorts | No | Comma-separated cohort tickers from SPY, XLE, XLB, XLI, XLY, XLP, XLV, XLF, XLK, XLC, XLU, XLRE, e.g. "SPY,XLK" (default all) | |
| end_date | No | Series end, series=true only, format YYYY-MM-DD, e.g. 2026-06-30 | |
| min_names | No | Drop cohorts or days with fewer members, integer, e.g. 20 | |
| variables | No | Comma-separated variables, e.g. "residual_sd,n_names" (default residual_mean, residual_sd, mean_pairwise_corr, n_names, n_effective) | |
| start_date | No | Series start, series=true only, format YYYY-MM-DD, e.g. 2025-01-02 |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only cover the safety profile (readOnly, non-destructive, open-world), yet the description goes well beyond: it discloses that ERM3 residuals are fitted without an intercept so residual_mean is non-zero, explains link_fit_resid_sd as a fit-quality measure rather than a standard error, states that subsector cohorts are unavailable, notes EOD refresh timing, and lists per-call pricing. This is exactly the extra context annotations cannot carry.
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?
Dense but front-loaded: routing guidance comes first, then return shape, then caveats and pricing. Every sentence carries information, though the residual-fitting and fit-quality caveats make it a long single block that could be slightly more scannable.
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?
Although there is no output schema, the description enumerates the default return fields (residual_mean, residual_sd, mean_pairwise_corr, n_names, n_effective) and signals more are available, plus the endpoints, data-freshness cadence, and cost. An agent has everything needed to call and interpret the result.
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?
Schema coverage is 100% so the baseline is 3, but the description adds real semantic value: it maps series=true to the /cohorts/series endpoint versus /cohorts for one date, notes that the returned variable set is a default 'more on request', and introduces link_fit_resid_sd as a valid variable. These details go beyond the schema's per-field docs.
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?
States a specific verb+resource (cross-sectional residual statistics for SPY and the 11 GICS sector SPDR cohorts) and immediately scopes it against the two nearest siblings by name. An agent can distinguish it from get_peers and get_rankings without opening any schema.
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?
Opens with an explicit 'Use when' condition and follows with negative routing — 'Not for one stock's peers (use riskmodels_get_peers) or one stock's rank (use riskmodels_get_rankings)'. Both the trigger and the alternatives are named, leaving nothing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
riskmodels_get_etfRiskModels ETFARead-onlyInspect
Use when you want one ETF's registry metadata and portfolio surface, and optionally its largest holdings. Not for finding an ETF ticker (use riskmodels_search) or the ETF's daily returns (use riskmodels_get_returns). Returns { snapshot, holdings }: snapshot from GET /data/etf/{ticker}; holdings, only when holdings_top is set, from GET /data/etf/{ticker}/holdings. Holdings follow the latest published holdings file; registry refreshed end-of-day. Free (no per-call charge).
| Name | Required | Description | Default |
|---|---|---|---|
| ticker | Yes | ETF ticker symbol, case-insensitive, e.g. SMH | |
| holdings_top | No | Also return the largest N holdings, integer 1-200, e.g. 25 (default: no holdings) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover only the safety profile (readOnly/openWorld/non-destructive), and the description layers on traits they cannot express: the two backing endpoints, holdings sourced from the latest published file, registry freshness at end-of-day, and cost ('Free, no per-call charge'). Conditional output behavior is disclosed rather than left to inference.
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?
Three sentences, each earning its place: scoping first, exclusions second, return shape and freshness third. The endpoint URLs are dense but add provenance value rather than padding.
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?
With no output schema, the description still declares the return envelope ({ snapshot, holdings }) and when each component appears. For a two-parameter read tool with full annotation coverage, nothing needed to invoke it correctly is missing.
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?
Schema coverage is 100%, so the baseline is 3, but the description adds meaning beyond the schema by tying holdings_top to the presence of the holdings key in the response. It does not restate the 1-200 bound or case-insensitivity, which are already in the 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?
States a specific verb and resource ('one ETF's registry metadata and portfolio surface, optionally its largest holdings') and explicitly separates itself from sibling tools riskmodels_search and riskmodels_get_returns. An agent can pick it out of a 23-tool family without opening a schema.
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?
Opens with an explicit when-to-use clause and adds two named exclusions with the correct alternatives for each case (ticker lookup -> riskmodels_search, daily returns -> riskmodels_get_returns). The conditional trigger for holdings (only when holdings_top is set) is also spelled out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
riskmodels_get_factor_returnsRiskModels Macro and Sector ETF Factor ReturnsARead-onlyInspect
Use when you need macro factor return series (inflation, term spread, short rates, credit, oil, gold, the dollar, volatility, bitcoin, VIX) or the trailing returns of SPY and the 11 GICS sector SPDR ETFs. Not for a stock's correlation with those factors (use riskmodels_get_macro_correlation) or one ETF's daily return series (use riskmodels_get_returns). kind macro returns daily total returns over a date range (GET /macro-factors); kind sector_etf returns closing price and trailing 1, 21, 63 and 252-day total returns on one date (GET /etf/factor-returns). End-of-day data, refreshed after each US market close. Price: $0.005 per call (macro) or $0.02 per call (sector_etf).
| Name | Required | Description | Default |
|---|---|---|---|
| end | No | kind macro only: last date, inclusive (default today), format YYYY-MM-DD, e.g. 2026-06-30 | |
| teo | No | kind sector_etf only: observation date (default latest), format YYYY-MM-DD, e.g. 2026-06-30 | |
| kind | Yes | macro: daily macro factor returns over a range; sector_etf: SPY and sector SPDR returns on one date, e.g. macro | |
| start | No | kind macro only: first date, inclusive (default five years before end), format YYYY-MM-DD, e.g. 2021-01-04 | |
| sleeve | No | kind sector_etf only: market (SPY), sector (11 sector SPDRs) or all, e.g. sector (default all) | |
| factors | No | kind macro only: comma-separated keys from inflation, term_spread, short_rates, credit, oil, gold, usd, volatility, bitcoin, vix_spot, e.g. "oil,gold,usd" (default all ten) | |
| tickers | No | kind sector_etf only: comma-separated subset of SPY, XLE, XLB, XLI, XLY, XLP, XLV, XLF, XLK, XLC, XLU, XLRE, e.g. "XLK,XLF" |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover the safety profile (readOnlyHint, destructiveHint, openWorldHint), and the description adds genuinely new context: end-of-day cadence refreshed after each US market close, the underlying endpoints (GET /macro-factors vs GET /etf/factor-returns), and per-call pricing ($0.005 macro / $0.02 sector_etf). That is exactly the extra operational detail structured fields do not carry.
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?
Front-loads the use-when clause and the sibling exclusions before the per-mode detail. Dense but every sentence carries routing, semantics, or cost information; only the pricing-inline parentheticals are mildly verbose.
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?
For a dual-mode read tool with no output schema, the description covers both modes' semantics, defaults, cadence, cost, and sibling disambiguation. Nothing an agent needs to call it correctly is missing.
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?
Schema description coverage is 100%, so the schema carries parameter documentation (baseline 3). The description adds meaning by explaining that `kind` selects between two fundamentally different data shapes and return semantics (daily total returns over a range vs. one-date close + trailing 1/21/63/252-day returns), which goes beyond the raw enum values.
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?
States a specific verb+resource (returns macro factor series / SPY and 11 GICS sector SPDR trailing returns) and enumerates the factor keys (inflation, term spread, oil, gold, etc.). It explicitly distinguishes itself from the two closest siblings, riskmodels_get_macro_correlation and riskmodels_get_returns.
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?
Leads with 'Use when you need...' and adds 'Not for a stock's correlation with those factors (use riskmodels_get_macro_correlation) or one ETF's daily return series (use riskmodels_get_returns).' Both the positive trigger and the exclusion/alternative are named, so routing is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
riskmodels_get_filerRiskModels 13F FilerARead-onlyInspect
Use when you want a 13F filer's profile, latest metrics and concentration, and optionally its largest holdings. Not for finding the bw_filer_id (use riskmodels_search) or comparing the book with a benchmark (use riskmodels_get_benchmark_fit). Returns { snapshot, holdings }: snapshot from GET /13f/filers/{bw_filer_id}/snapshot (registry details, latest metrics, concentration); holdings, only when holdings_top is set, from GET /13f/filers/{bw_filer_id}/holdings with the source filing's accession_number, filing_type (13F-HR, 13F-HR/A, 13F-NT) and amendment_type (ORIGINAL, RESTATEMENT, NEW_HOLDINGS or UNKNOWN; null on panels published before filing vintages were stored). Holdings follow the latest 13F filing; metrics use end-of-day prices. Price: $0.05, plus $0.02 when holdings are requested.
| Name | Required | Description | Default |
|---|---|---|---|
| bw_filer_id | Yes | bw_filer_id, e.g. BW-FILER-CIK0001067983, or a composite entity id BW-SYNTH-… | |
| holdings_top | No | Also return the largest N holdings, integer 1-200, e.g. 25 (default: no holdings) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, non-destructive, open-world, but the description goes well beyond them: it discloses the conditional behavior of holdings (only returned when holdings_top is set), the underlying endpoints and filing metadata (accession_number, filing_type, amendment_type), the null-before-vintage caveat, end-of-day pricing semantics, and explicit cost ($0.05, +$0.02 with holdings). This is rich, non-redundant behavioral context.
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?
Front-loads the trigger and exclusions, then the return shape and cost. It is dense and information-rich, with every clause carrying semantic weight, though the parenthetical enumeration of filing_type/amendment_type values makes it slightly heavier than strictly necessary.
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?
With no output schema, the description carries the full burden and delivers: it names the return object ({ snapshot, holdings }), the data each part contains, the conditional rule for holdings, the filing metadata, and pricing. Nothing an agent needs to call and interpret the result is missing.
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?
Schema coverage is 100%, so baseline is 3. The description adds real meaning: it clarifies that holdings are returned only when holdings_top is set, and explains the source filing fields surfaced alongside them. It stops short of restating the 1-200 bound, but the conditional logic it adds exceeds what the schema conveys.
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?
States a specific verb and resource: a 13F filer's profile, latest metrics, concentration, and optional largest holdings. It explicitly names what it is not for, distinguishing it from riskmodels_search and riskmodels_get_benchmark_fit, so an agent can route to it without opening sibling schemas.
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?
Opens with an explicit 'Use when you want...' trigger and follows with two concrete exclusions pointing to the correct alternatives (riskmodels_search for the id, riskmodels_get_benchmark_fit for benchmark comparison). When-to-use and when-not-to-use are both fully spelled out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
riskmodels_get_fundRiskModels Mutual FundARead-onlyInspect
Use when you want a US mutual fund's profile, return decomposition, hedge ratios and style-box ranks, and optionally its full holdings. Not for finding the bw_fund_id (use riskmodels_search) or comparing the fund with a benchmark (use riskmodels_get_benchmark_fit). Returns { snapshot, holdings }: snapshot from GET /funds/snapshot/{bw_fund_id} (registry details, latest return decomposition and diagnostics, top 25 holdings, L1/L2/L3 ETF hedge ratios, a 12-month portfolio time series and the fund's rank within its style box on each ranked metric); holdings, only when holdings_limit is set, from GET /funds/{bw_fund_id}/holdings (latest filed SEC N-PORT report, ranked by absolute market value, signed weights, long/short/net/gross totals and ticker coverage). Holdings follow the latest N-PORT filing; metrics use end-of-day prices. Price: $0.05, plus $0.02 when holdings are requested.
| Name | Required | Description | Default |
|---|---|---|---|
| bw_fund_id | Yes | Fund id, e.g. BW-FUND-S000019457 | |
| holdings_limit | No | Also return up to N holdings, integer 1-5000, e.g. 100; 5000 returns the whole book (default: no holdings) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnly/openWorld/non-destructive; the description adds substantial behavioral detail beyond them: the exact return shape { snapshot, holdings }, the backing endpoints, that holdings reflect the latest N-PORT filing while metrics use end-of-day prices, and the pricing model ($0.05, plus $0.02 with holdings). For a tool with no output schema, this is rich disclosure.
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 long but front-loaded: usage and exclusions come first, then return structure, then cost. Every clause carries information (endpoints, refresh semantics, pricing), though the parenthetical endpoint detail is dense enough that a tighter phrasing could reduce length without losing meaning.
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?
With no output schema and a 2-parameter surface, the description still fully specifies what is returned (snapshot contents, holdings contents, their sources and ranking) plus freshness and cost. An agent has everything needed to call and interpret the result.
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?
Schema coverage is 100%, so both parameters are already documented and the baseline is 3. The description goes beyond the schema by explaining the behavioral consequence of holdings_limit ('holdings, only when holdings_limit is set'), including that it triggers a separate endpoint and an extra $0.02 cost, which the schema does not convey.
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?
States a specific verb (get) and resource (a US mutual fund's profile, return decomposition, hedge ratios, style-box ranks, and optionally holdings). It explicitly distinguishes itself from siblings by naming riskmodels_search and riskmodels_get_benchmark_fit as the tools for adjacent tasks, so an agent can route correctly without opening any schema.
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?
Leads with 'Use when you want...' and then states two explicit exclusions with the alternative tools to use instead (finding the bw_fund_id, comparing with a benchmark). This is the when/when-not/alternatives pattern at full strength.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
riskmodels_get_fundamentalsRiskModels PIT Quarterly FundamentalsARead-onlyInspect
Use when you need point-in-time quarterly fundamentals or CAPM cost of capital for one stock. Not for risk or hedge numbers (use riskmodels_get_stock_snapshot). Returns, from GET /fundamentals/{ticker}: TTM profitability and capital-return ratios, leverage, ERM3 valuation betas, cost_of_debt and wacc from reported data, separately labelled cost_of_debt_imputed and wacc_imputed from a market proxy (10-year Treasury plus a high-quality corporate spread, not issuer-specific), economic profit, an equity-bridge decomposition and SEC line items (sec_facts). A quarter is included only if it was filed on or before as_of. grid=true adds an ERP x Treasury-tenor table of cost of equity, wacc, wacc_imputed and economic profit for the latest period. Realized history only, no forecasts; filings are picked up end-of-day. Price: $0.02 per call.
| Name | Required | Description | Default |
|---|---|---|---|
| erp | No | Equity risk premium as a decimal, e.g. 0.055 for 5.5% (default 0.05) | |
| grid | No | true adds sensitivity_grid (cost_of_equity, wacc, wacc_imputed, economic_profit) across erp_grid x rf_tenor_grid for the latest period, e.g. true (default false) | |
| as_of | No | Point-in-time date; only quarters filed on or before it are returned (default today), format YYYY-MM-DD, e.g. 2025-12-31 | |
| ticker | Yes | US stock ticker symbol, case-insensitive, e.g. AAPL | |
| periods | No | Quarterly rows returned, most recent last, integer 1-40, e.g. 12 (default 8) | |
| erp_grid | No | Comma-separated ERP decimals for the grid, e.g. "0.03,0.04,0.05,0.06,0.07"; used only when grid=true | |
| rf_tenor | No | Treasury constant-maturity tenor for the risk-free rate, e.g. 10y (default 10y); pair a short tenor with a bill-basis ERP | |
| tax_rate | No | Tax rate for the WACC debt shield as a decimal, e.g. 0.25 (default 0.21) | |
| rf_tenor_grid | No | Comma-separated tenors for the grid, e.g. "1y,10y,30y"; used only when grid=true |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, openWorldHint=true, and destructiveHint=false, so safety is covered. The description adds useful context: it explains that reported versus imputed cost of debt/wacc use different sources, clarifies the as_of inclusion rule, states that only realized history is returned (no forecasts), notes that filings are picked up end-of-day, and gives a per-call price. However, it does not address key operational traits such as rate limits, authentication scope, or error behavior. With annotations carrying the safety profile, a 3 is appropriate.
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 front-loaded with usage guidance and then systematically details outputs, caveats, and cost. It is dense and somewhat long, but with 9 parameters and no output schema, nearly every sentence earns its place by explaining what is returned or how the tool behaves. Minor redundancies with schema descriptions (as_of, grid) are the only waste.
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?
Without an output schema, the description carries the full burden of explaining return values, and it does so comprehensively—listing TTM ratios, leverage, betas, reported and imputed cost components, economic profit, equity-bridge decomposition, SEC line items, and grid behavior. It also covers caveats (realized only, no forecasts, end-of-day filings) and pricing, leaving the agent well equipped to call the tool correctly.
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?
Schema description coverage is 100%, so the baseline is 3. The description repeats but does not meaningfully extend the schema's parameter documentation: its statements about as_of filtering and grid behavior restate what is already in the schema. It adds no new syntax, defaults, or constraints beyond the schema for any of the 9 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 states a specific verb and resource: 'point-in-time quarterly fundamentals or CAPM cost of capital for one stock'. It explicitly distinguishes itself from the sibling tool 'riskmodels_get_stock_snapshot' for risk/hedge numbers. An agent can identify the tool's unique scope without opening the schema.
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 opening sentence specifies the exact condition for use ('when you need point-in-time quarterly fundamentals or CAPM cost of capital'), and the second sentence gives an explicit exclusion with the alternative tool to use instead. This covers when, when-not, and the alternative in a single compact routing statement.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
riskmodels_get_macro_correlationRiskModels Macro Factor CorrelationARead-onlyInspect
Use when you want to know how one stock's returns co-move with macro factors such as rates, credit, oil, the dollar or volatility. Not for the macro factor return series themselves (use riskmodels_get_factor_returns). Returns, from POST /correlation, Pearson or Spearman correlations over a trailing window, using the L3 residual return by default. End-of-day data, refreshed after each US market close. Price: $0.01 per call.
| Name | Required | Description | Default |
|---|---|---|---|
| method | No | "pearson" or "spearman", e.g. "spearman" (default "pearson") | |
| ticker | Yes | US stock ticker symbol, case-insensitive, e.g. NVDA | |
| factors | No | Macro factor keys, e.g. ["oil","usd","term_spread"] (default: the standard set) | |
| return_type | No | Return series to correlate, e.g. "gross" (default "l3_residual") | |
| window_days | No | Trailing window in trading days, integer, e.g. 126 (default 252) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only cover the safety profile (readOnly, openWorld, non-destructive). The description adds meaningful behavior beyond them: the underlying endpoint (POST /correlation), default return basis (L3 residual), data freshness (end-of-day, refreshed after US close), and cost ($0.01 per call). Cost and latency signals are especially valuable and absent from structured fields.
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?
Front-loads the 'Use when' trigger, then the exclusion, then return/methodology, then freshness and price. Four sentences with no filler; each carries distinct, useful information.
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 no output schema, the description conveys what is returned (correlations over a trailing window, method and return basis) plus cost and freshness. It stops short of describing the response shape (e.g., per-factor mapping), which is a minor gap for a no-output-schema tool.
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?
Schema description coverage is 100%, so method, ticker, factors, return_type, and window_days are already well documented. The description restates default behavior ('L3 residual return by default', 'Pearson or Spearman') which corroborates but does not extend the schema. 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?
States a specific purpose with verb-resource-scope: 'how one stock's returns co-move with macro factors such as rates, credit, oil, the dollar or volatility.' It explicitly names the sibling it is not (riskmodels_get_factor_returns), so an agent can select correctly without opening either schema.
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?
Opens with an explicit 'Use when' condition and follows with a clear exclusion ('Not for the macro factor return series themselves') plus the alternative tool to use instead. Both when-to-use and when-not are covered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
riskmodels_get_my_positionsRiskModels linked brokerage positionsARead-onlyInspect
Use when the request concerns the caller's own linked brokerage book. Not for a book typed into the conversation (use riskmodels_analyze_portfolio or riskmodels_portfolio_exposure). Returns the caller's positions from their default riskmodels.net portfolio (Alpaca Connect, Connect Trade or Plaid): ticker, quantity, market value and weight of each position, has_shorts, and the same book in three shapes: for_analysis (positive weights), for_hedge (positive dollar values) and for_exposure (signed dollars, short < 0). Returns an empty book when no brokerage is linked. Read-only; it does not place orders. Positions are as of the portal's last brokerage sync. Free (no REST charge). No inputs.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only/destructive, but the description adds substantive behavior: empty book when nothing is linked, sync timing ('as of the portal's last brokerage sync'), free/no REST charge, and that it does not place orders. These are useful traits beyond the structured fields.
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?
Front-loads the usage routing ahead of behavioral detail, which is the right ordering. The middle is dense but each clause (three book shapes, empty-book behavior) carries information not available elsewhere, so little is wasted.
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?
With no output schema, the description takes on the burden of explaining return values and does so fully: fields (ticker, quantity, market value, weight), has_shorts, and the three re-shaped book variants. An agent has everything needed to call and interpret it.
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?
Zero parameters, so the baseline is 4. The description confirms 'No inputs,' which closes any ambiguity about required arguments.
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?
States a specific verb (returns) and resource (caller's linked brokerage positions), and explicitly distinguishes itself from riskmodels_analyze_portfolio and riskmodels_portfolio_exposure for conversation-typed books. The scope 'default riskmodels.net portfolio' is unambiguous.
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?
Gives an explicit when-to-use ('request concerns the caller's own linked brokerage book') and when-not ('Not for a book typed into the conversation'), naming the two alternative tools to route to. Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
riskmodels_get_peersRiskModels Peer GroupARead-onlyInspect
Use when you want the stocks that share a stock's subsector ETF or sector ETF. Not for cohort-level residual statistics (use riskmodels_get_cohorts). Returns, from GET /peers, the peer list ordered by market cap with each peer's market cap. End-of-day data, refreshed after each US market close. Price: $0.005 per call.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum peers, integer 1-200, e.g. 20 (default 50) | |
| ticker | Yes | US stock ticker symbol, case-insensitive, e.g. NVDA | |
| group_by | No | Peer grouping, e.g. sector_etf (default subsector_etf) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover the read-only, non-destructive, open-world safety profile, and the description goes well beyond them: result ordering (market cap), inclusion of each peer's market cap, end-of-day freshness ('refreshed after each US market close'), the source endpoint, and a per-call price. Cost and data-freshness context are exactly the traits annotations cannot convey.
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?
Four tight sentences, front-loaded with the use condition and the sibling exclusion before the return and operational details. Each sentence contributes distinct information with no repetition of the schema.
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?
There is no output schema, yet the description specifies the return shape (peer list ordered by market cap with each peer's market cap), data currency, and pricing. For a simple three-parameter lookup, nothing an agent needs to select and call it correctly is missing.
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?
Schema description coverage is 100%, with limit, ticker, and group_by all documented including an enum and defaults, so the schema carries the parameter burden. The description adds only an implicit echo of the group_by choice ('subsector ETF or sector ETF') and the market-cap ordering, which is the expected baseline when the schema is complete.
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 states a specific verb and resource ('the stocks that share a stock's subsector ETF or sector ETF') and explicitly separates this tool from riskmodels_get_cohorts. An agent can distinguish it from siblings like get_fund, get_etf, or get_cohorts without opening any schema.
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?
It opens with an explicit use condition ('Use when you want...') and adds a negative routing rule ('Not for cohort-level residual statistics (use riskmodels_get_cohorts)'). The alternative and the condition that selects it are named directly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
riskmodels_get_portfolio_risk_snapshotRiskModels Portfolio Risk SnapshotARead-onlyInspect
Use when you want a long-only portfolio's risk decomposed into market, sector, subsector and residual variance, with diversification analytics and return attribution. Not for long/short books (use riskmodels_portfolio_exposure) or ETF hedge notionals (use riskmodels_analyze_portfolio). Returns, from POST /snapshot (the canonical portfolio snapshot), the L3 variance decomposition, per-position L3 hedge ratios, diversification analytics with sector and subsector ETF correlations, frozen-weight daily return attribution, cumulative return and drawdown over lookback_days, and a risk summary with dominant drivers and concentration flags. End-of-day data, refreshed after each US market close. Price: $1.25 per call.
| Name | Required | Description | Default |
|---|---|---|---|
| benchmark | No | Benchmark ticker, e.g. SPY | |
| positions | Yes | Long positions, each with one of weight, dollars or shares (shares on every position or none), e.g. [{"ticker":"AAPL","weight":0.4},{"ticker":"NVDA","weight":0.35},{"ticker":"CRWD","weight":0.25}] | |
| lookback_days | No | Trading days of history for returns, attribution and the diversification window, integer 20-2000, e.g. 504 (default 252) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only cover the read-only/non-destructive safety profile; the description adds substantial behavior beyond them: end-of-day data refreshed after each US market close, the backing endpoint (POST /snapshot), the exact decomposition levels and analytics returned, and a concrete price of $1.25 per call. The cost and data-freshness disclosures are exactly the kind of context annotations cannot supply.
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?
Five sentences, each earning its place: purpose, exclusions with alternatives, return contents, data cadence, price. Purpose and the routing constraint are front-loaded, and the dense return enumeration is necessary given there is no output schema.
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?
With no output schema, the description carries the burden of explaining what comes back and does so thoroughly (variance decomposition, hedge ratios, diversification analytics, attribution, drawdown, risk summary). Combined with cadence and pricing, an agent has everything needed to decide and call correctly.
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?
Schema description coverage is 100%, so the schema already documents benchmark, positions (with weight/dollars/shares alternatives) and lookback_days in detail. The description reinforces the long-only constraint but adds no syntax, format or default detail beyond the schema, so the baseline of 3 applies.
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?
States a specific verb and resource (portfolio risk decomposition into market/sector/subsector/residual variance) with the scope constraint 'long-only' up front. It explicitly distinguishes itself from two named siblings (riskmodels_portfolio_exposure for long/short books, riskmodels_analyze_portfolio for ETF hedge notionals).
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?
Opens with 'Use when you want...' and follows with explicit NOT-for cases that route the agent to the correct alternative tool. Both the inclusion condition and the two exclusion conditions are spelled out, leaving nothing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
riskmodels_get_rankingsRiskModels Cross-Sectional RankingsARead-onlyInspect
Use when you want one stock's percentile rank within the universe, its sector or its subsector on a risk or return metric. Not for screening the whole universe (use riskmodels_screen_rankings). Returns, from GET /rankings/{ticker}, the stock's rank and percentile for the metric and window. Metrics: subsector_residual, sector_residual, gross_return, mkt_cap, er_l1, er_l2 or er_l3. Windows: 1d, 21d, 63d, 252d. End-of-day data, refreshed after each US market close. Price: $0.005 per call.
| Name | Required | Description | Default |
|---|---|---|---|
| cohort | No | Cohort: universe, sector or subsector, e.g. sector | |
| metric | No | Metric: subsector_residual, sector_residual, gross_return, mkt_cap, er_l1, er_l2 or er_l3, e.g. subsector_residual | |
| ticker | Yes | US stock ticker symbol, case-insensitive, e.g. NVDA | |
| window | No | Window in trading days: 1d, 21d, 63d or 252d, e.g. 63d |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly/openWorld annotations, the description discloses the underlying endpoint, the returned fields (rank and percentile), data freshness (end-of-day, refreshed after each US market close), and cost ($0.005 per call). This is unusually rich operational context that annotations do not carry.
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?
Front-loaded with the use case and the sibling exclusion, then supporting detail. Four compact sentences, though the metric and window enumerations duplicate the schema and could be trimmed.
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?
No output schema exists, and the description names the returned values (rank and percentile) plus endpoint and freshness. Safety is covered by annotations, so nothing an agent needs to invoke this correctly is missing.
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?
Schema description coverage is 100%, so the schema already documents all four parameters, including valid metric and window values. The description restates the same metric and window enumerations and only loosely clarifies that the cohort determines the comparison group; extension beyond the schema is minimal, so the baseline 3 applies.
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?
States a specific verb and resource ('one stock's percentile rank within the universe, its sector or its subsector on a risk or return metric') and names the sibling it is not (riskmodels_screen_rankings). An agent can distinguish this from screening without opening the schema.
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?
Explicit when-to-use (single-stock rank/percentile) plus an explicit exclusion with a named alternative: 'Not for screening the whole universe (use riskmodels_screen_rankings)'. Routing is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
riskmodels_get_residual_returnsRiskModels Residual Returns and Recommended Hedge DepthARead-onlyInspect
Use when you need daily residual (stock-specific) returns and the recommended hedge depth (L1 market, L2 sector or L3 subsector) for 1-100 stocks. Not for the full factor split of each day's return (use riskmodels_get_return_attribution) or a mean-reversion signal on a basket (use riskmodels_get_residual_signal). Returns, per ticker, the recommended depth by date, the hedge ratios at that depth and the daily residual return series. One ticker is served by GET /lstar; 2-100 tickers by POST /batch/lstar. Without threshold the depth is the one ERM3 publishes; with threshold it is the simplest depth whose marginal explained risk exceeds the threshold. End-of-day data, refreshed after each US market close. Price: one ticker $0.02 plus $0.01 per year beyond the first; 2-100 tickers $0.015 per ticker plus $0.0075 per ticker per year beyond the first, minimum $0.03 per call.
| Name | Required | Description | Default |
|---|---|---|---|
| years | No | Calendar years of daily history, integer 1-15, e.g. 3 (default 1) | |
| tickers | Yes | 1-100 US stock ticker symbols, e.g. ["NVDA"] or ["AAPL","MSFT"] | |
| threshold | No | Marginal explained-risk threshold, a fraction, e.g. 0.01. Omit for the depth ERM3 publishes | |
| market_factor_etf | No | ETF ticker used as the market factor, e.g. QQQ (default SPY) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only/non-destructive nature, but the description adds substantial context beyond them: routing (GET /lstar for one ticker vs POST /batch/lstar for 2-100), data freshness (EOD, refreshed after each US market close), and per-call pricing tiers.
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?
Front-loaded with the use-when and exclusions, then output shape, routing, threshold semantics, freshness, and price in a tight sequence. Despite being information-dense, every sentence (including pricing) earns its place for a cost-aware agent.
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?
No output schema exists, yet the description specifies what is returned per ticker (recommended depth by date, hedge ratios at that depth, daily residual return series). Combined with routing and data-freshness details, an agent has everything needed to call it correctly.
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?
Schema coverage is 100%, so baseline is 3. The description adds real semantic value beyond the schema by explaining threshold behavior: omitted gives the depth ERM3 publishes, present gives the simplest depth whose marginal explained risk exceeds it.
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?
States a specific verb+resource (daily residual/stock-specific returns and recommended hedge depth) with clear scope (1-100 stocks). It explicitly differentiates from siblings by naming riskmodels_get_return_attribution for full factor splits and riskmodels_get_residual_signal for mean-reversion signals.
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?
Opens with an explicit 'Use when' clause and immediately provides when-NOT guidance that routes to two named alternative tools with the distinguishing condition. An agent can select correctly without opening any sibling.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
riskmodels_get_residual_signalRiskModels Residual Mean-Reversion SignalARead-onlyInspect
Use when you want the L3 residual mean-reversion signal aggregated over a basket of 1-100 stocks. Not for the residual return series themselves (use riskmodels_get_residual_returns). Returns, from POST /signals/residual-reversion/basket, the basket-aggregated signal, with optional weights and a minimum signal-quality quintile; it describes recent residual moves and is not a forecast. End-of-day data, refreshed after each US market close. Price: $0.02 per call.
| Name | Required | Description | Default |
|---|---|---|---|
| tickers | Yes | 1-100 basket ticker symbols, e.g. ["AAPL","MSFT","NVDA"] | |
| weights | No | Weights aligned to tickers, decimals, e.g. [0.5,0.3,0.2] (default equal weight) | |
| signal_quality_min_quintile | No | Drop names below this signal-quality quintile, integer 1-5, e.g. 3 |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, but the description adds substantial behavioral context: it is a basket-aggregated signal, not a forecast, based on end-of-day data refreshed after US market close, with a stated price per call. No contradiction with annotations.
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 front-loaded with the primary use case and exclusion, then adds return source, constraints, data freshness, and price. Every sentence earns its place with no redundancy 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?
There is no output schema, so the description should ideally explain return values more concretely. It does describe the conceptual return (basket-aggregated signal) and important caveats, but stops short of specifying response shape or field structure. Still, it is largely complete for an agent to invoke the tool correctly.
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?
Schema description coverage is 100%, so the schema already documents tickers, weights, and signal_quality_min_quintile in detail. The description mentions optional weights and a minimum signal-quality quintile, but adds no syntax or format meaning beyond the schema, making the baseline 3 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 gives a specific verb-resource pair: aggregating the L3 residual mean-reversion signal over a basket of 1-100 stocks. It explicitly distinguishes itself from the sibling tool riskmodels_get_residual_returns, so an agent can route correctly without opening either schema.
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?
It states when to use the tool ('Use when you want the L3 residual mean-reversion signal aggregated over a basket...') and when not to ('Not for the residual return series themselves (use riskmodels_get_residual_returns)'). This is explicit routing guidance with a named alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
riskmodels_get_return_attributionRiskModels Return Attribution (factor vs residual)ARead-onlyInspect
Use when you need each day's return of one stock split into market, sector and subsector factor returns and the residual (stock-specific) return. Not for raw total returns (use riskmodels_get_returns) or residual returns for many stocks (use riskmodels_get_residual_returns). Returns, from GET /returns-decomposition, the daily gross return and its additive components (decimal returns); include_lstar adds the residual series at each day's recommended hedge depth. End-of-day data, refreshed after each US market close. Price: $0.04 per call plus $0.01 per year of history beyond the first.
| Name | Required | Description | Default |
|---|---|---|---|
| years | No | Calendar years of daily history, integer, e.g. 2 (default 1) | |
| ticker | Yes | US stock ticker symbol, case-insensitive, e.g. AAPL | |
| threshold | No | Marginal explained-risk threshold for the hedge-depth rule, a fraction, e.g. 0.01 (default 0.01) | |
| include_lstar | No | true adds the lstar level and lstar_residual_return arrays, e.g. true (default false) | |
| market_factor_etf | No | ETF ticker used as the market factor, e.g. QQQ (default SPY) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover read-only/safe semantics, but the description adds material context: returns are gross and in decimals, include_lstar adds a residual series at each day's recommended hedge depth, data is end-of-day refreshed after US close, and pricing is $0.04/call plus $0.01 per year beyond the first. It stops short of describing pagination, response size, or error behavior for an invalid ticker.
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?
Four sentences, each doing distinct work: purpose, exclusions, return shape, freshness and cost. The purpose is front-loaded and there is no redundant restatement of the name or title.
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?
With no output schema, the description carries the return-value burden and does: daily gross return plus additive components, decimal units, and the extra arrays gated by include_lstar. Freshness and per-call cost round out what an agent needs before invoking.
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?
Schema description coverage is 100%, so all five parameters are already documented, which sets the baseline at 3. The description only elaborates on include_lstar (hedge-depth residual series), adding marginal meaning over the schema's own 'adds the lstar level and lstar_residual_return arrays'; years, ticker, threshold, and market_factor_etf get no extra interpretation.
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?
States a specific operation — one stock's daily return decomposed into market, sector, subsector factors plus a residual — and names the endpoint (GET /returns-decomposition). It distinguishes itself from the two closest siblings by name, so an agent can route without opening any schema.
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?
Explicit when-to-use plus two explicit when-not-to-use cases with the correct alternative tool for each ('Not for raw total returns (use riskmodels_get_returns) or residual returns for many stocks (use riskmodels_get_residual_returns)'). Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
riskmodels_get_returnsRiskModels Stock Total ReturnsARead-onlyInspect
Use when you need the daily dividend-adjusted total returns of one US stock or ETF over 1-15 years. Not for returns split into factor and residual parts (use riskmodels_get_return_attribution) or residual returns at the recommended hedge depth (use riskmodels_get_residual_returns). Returns, from GET /ticker-returns, the daily return series (decimal, 0.01 = 1%) with each day's L3 market, sector and subsector hedge ratios and explained-risk shares; history is point-in-time. End-of-day data, refreshed after each US market close. Price: $0.02 per call plus $0.01 per year of history beyond the first.
| Name | Required | Description | Default |
|---|---|---|---|
| years | No | Years of daily history, integer 1-15, e.g. 3 (default 1) | |
| ticker | Yes | US stock ticker symbol, case-insensitive, e.g. AAPL |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover safety (readOnly, non-destructive, openWorld), and the description adds substantial behavior beyond them: return format (decimal, 0.01 = 1%), what each day includes (L3 market/sector/subsector hedge ratios and explained-risk shares), point-in-time history, end-of-day refresh cadence after US close, and a concrete price model ($0.02/call + $0.01/year beyond first).
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?
Five sentences, front-loaded with the usage condition and followed by exclusions, then payload details, cadence, and cost. Every sentence carries information, though the pricing and refresh sentences could be tightened slightly.
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?
No output schema exists, and the description compensates fully by describing the returned series format, its per-day contents, and the point-in-time/end-of-day semantics. An agent has everything needed to call and interpret the result.
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?
Schema description coverage is 100%, so the schema already documents both 'ticker' and 'years' (including the 1-15 bound). The description restates the 1-15 year range but adds no syntax or format detail beyond the schema, so the baseline 3 applies.
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?
States a specific verb+resource+scope: 'daily dividend-adjusted total returns of one US stock or ETF over 1-15 years'. It also names the two siblings it is not (riskmodels_get_return_attribution, riskmodels_get_residual_returns), so an agent can disambiguate without opening schemas.
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?
Opens with an explicit 'Use when' condition, then gives two explicit exclusions mapping each to the correct alternative tool. This is textbook when/when-not/alternatives routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
riskmodels_get_stock_snapshotRiskModels Stock Risk SnapshotARead-onlyInspect
Use when you need one US stock's latest risk numbers: hedge ratios to SPY and to its sector and subsector ETFs, explained-risk shares by layer, volatility, closing price and market cap. Not for a layer-by-layer decomposition or the ETF hedge of a dollar position (use riskmodels_decompose), several stocks at once (use riskmodels_compare) or daily history (use riskmodels_get_returns). Returns the latest row of GET /metrics/{ticker}, including the hedge_levels block with hedge ratios, explained risk and hedge ETFs at L1, L2 and L3. End-of-day data, refreshed after each US market close. Price: $0.005 per call.
| Name | Required | Description | Default |
|---|---|---|---|
| ticker | Yes | US stock ticker symbol, case-insensitive, e.g. NVDA |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnlyHint, destructiveHint=false, openWorldHint), and the description adds material context beyond them: end-of-day freshness refreshed after each US market close, the underlying GET /metrics/{ticker} endpoint and that it returns the latest row including the hedge_levels block, and a per-call price of $0.005. Freshness and cost are exactly the operational traits annotations cannot express.
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?
Three sentences, front-loaded with the positive trigger before the negative routing, then return shape, then freshness and price. Every clause carries information an agent needs; nothing is padding.
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?
No output schema exists, so the description carries the return burden and does so — it names the endpoint, the returned row, and the hedge_levels block at L1/L2/L3. Combined with freshness and pricing, an agent has everything needed to call it correctly.
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?
Schema description coverage is 100% and the single ticker parameter is fully documented there (case-insensitive, e.g. NVDA). The description only reinforces the 'one US stock' scope, which is already implied by the schema and the tool name, so the baseline 3 applies.
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?
States a specific verb and resource ('one US stock's latest risk numbers') and enumerates the exact contents: hedge ratios to SPY/sector/subsector ETFs, explained-risk shares, volatility, price and market cap. It also names the sibling tools it is NOT for, so an agent can distinguish it without opening any schema.
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?
Opens with an explicit 'Use when you need...' trigger and then gives three concrete exclusions with the correct alternative for each: layer decomposition and dollar-position ETF hedge → riskmodels_decompose, multiple stocks → riskmodels_compare, daily history → riskmodels_get_returns. This is a complete routing rule set.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
riskmodels_portfolio_exposureRiskModels Long/Short Portfolio ExposureARead-onlyInspect
Use when a book has short positions or more than 100 names, or when you want its beta-dollars and the ETF trades that neutralise it. Not for long-only books of up to 100 names given as weights (use riskmodels_analyze_portfolio). Returns, from POST /portfolio/exposure, beta-dollars by sector, the ETF trades that neutralise the book at L1, L2 and L3, systematic and residual dollar risk at hedge_level (default lstar: each name at its own recommended depth), coverage (positions not modelled, with reasons) and warnings. Positions are netted by security and not rescaled. End-of-day data, refreshed after each US market close. Price: $0.25 per call up to 25 modelled names, $1.00 above.
| Name | Required | Description | Default |
|---|---|---|---|
| as_of | No | Past model date, 2011-12-07 or later; before 2013-01-01 lstar uses L3 (default latest), format YYYY-MM-DD, e.g. 2024-12-31 | |
| positions | Yes | Signed book of 1-1000 positions, e.g. [{"ticker":"AAPL","value":100000},{"ticker":"TSLA","value":-50000}] | |
| hedge_level | No | lstar: each name at its own recommended depth; l1/l2/l3: one depth for every name, e.g. l3 (default lstar) | |
| lookback_days | No | Trading days in the ETF covariance window, integer 60-756, e.g. 126 (default 252) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, but the description adds behavior the annotations cannot: positions are netted by security and not rescaled, data is end-of-day refreshed after each US close, the response includes coverage gaps with reasons and warnings, and pricing is given ($0.25 up to 25 names, $1.00 above). This is exactly the beyond-annotation context the dimension rewards.
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?
Usage routing is front-loaded in the first two sentences, followed by returns, semantics, freshness, and price. Each sentence carries distinct information (routing, output shape, netting behavior, data cadence, cost), so nothing is wasted.
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?
There is no output schema, but the description enumerates the return payload (beta-dollars by sector, L1/L2/L3 ETF trades, systematic and residual dollar risk, coverage, warnings) and covers freshness, cost, and netting rules. Complete for an agent to call it correctly.
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?
Schema description coverage is 100%, so all four parameters are documented in the schema itself; the description largely echoes the hedge_level default of lstar without adding new syntax. The only extra semantic, that positions are netted by security, is more behavioral than parameter-level. 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?
States a specific verb and resource ('returns beta-dollars by sector, the ETF trades that neutralise the book at L1, L2 and L3, systematic and residual dollar risk') and explicitly contrasts itself with the sibling riskmodels_analyze_portfolio. An agent can route between the two without opening either schema.
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?
Gives an explicit trigger ('when a book has short positions or more than 100 names, or when you want its beta-dollars') and an explicit exclusion with a named alternative ('Not for long-only books of up to 100 names given as weights (use riskmodels_analyze_portfolio)'). When-to, when-not, and the substitute are all present.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
riskmodels_screen_rankingsRiskModels Rankings ScreenARead-onlyInspect
Use when you want the names in the universe that rank highest or lowest on one metric, with optional percentile, decile and sector filters. Not for one stock's rank (use riskmodels_get_rankings). Returns, from POST /rankings/screen, the ranked rows that pass the filters; metrics, cohorts and windows are the same as for one stock's rank. End-of-day data, refreshed after each US market close. Price: $0.25 per call.
| Name | Required | Description | Default |
|---|---|---|---|
| as_of | No | Ranking date (default latest), format YYYY-MM-DD, e.g. 2026-06-30 | |
| limit | No | Maximum rows, integer, e.g. 25 (default 100) | |
| cohort | Yes | Cohort: universe, sector or subsector, e.g. universe | |
| decile | No | Restrict to one decile, integer 1-10, e.g. 10 | |
| metric | Yes | Metric: subsector_residual, sector_residual, gross_return, mkt_cap, er_l1, er_l2 or er_l3, e.g. er_l3 | |
| window | Yes | Window in trading days: 1d, 21d, 63d or 252d, e.g. 21d | |
| sector_filter | No | Restrict to one sector, by sector ETF ticker, e.g. XLK | |
| min_percentile | No | Minimum percentile, 0-100, e.g. 90 |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover safety (readOnlyHint, destructiveHint=false, openWorldHint), so the bar is lower. The description adds genuinely useful operational context beyond them: end-of-day data refreshed after each US market close, a $0.25 per-call price, and what gets returned (the ranked rows passing the filters). It stops short of describing pagination or auth, but adds real value over the structured fields.
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?
Front-loaded with the when-to-use clause, then the sibling exclusion, then return/freshness/cost details. Dense but every sentence carries information; there is no redundant repetition of the title or name.
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?
No output schema exists, so the description carries the return-value burden and does explain that it returns the ranked rows that pass the filters, plus freshness and pricing. For an eight-parameter screening tool this is largely complete, though row shape and pagination semantics remain implicit.
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?
Schema description coverage is 100%, so the schema already documents all eight parameters, making the baseline 3. The description only conceptually groups the filters ('percentile, decile and sector filters') and cross-references the metric/cohort/window definitions used by riskmodels_get_rankings; it adds little syntax or format detail beyond the 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?
States a specific verb+resource: the names in the universe ranked highest or lowest on one metric with optional filters. It explicitly distinguishes itself from the sibling riskmodels_get_rankings ('Not for one stock's rank'), so an agent can tell them apart without opening either schema.
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?
Opens with an explicit when-to-use ('Use when you want the names in the universe that rank highest or lowest'), names the condition selecting the alternative sibling, and identifies the endpoint (POST /rankings/screen). No exclusions are left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
riskmodels_searchRiskModels SearchARead-onlyInspect
Use when you need to resolve a name or fragment to an identifier: a stock ticker, an ETF ticker, a mutual fund's bw_fund_id or a 13F filer's bw_filer_id. Not for data about the match (use riskmodels_get_stock_snapshot, riskmodels_get_etf, riskmodels_get_fund or riskmodels_get_filer). Returns matches from GET /tickers (type stock), GET /data/etf/search (etf), GET /funds/search (fund: bw_fund_id, ticker, name, style box, asset class, total assets) or GET /13f/filers/search (filer: bw_filer_id). Registry refreshed end-of-day. Free.
| Name | Required | Description | Default |
|---|---|---|---|
| q | No | Symbol or name fragment, e.g. "nvidia", "SMH", "contrafund" or "berkshire"; required for type filer | |
| mag7 | No | type stock only: true returns the seven largest US technology names, e.g. true | |
| type | No | What to search for, e.g. filer (default stock) | |
| limit | No | Maximum matches, integer, e.g. 10 (default 25 for etf and filer, 50 for fund; max 100, fund 500; ignored for stock) | |
| primary | No | type fund only: true returns share-class primaries only, e.g. true | |
| include_etfs | No | type fund only: false drops funds flagged as ETFs, e.g. false (default true) | |
| include_inactive | No | type fund only: true also returns funds without a recent holdings report, e.g. true (default false) | |
| include_metadata | No | type stock only: true adds sector and company metadata per match, e.g. true | |
| equity_style_9box | No | type fund only: style box slug or name, e.g. "large-growth" or "Large Growth" |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, openWorldHint=true, destructiveHint=false, so the safety profile is covered. The description adds genuinely useful extra context — the underlying endpoints per type, the end-of-day registry refresh (data freshness) and that the call is free (cost) — but says nothing about result pagination or output shape despite being a search/list tool.
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?
Front-loaded with the use case and the exclusion before the endpoint detail, and every sentence carries routing, freshness, or cost information. It is dense — the endpoint URL enumeration is the most expendable part — but not padded.
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?
For a 9-parameter, zero-required, read-only search tool with full schema coverage and annotations covering safety, the description supplies the missing decision context (when/when-not, alternatives, freshness, cost). The remaining gap is how matches are returned/paged, which matters little given no output schema exists to describe.
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?
Schema description coverage is 100%, so every one of the 9 parameters is already documented in the schema, including defaults and the 'type X only' scoping. The description's per-endpoint field lists (e.g. fund returns bw_fund_id, ticker, style box) describe return content rather than parameter meaning, so the baseline of 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?
States a specific verb and resource — resolving a name/fragment to an identifier — and enumerates the identifier kinds (stock ticker, ETF ticker, bw_fund_id, bw_filer_id). It also names the sibling tools it is NOT (riskmodels_get_stock_snapshot, riskmodels_get_etf, riskmodels_get_fund, riskmodels_get_filer), so an agent can separate lookup from data retrieval without opening a schema.
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?
Includes an explicit trigger ('use when you need to resolve a name or fragment to an identifier') and an explicit exclusion with the correct alternatives for the excluded case. Nothing about when to pick this tool versus the get_* siblings is left to inference.
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.
46 tool updates
v1.0.12- Removed
get_fundamentals - Removed
get_l3_decomposition - Removed
get_metrics - Removed
get_portfolio_risk_snapshot - Removed
post_snapshot - Changed
riskmodels_analyze_portfolio6 fields changed- added
Input schema / properties / levelAdded value: +{ + "description": "Hedge depth for the ETF notionals, used only when every position is in dollars, e.g. L2 (default L3)", + "enum": [ + "L1", + "L2", + "L3" + ], + "type": "string" +} - changed
Input schema / properties / positions / descriptionPrevious value: -"Positions with weight or dollars (combined per ticker)"New value: +"Long positions, each with weight or dollars, combined per ticker, e.g. [{\"ticker\":\"AAPL\",\"dollars\":25000},{\"ticker\":\"NVDA\",\"dollars\":15000}]" - added
Input schema / properties / positions / items / properties / dollars / descriptionAdded value: +"Positive position value in US dollars, e.g. 25000" - added
Input schema / properties / positions / items / properties / ticker / descriptionAdded value: +"US stock ticker symbol, e.g. AAPL" - added
Input schema / properties / positions / items / properties / weight / descriptionAdded value: +"Positive portfolio weight, any scale, e.g. 0.4" - changed
Input schema / properties / years / descriptionPrevious value: -"Batch lookback window, default 1"New value: +"Lookback window in years, integer 1-30, e.g. 2 (default 1)"
- Removed
riskmodels_batch_lstar - Removed
riskmodels_call_endpoint - Changed
riskmodels_compare1 field changed- changed
Input schema / properties / tickers / descriptionPrevious value: -"Ticker symbols to compare"New value: +"2-100 US stock ticker symbols, e.g. [\"AAPL\",\"NVDA\"]"
- Changed
riskmodels_decompose2 fields changed- added
Input schema / properties / dollarsAdded value: +{ + "description": "Position size in US dollars, a positive number, e.g. 10000. Omit for the decomposition alone", + "exclusiveMinimum": 0, + "type": "number" +} - changed
Input schema / properties / ticker / descriptionPrevious value: -"Ticker symbol, e.g. NVDA or AAPL"New value: +"US stock ticker symbol, case-insensitive, e.g. NVDA"
- Changed
riskmodels_decompose_selection_vs_drift10 fields changed- changed
Input schema / properties / end_date / descriptionPrevious value: -"Window end YYYY-MM-DD"New value: +"Window end, format YYYY-MM-DD, e.g. 2026-06-30" - added
Input schema / properties / end_date / patternAdded value: +"^\\d{4}-\\d{2}-\\d{2}$" - changed
Input schema / properties / include_series / descriptionPrevious value: -"Include the daily selection/drift series (bulky)"New value: +"true adds the daily selection and drift series (large), e.g. true (default false)" - changed
Input schema / properties / level / descriptionPrevious value: -"Cascade level (default sector)"New value: +"Cohort level, e.g. market (default sector)" - changed
Input schema / properties / min_names / descriptionPrevious value: -"Ignore cohort means on days the cohort was thinner than this"New value: +"Ignore cohort means on days the cohort had fewer members, integer, e.g. 20" - changed
Input schema / properties / positions / descriptionPrevious value: -"The book to attribute"New value: +"The book to attribute, 1-500 positions, e.g. [{\"ticker\":\"MSFT\",\"weight\":0.1},{\"ticker\":\"INTC\",\"weight\":-0.05}]" - added
Input schema / properties / positions / items / properties / ticker / descriptionAdded value: +"US stock ticker symbol, e.g. MSFT" - changed
Input schema / properties / positions / items / properties / weight / descriptionPrevious value: -"Portfolio weight; negative for a short"New value: +"Portfolio weight as a decimal, negative for a short, e.g. -0.05" - changed
Input schema / properties / start_date / descriptionPrevious value: -"Window start YYYY-MM-DD"New value: +"Window start, format YYYY-MM-DD, e.g. 2026-01-02" - added
Input schema / properties / start_date / patternAdded value: +"^\\d{4}-\\d{2}-\\d{2}$"
- Changed
riskmodels_get_benchmark_fit5 fields changed- changed
Input schema / properties / as_of / descriptionPrevious value: -"YYYY-MM-DD upper bound on the subject teo (benchmark then at its latest teo ≤ the subject's)"New value: +"Upper bound on the subject's holdings date; the benchmark is taken at its latest date on or before it, format YYYY-MM-DD, e.g. 2026-03-31" - added
Input schema / properties / as_of / patternAdded value: +"^\\d{4}-\\d{2}-\\d{2}$" - changed
Input schema / properties / benchmark / descriptionPrevious value: -"ff_own, a large or small style cell, or all"New value: +"ff_own, a large or small style cell, or all, e.g. cell_large-growth" - changed
Input schema / properties / subject / descriptionPrevious value: -"BW-* portfolio id (BW-FUND-…, BW-FILER-…, BW-ETF-…) or an ETF ticker (→ BW-ETF-{TICKER})"New value: +"BW-* portfolio id (BW-FUND-…, BW-FILER-…, BW-ETF-…) or an ETF ticker, e.g. BW-FUND-S000019457 or SPY" - changed
Input schema / properties / top / descriptionPrevious value: -"Top-N over/underweights (default 10, max 100)"New value: +"Number of over- and underweights, integer 1-100, e.g. 20 (default 10)"
- Removed
riskmodels_get_capability - Changed
riskmodels_get_cohorts10 fields changed- changed
Input schema / properties / cohorts / descriptionPrevious value: -"Comma-separated cohort tickers (SPY, XLE, XLB, XLI, XLY, XLP, XLV, XLF, XLK, XLC, XLU, XLRE). Default: all"New value: +"Comma-separated cohort tickers from SPY, XLE, XLB, XLI, XLY, XLP, XLV, XLF, XLK, XLC, XLU, XLRE, e.g. \"SPY,XLK\" (default all)" - changed
Input schema / properties / end_date / descriptionPrevious value: -"Series window end YYYY-MM-DD (series=true only)"New value: +"Series end, series=true only, format YYYY-MM-DD, e.g. 2026-06-30" - added
Input schema / properties / end_date / patternAdded value: +"^\\d{4}-\\d{2}-\\d{2}$" - changed
Input schema / properties / min_names / descriptionPrevious value: -"Drop cohorts/days below this member count — their statistics are noise"New value: +"Drop cohorts or days with fewer members, integer, e.g. 20" - changed
Input schema / properties / series / descriptionPrevious value: -"If true, return a time series over start_date..end_date instead of a one-date cross-section"New value: +"true returns a time series over start_date..end_date, e.g. true (default false: one date)" - changed
Input schema / properties / start_date / descriptionPrevious value: -"Series window start YYYY-MM-DD (series=true only)"New value: +"Series start, series=true only, format YYYY-MM-DD, e.g. 2025-01-02" - added
Input schema / properties / start_date / patternAdded value: +"^\\d{4}-\\d{2}-\\d{2}$" - changed
Input schema / properties / teo / descriptionPrevious value: -"Observation date YYYY-MM-DD for the cross-section (default latest)"New value: +"Observation date for the one-date view (default latest), format YYYY-MM-DD, e.g. 2026-06-30" - added
Input schema / properties / teo / patternAdded value: +"^\\d{4}-\\d{2}-\\d{2}$" - changed
Input schema / properties / variables / descriptionPrevious value: -"Comma-separated variables. Default: residual_mean, residual_sd, mean_pairwise_corr, n_names, n_effective"New value: +"Comma-separated variables, e.g. \"residual_sd,n_names\" (default residual_mean, residual_sd, mean_pairwise_corr, n_names, n_effective)"
- Changed
riskmodels_get_etf2 fields changed- added
Input schema / properties / holdings_topAdded value: +{ + "description": "Also return the largest N holdings, integer 1-200, e.g. 25 (default: no holdings)", + "maximum": 200, + "minimum": 1, + "type": "integer" +} - changed
Input schema / properties / ticker / descriptionPrevious value: -"ETF ticker, e.g. SMH"New value: +"ETF ticker symbol, case-insensitive, e.g. SMH"
- Removed
riskmodels_get_etf_holdings - Added
riskmodels_get_factor_returns - Added
riskmodels_get_filer - Removed
riskmodels_get_filer_holdings - Removed
riskmodels_get_filer_snapshot - Added
riskmodels_get_fund - Changed
riskmodels_get_fundamentals10 fields changed- changed
Input schema / properties / as_of / descriptionPrevious value: -"Point-in-time date YYYY-MM-DD (default: today)"New value: +"Point-in-time date; only quarters filed on or before it are returned (default today), format YYYY-MM-DD, e.g. 2025-12-31" - added
Input schema / properties / as_of / patternAdded value: +"^\\d{4}-\\d{2}-\\d{2}$" - changed
Input schema / properties / erp / descriptionPrevious value: -"Equity risk premium request parameter for cost-of-capital (default 0.05 when omitted)"New value: +"Equity risk premium as a decimal, e.g. 0.055 for 5.5% (default 0.05)" - changed
Input schema / properties / erp_grid / descriptionPrevious value: -"Comma-separated ERP values for the grid, e.g. \"0.03,0.04,0.05,0.06,0.07\". Only used when grid=true"New value: +"Comma-separated ERP decimals for the grid, e.g. \"0.03,0.04,0.05,0.06,0.07\"; used only when grid=true" - changed
Input schema / properties / grid / descriptionPrevious value: -"If true, response also carries sensitivity_grid: cost_of_equity, strict wacc, parallel wacc_imputed, and economic_profit across erp_grid x rf_tenor_grid for the latest PIT-visible period only"New value: +"true adds sensitivity_grid (cost_of_equity, wacc, wacc_imputed, economic_profit) across erp_grid x rf_tenor_grid for the latest period, e.g. true (default false)" - changed
Input schema / properties / periods / descriptionPrevious value: -"Quarterly rows returned, most recent last (default 8, max 40)"New value: +"Quarterly rows returned, most recent last, integer 1-40, e.g. 12 (default 8)" - changed
Input schema / properties / rf_tenor / descriptionPrevious value: -"Treasury CMT tenor backing rf_rate (default 10y — pair a short tenor with a bill-basis ERP)"New value: +"Treasury constant-maturity tenor for the risk-free rate, e.g. 10y (default 10y); pair a short tenor with a bill-basis ERP" - changed
Input schema / properties / rf_tenor_grid / descriptionPrevious value: -"Comma-separated tenor subset for the grid, e.g. \"1y,10y,30y\". Only used when grid=true"New value: +"Comma-separated tenors for the grid, e.g. \"1y,10y,30y\"; used only when grid=true" - changed
Input schema / properties / tax_rate / descriptionPrevious value: -"Tax rate applied to the WACC debt shield (default 0.21)"New value: +"Tax rate for the WACC debt shield as a decimal, e.g. 0.25 (default 0.21)" - changed
Input schema / properties / ticker / descriptionPrevious value: -"Ticker symbol, e.g. AAPL"New value: +"US stock ticker symbol, case-insensitive, e.g. AAPL"
- Removed
riskmodels_get_hedge_levels - Removed
riskmodels_get_lstar - Changed
riskmodels_get_macro_correlation5 fields changed- changed
Input schema / properties / factors / descriptionPrevious value: -"Macro factor ids to test (default: standard set)"New value: +"Macro factor keys, e.g. [\"oil\",\"usd\",\"term_spread\"] (default: the standard set)" - changed
Input schema / properties / method / descriptionPrevious value: -"\"pearson\" (default) or \"spearman\""New value: +"\"pearson\" or \"spearman\", e.g. \"spearman\" (default \"pearson\")" - changed
Input schema / properties / return_type / descriptionPrevious value: -"Return series to correlate (default \"l3_residual\")"New value: +"Return series to correlate, e.g. \"gross\" (default \"l3_residual\")" - changed
Input schema / properties / ticker / descriptionPrevious value: -"Ticker symbol, e.g. NVDA"New value: +"US stock ticker symbol, case-insensitive, e.g. NVDA" - changed
Input schema / properties / window_days / descriptionPrevious value: -"Rolling window in days (default 252)"New value: +"Trailing window in trading days, integer, e.g. 126 (default 252)"
- Removed
riskmodels_get_openapi_spec - Added
riskmodels_get_peers - Added
riskmodels_get_portfolio_risk_snapshot - Changed
riskmodels_get_rankings4 fields changed- changed
Input schema / properties / cohort / descriptionPrevious value: -"universe, sector or subsector"New value: +"Cohort: universe, sector or subsector, e.g. sector" - changed
Input schema / properties / metric / descriptionPrevious value: -"subsector_residual, sector_residual, gross_return, mkt_cap, er_l1, er_l2 or er_l3"New value: +"Metric: subsector_residual, sector_residual, gross_return, mkt_cap, er_l1, er_l2 or er_l3, e.g. subsector_residual" - changed
Input schema / properties / ticker / descriptionPrevious value: -"Ticker symbol, e.g. NVDA"New value: +"US stock ticker symbol, case-insensitive, e.g. NVDA" - changed
Input schema / properties / window / descriptionPrevious value: -"1d, 21d, 63d or 252d"New value: +"Window in trading days: 1d, 21d, 63d or 252d, e.g. 63d"
- Added
riskmodels_get_residual_returns - Changed
riskmodels_get_residual_signal3 fields changed- changed
Input schema / properties / signal_quality_min_quintile / descriptionPrevious value: -"Drop names below this signal-quality quintile (1-5)"New value: +"Drop names below this signal-quality quintile, integer 1-5, e.g. 3" - changed
Input schema / properties / tickers / descriptionPrevious value: -"Basket tickers"New value: +"1-100 basket ticker symbols, e.g. [\"AAPL\",\"MSFT\",\"NVDA\"]" - changed
Input schema / properties / weights / descriptionPrevious value: -"Optional weights, aligned to tickers"New value: +"Weights aligned to tickers, decimals, e.g. [0.5,0.3,0.2] (default equal weight)"
- Changed
riskmodels_get_return_attribution5 fields changed- changed
Input schema / properties / include_lstar / descriptionPrevious value: -"Include lstar + lstar_residual_return arrays (default false)"New value: +"true adds the lstar level and lstar_residual_return arrays, e.g. true (default false)" - changed
Input schema / properties / market_factor_etf / descriptionPrevious value: -"Market factor ETF (default SPY)"New value: +"ETF ticker used as the market factor, e.g. QQQ (default SPY)" - changed
Input schema / properties / threshold / descriptionPrevious value: -"Marginal ER threshold for Lstar derivation (default 0.01)"New value: +"Marginal explained-risk threshold for the hedge-depth rule, a fraction, e.g. 0.01 (default 0.01)" - changed
Input schema / properties / ticker / descriptionPrevious value: -"Ticker symbol, e.g. NVDA or AAPL"New value: +"US stock ticker symbol, case-insensitive, e.g. AAPL" - changed
Input schema / properties / years / descriptionPrevious value: -"Calendar years of daily history (default 1)"New value: +"Calendar years of daily history, integer, e.g. 2 (default 1)"
- Changed
riskmodels_get_returns2 fields changed- changed
Input schema / properties / ticker / descriptionPrevious value: -"Ticker symbol, e.g. NVDA or AAPL"New value: +"US stock ticker symbol, case-insensitive, e.g. AAPL" - changed
Input schema / properties / years / descriptionPrevious value: -"Years of daily history (default 1, max 15)"New value: +"Years of daily history, integer 1-15, e.g. 3 (default 1)"
- Removed
riskmodels_get_schema - Added
riskmodels_get_stock_snapshot - Removed
riskmodels_hedge_portfolio - Removed
riskmodels_hedge_position - Removed
riskmodels_list_endpoints - Removed
riskmodels_portfolio_decompose - Changed
riskmodels_portfolio_exposure6 fields changed- changed
Input schema / properties / as_of / descriptionPrevious value: -"Past model date YYYY-MM-DD (2011-12-07 or later; before 2013-01-01 lstar uses L3); omit for the latest"New value: +"Past model date, 2011-12-07 or later; before 2013-01-01 lstar uses L3 (default latest), format YYYY-MM-DD, e.g. 2024-12-31" - changed
Input schema / properties / hedge_level / descriptionPrevious value: -"lstar (default): each name at its own L* level. l1/l2/l3: one level for every name"New value: +"lstar: each name at its own recommended depth; l1/l2/l3: one depth for every name, e.g. l3 (default lstar)" - changed
Input schema / properties / lookback_days / descriptionPrevious value: -"Trading days in the ETF covariance window (default 252)"New value: +"Trading days in the ETF covariance window, integer 60-756, e.g. 126 (default 252)" - changed
Input schema / properties / positions / descriptionPrevious value: -"Signed book: { ticker, value } in dollars, short < 0 (1-1000)"New value: +"Signed book of 1-1000 positions, e.g. [{\"ticker\":\"AAPL\",\"value\":100000},{\"ticker\":\"TSLA\",\"value\":-50000}]" - added
Input schema / properties / positions / items / properties / ticker / descriptionAdded value: +"US stock ticker symbol, e.g. TSLA" - changed
Input schema / properties / positions / items / properties / value / descriptionPrevious value: -"Signed dollar market value; short < 0"New value: +"Signed market value in US dollars, short < 0, e.g. -50000"
- Changed
riskmodels_screen_rankings9 fields changed- changed
Input schema / properties / as_of / descriptionPrevious value: -"As-of date (YYYY-MM-DD)"New value: +"Ranking date (default latest), format YYYY-MM-DD, e.g. 2026-06-30" - added
Input schema / properties / as_of / patternAdded value: +"^\\d{4}-\\d{2}-\\d{2}$" - changed
Input schema / properties / cohort / descriptionPrevious value: -"universe, sector or subsector"New value: +"Cohort: universe, sector or subsector, e.g. universe" - changed
Input schema / properties / decile / descriptionPrevious value: -"Restrict to a decile (1-10)"New value: +"Restrict to one decile, integer 1-10, e.g. 10" - changed
Input schema / properties / limit / descriptionPrevious value: -"Max rows (default 100)"New value: +"Maximum rows, integer, e.g. 25 (default 100)" - changed
Input schema / properties / metric / descriptionPrevious value: -"subsector_residual, sector_residual, gross_return, mkt_cap, er_l1, er_l2 or er_l3"New value: +"Metric: subsector_residual, sector_residual, gross_return, mkt_cap, er_l1, er_l2 or er_l3, e.g. er_l3" - changed
Input schema / properties / min_percentile / descriptionPrevious value: -"Minimum percentile filter"New value: +"Minimum percentile, 0-100, e.g. 90" - changed
Input schema / properties / sector_filter / descriptionPrevious value: -"Restrict to a sector"New value: +"Restrict to one sector, by sector ETF ticker, e.g. XLK" - changed
Input schema / properties / window / descriptionPrevious value: -"1d, 21d, 63d or 252d"New value: +"Window in trading days: 1d, 21d, 63d or 252d, e.g. 21d"
- Added
riskmodels_search - Removed
riskmodels_search_etfs - Removed
riskmodels_search_filers - Removed
riskmodels_search_tickers - Removed
riskmodels_whitepaper_example
39 tool updates
v1.0.11- First observed
get_fundamentals - First observed
get_l3_decomposition - First observed
get_metrics - First observed
get_portfolio_risk_snapshot - First observed
post_snapshot - First observed
riskmodels_analyze_portfolio - First observed
riskmodels_batch_lstar - First observed
riskmodels_call_endpoint - First observed
riskmodels_compare - First observed
riskmodels_decompose - First observed
riskmodels_decompose_selection_vs_drift - First observed
riskmodels_get_benchmark_fit - First observed
riskmodels_get_capability - First observed
riskmodels_get_cohorts - First observed
riskmodels_get_etf - First observed
riskmodels_get_etf_holdings - First observed
riskmodels_get_filer_holdings - First observed
riskmodels_get_filer_snapshot - First observed
riskmodels_get_fundamentals - First observed
riskmodels_get_hedge_levels - First observed
riskmodels_get_lstar - First observed
riskmodels_get_macro_correlation - First observed
riskmodels_get_my_positions - First observed
riskmodels_get_openapi_spec - First observed
riskmodels_get_rankings - First observed
riskmodels_get_residual_signal - First observed
riskmodels_get_return_attribution - First observed
riskmodels_get_returns - First observed
riskmodels_get_schema - First observed
riskmodels_hedge_portfolio - First observed
riskmodels_hedge_position - First observed
riskmodels_list_endpoints - First observed
riskmodels_portfolio_decompose - First observed
riskmodels_portfolio_exposure - First observed
riskmodels_screen_rankings - First observed
riskmodels_search_etfs - First observed
riskmodels_search_filers - First observed
riskmodels_search_tickers - First observed
riskmodels_whitepaper_example
TDQS
Scored across 24 tools
Each tool targets a distinct resource+action and nearly every description includes explicit 'not for X (use Y)' routing, e.g. the closely related get_returns vs get_return_attribution vs get_residual_returns vs get_residual_signal are clearly separated. The four portfolio tools (analyze_portfolio, get_portfolio_risk_snapshot, portfolio_exposure, decompose_selection_vs_drift) overlap most, but size/short/long-only/purpose boundaries are spelled out, so selection is tractable.
All tools share the riskmodels_ prefix and most follow a get_<noun> or verb_noun pattern (get_stock_snapshot, get_rankings, screen_rankings, analyze_portfolio). A few drop the verb or use noun phrases (decompose, compare, portfolio_exposure, decompose_selection_vs_drift), which is a minor deviation but still readable.
24 tools is on the heavy side but the server spans a genuinely broad domain: single-stock risk, returns/attribution, macro, screening, portfolios, funds, 13F filers and ETFs. Each tool maps to a distinct endpoint and earns its place, so the count is justified rather than bloated.
Coverage is comprehensive across the equity-risk lifecycle: fundamentals, metrics snapshots, per-stock and universe rankings/screens, returns and factor/residual attribution, macro factors and correlations, peers/cohorts, entity search, and full portfolio construction/hedging/attribution. The fund, filer, ETF and benchmark-fit tools round out the security-master side, leaving no obvious dead ends.
Maintenance
Related MCP Connectors
Portfolio risk analytics — VaR, Monte Carlo, optimization, options Greeks, stress testing.
Stock & options risk analytics for AI agents: pre-trade risk scan, IV, gamma walls, Monte Carlo.
Explainable model signals, drivers, news sentiment, SEC filings and macro data for US stocks.
Portfolio and strategy stress diagnostics with hedge-break detection and regime outlook. Free tier.
Related MCP Servers
- AlicenseAqualityBmaintenanceWhat it does: * Portfolio risk profiling (per-asset and portfolio-level) * Target allocation based on risk profile (conservative/moderate/aggressive) * Diversification scoring via HHI index * Sharpe proxy calculation * Concentration risk detection * Rule-based rebalance recommendations101MIT
- 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.1048 npm2MIT
- AlicenseNot gradedqualityDmaintenanceThe verifiable risk engine for autonomous agents: deterministic, self-verifying financial calculations that an agent can delegate and prove. It covers liquidation and funding, position sizing and risk of ruin, options Greeks and margin, LP divergence, treasury concentration and depeg, execution quality checks, plus intelligence on options, DeFi, prediction markets, and transaction safety analysis.6 npm2MIT
- AlicenseAqualityBmaintenanceMCP server for decomposing US equity portfolio risk into factor exposures, with tools for portfolio risk, factor exposures, stress tests, and coverage checks using Barra-style fundamental factor models.710MIT