Skip to main content
An agent that answers “Is AAPL extended here?” needs two facts: where the price sits in its recent range, and what the momentum indicators say. That is two calls, not ten. This page traces that question end to end, then shows the two runtimes that carry it: hosted MCP and a REST-backed tool function.

The tool-selection policy

Start narrow. The first call is almost always /v2/snapshot: it carries price, 52-week position, performance, and quick fundamentals in one payload. Add exactly one call per dimension the question opens, and stop when the question is answered. “Is AAPL extended here?” has two dimensions: position in range (snapshot covers it) and momentum (snapshot does not). So the agent calls snapshot, reads that AAPL is near its 52-week high, then adds technicals for RSI, MACD, and trend strength. It does not call valuation, fundamentals, or history: none of them answer “extended.” For routing other question shapes to the right starting endpoint, see choose endpoints.

A worked trace

User: Is AAPL extended here? Call 1, snapshot. The agent asks for position in range first.
GET /v2/snapshot?symbol=AAPL (trimmed)
{
  "data": {
    "symbol": "AAPL",
    "as_of": "2026-06-05T14:19:06Z",
    "freshness": "intraday",
    "market_status": "open",
    "cache_age_seconds": 0,
    "quote": { "price": 314.86, "change_pct": 1.17, "previous_close": 311.23 },
    "performance": { "pct_1m": 9.62, "pct_ytd": 15.06, "pct_1y": 54.06, "vs_spy_pct_1y": 25.56 },
    "range_52w": { "high": 316.94, "low": 194.3, "position_pct": 95.3, "drawdown_from_high_pct": -1.8 },
    "asset_type": "stock"
  }
}
The full payload also returns fundamentals_quick, sector, and more, trimmed here to the fields that answer the question. AAPL sits at 95.3% of its 52-week range, 1.8% off the high, up 54% on the year. That reads extended on price. The agent needs momentum to confirm, so it makes one more call. Call 2, technicals. Same symbol, one new dimension.
GET /v2/technicals?symbol=AAPL (trimmed)
{
  "data": {
    "symbol": "AAPL",
    "as_of": "2026-06-05T14:19:11Z",
    "freshness": "intraday",
    "market_status": "open",
    "momentum": {
      "rsi_14": 66.61,
      "rsi_zone": "neutral",
      "rsi_14_weekly": 71.17,
      "rsi_14_weekly_zone": "overbought",
      "macd": { "histogram": -0.48, "above_signal": false }
    },
    "trend_strength": { "adx_14": 45.73, "trending": true },
    "volatility": { "bollinger_20": { "percent_b": 0.76 } }
  }
}
The live response also carries moving_averages and relative_strength. Daily RSI is 66.6 (neutral, not yet overbought), but weekly RSI is 71.2 (overbought) and MACD has rolled below its signal line. ADX 45.7 confirms a strong trend is in force. Two calls, enough to answer. Final answer. The agent answers first, then cites the data and the freshness it stood on:
Yes, AAPL looks extended on the longer timeframe but not at a daily-chart extreme. It trades at 314.86, 1.8% below its 52-week high and at 95.3% of its 52-week range, up 54% over the past year. Weekly RSI is overbought at 71.2 and MACD has crossed below its signal line, while daily RSI is still neutral at 66.6 and ADX 45.7 shows the uptrend intact. As of 2026-06-05 14:19 UTC, market open, intraday data. Calls used: snapshot, technicals. This is context, not advice.
That last paragraph is not optional. The single instruction that produces it (answer first, cite freshness and units, never give buy/sell advice, never invent data StockContext does not return) lives in agent instructions; paste that block into your system prompt.

Runtime A: hosted MCP

If your agent runs in Claude, Cursor, Codex, or any MCP client, connect the hosted server once and the model calls the tools directly. Setup (endpoint, auth header, smoke test) is on MCP hosted. With it connected, the trace above is two tool calls:
{ "tool": "stockcontext_snapshot", "arguments": { "symbol": "AAPL" } }
{ "tool": "stockcontext_technicals", "arguments": { "symbol": "AAPL" } }
Each tool returns the same { "data": ... } envelope you saw above, unchanged. Tool arguments use native JSON types, so list-valued arguments are arrays, not comma strings: for example stockcontext_filings_list({ "symbol": "AAPL", "forms": ["10-K", "10-Q"] }). A tool failure renders as [CODE] message (retryable: true|false); branch on that string the same way you would branch on error.retryable over REST.

Runtime B: REST-backed tool function

If you run your own agent loop, each tool is a function that calls REST and returns the parsed data. The detail to get right is auth: the key goes in the X-API-Key header, server-side, never in a prompt or client bundle.
agent_tools.py
import os
import httpx

BASE = "https://api.stockcontext.com"
KEY = os.environ["STOCKCONTEXT_API_KEY"]

async def nox_get(route: str, **params) -> dict:
    """One agent tool per route. Returns parsed `data` or raises on error."""
    async with httpx.AsyncClient(timeout=15) as client:
        res = await client.get(
            f"{BASE}/v2/{route}",
            params=params,
            headers={"X-API-Key": KEY},
        )
    body = res.json()
    if "error" in body:
        err = body["error"]
        raise RuntimeError(f"[{err['code']}] {err['message']} (retryable: {err['retryable']})")
    return body["data"]

# Expose these to the model as tools:
async def snapshot(symbol: str) -> dict:
    return await nox_get("snapshot", symbol=symbol)

async def technicals(symbol: str) -> dict:
    return await nox_get("technicals", symbol=symbol)
The error string mirrors the MCP format on purpose: whichever runtime your agent uses, the model sees [CODE] message (retryable: ...) and decides the same way. Wrap nox_get with retry only for retryable: true codes; the full policy and code are in errors and retries.

Where agents go wrong

  • Calling fundamentals for a valuation question. Start with valuation; reach for statements only when the user asks for line items.
  • Reading a low valuation multiple as “cheap.” Each multiple is ranked against the symbol’s own 3/5/10-year history only — never peers or a fair-value target — so near_5y_low is not a cheapness verdict. And a falling multiple can mean fundamentals rose, not that price fell; read change.driver before claiming the price dropped.
  • Calling history to answer “is it extended.” Snapshot’s range_52w and technicals answer it without pulling a series.
  • Summarizing SEC risk from memory. Use filing section text only.
  • Retrying PLAN_UPGRADE_REQUIRED, SYMBOL_UNKNOWN, or any freshness: "unsupported" response; none of those change on retry.
  • Dropping freshness and as_of from the answer, so the reader cannot tell whether the data is intraday or a week stale.

Agent instructions

The full operating rules (output format, anti-advice, anti-hallucination) to paste into your system prompt.