Developer API docs

MCP server for AI agents

Connect Claude Code or any MCP client to stock fundamentals: seven tools for summaries, metric histories, chart URLs, SEC statements, comparisons and screening.

Documentation updated 2026-09-02. Machine-readable: openapi.json · llms.txt

What it is

POST https://tgmcharts.com/api/v1/mcp is a Model Context Protocol server over streamable HTTP: stateless JSON-RPC 2.0, one JSON response per POST, no sessions and no server-initiated streams (GET and DELETE answer 405, as the streamable-HTTP specification allows for stateless servers). Protocol versions 2025-06-18, 2025-03-26 and 2024-11-05 are negotiated on initialize.

Methods: initialize, ping, tools/list, tools/call, and notifications (acknowledged with 202). Batches are accepted up to 20 messages. Every response is Cache-Control: no-store.

The tools are thin wrappers over the same builders the REST endpoints use — MCP and REST cannot disagree — and read stored, precomputed data only.

Connect

Discovery (initialize, tools/list, ping) needs no key. tools/call needs an API key — the free tier works, no card — sent as Authorization: Bearer tgm_live_…. Mint one at /developers/keys.

Claude Code
claude mcp add --transport http tgmcharts https://tgmcharts.com/api/v1/mcp \
  --header "Authorization: Bearer tgm_live_YOUR_KEY"
.mcp.json (project scope)
{
  "mcpServers": {
    "tgmcharts": {
      "type": "http",
      "url": "https://tgmcharts.com/api/v1/mcp",
      "headers": { "Authorization": "Bearer tgm_live_YOUR_KEY" }
    }
  }
}
Raw JSON-RPC · list the tools (no key)
curl -s https://tgmcharts.com/api/v1/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

The seven tools

Results carry the machine shape in structuredContent and the same JSON serialized in content[0].text. Honest states — symbol not covered, a metric outside the tier, compare on a line chart — come back as readable text with isError: true; argument-schema violations are JSON-RPC -32602 errors.

ToolPurposeInputs (required in bold)Notes
get_stock_summaryCompact fundamentals summary for one ticker — the same body as GET /api/v1/summary.symbol — string: Ticker symbol, e.g. AAPLNull values are honest gaps or sector-inappropriate metrics — never zeros. Unknown symbols return an isError result with the onboarding hint.
list_metricsThe metric catalogue: slug, label, description, unit, basis, and whether each metric is a JSON series and/or a chart render.noneNo inputs. Mirrors the x-tgmcharts-metrics catalogue in the OpenAPI document.
get_metric_seriesHistorical series for a series-tier metric, even-time downsampled to stay token-frugal.
symbol — string: Ticker symbol, e.g. KO
metric — enum (series-tier slugs): One of the series-tier slugs on the series page
years — integer 2–20: Trailing window (default: full stored history)
max_points — integer 10–500: Downsample cap (default 120)
points: null = intentionally withheld (sector-inappropriate, message included); [] = no stored history. Full density lives at GET /api/v1/series/{symbol}/{metric}.
get_chartThe canonical PNG chart URL for a chart-tier metric — a resource_link the agent can embed or fetch.
symbol — string: Ticker symbol, e.g. AAPL
metric — enum (chart-tier slugs): One of the chart-tier slugs on the charts page
years — integer 2–20: Trailing window
compare — string: Second ticker for grouped comparison bars (bar metrics only)
Returns a URL, never inline pixels. compare is refused on line metrics and when it equals symbol.
get_financial_statementRaw as-filed statement rows (income statement, balance sheet, or cash flow) from SEC EDGAR XBRL company facts.
symbol — string: Ticker symbol, e.g. AAPL
statement — enum: income-statement | balance-sheet | cash-flow: Which statement
period — enum: annual | quarterly: Default annual
years — integer 1–10: Trailing fiscal years of rows (default 5; quarterly serves 4×years)
include_provenance — boolean: Per-value us-gaap tag, accession and filing date (default false)
Token-frugal by default (5 years, no provenance, concept catalogue trimmed to key/label/unit). Full depth (30 years, CSV) lives at GET /api/v1/statements.
compare_stocksSide-by-side headline fundamentals for 2–4 tickers: market cap, close, P/E, P/S, margins, ROE, dividend yield, 5-year revenue and EPS CAGRs.symbols — string[] (2–4): Two to four ticker symbolsUncovered symbols are reported with covered: false, never dropped silently.
screen_stocksFilter and rank the covered universe on fundamental fields.
filters — array (≤ 5) of { field, operator, value }: operator ∈ gt, gte, lt, lte, eq, neq; field ∈ the screener field list below
sortBy — enum (screener field): Default marketCap
sortOrder — enum: asc | desc: Default desc
limit — integer 1–25: Rows to return (default 10)
includeEtfs — boolean: Include ETFs (default false)
At most 25 rows — the MCP tier's cap; the full screener is at /screener.

Screener fields

screen_stocks filters and sorts on: symbol, name, sector, marketCap, peRatio, dividendYield, consecutiveYears, netProfitMargin, grossMargin, revenueGrowth, debtToEquity, priceChange1Y, percentFrom52WeekHigh, percentFrom52WeekLow, revenueCagr5y, netIncomeCagr5y, epsCagr5y, fcfCagr5y, dividendsCagr5y.

A keyed tools/call

Each tools/call in the body is metered at 2 units against the key's tier quota; keyed responses carry X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Window.

curl · tools/call with a key
curl -s https://tgmcharts.com/api/v1/mcp \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer tgm_live_YOUR_KEY" \
  -d '{"jsonrpc": "2.0","id": 1,"method": "tools/call","params": {"name": "get_metric_series","arguments": { "symbol": "KO", "metric": "pe-ratio", "years": 10, "max_points": 60 }}}'
Request body
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "get_metric_series",
    "arguments": { "symbol": "KO", "metric": "pe-ratio", "years": 10, "max_points": 60 }
  }
}
Result shape
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [ { "type": "text", "text": "<the same JSON as structuredContent, serialized>" } ],
    "structuredContent": { …series body…, "points": [ … ≤ max_points … ], "downsampledTo": integer | null },
    "isError": false            // true + a readable text explanation for honest states (symbol not covered, non-series metric)
  }
}

401 and 429

A tools/call without a key answers HTTP 401 with a JSON-RPC error and a WWW-Authenticate: Bearer realm="tgmcharts-api", error="missing_token" header. A malformed, unknown or revoked key answers 401 with { "error": "Invalid API key", … }. An exhausted quota answers 429 with Retry-After — the same body as the REST endpoints, shown on authentication and limits.

401 — tools/call without a key
{
  "jsonrpc": "2.0",
  "id": null,
  "error": {
    "code": -32001,
    "message": "tools/call requires an API key — the free tier works (no card): mint one at https://tgmcharts.com/developers/keys and send it as Authorization: Bearer tgm_live_… . Lifecycle methods (initialize, tools/list, ping) need no key."
  }
}

Not using MCP?

Frameworks that build tools from an OpenAPI document can use /api/v1/openapi.json — every metric slug is enumerated in the path parameters, and the x-tgmcharts-metrics extension carries the full catalogue in one fetch. A worked example is in the quickstarts.

FAQ

Is there an MCP server for stock fundamentals?
Yes — POST https://tgmcharts.com/api/v1/mcp is a streamable-HTTP Model Context Protocol server with seven read-only tools: get_stock_summary, list_metrics, get_metric_series, get_chart, get_financial_statement, compare_stocks and screen_stocks, covering 800+ US-listed stocks and ETFs. Add it to Claude Code with: claude mcp add --transport http tgmcharts https://tgmcharts.com/api/v1/mcp
Does the MCP server need an API key?
Discovery (initialize, tools/list, ping) does not. tools/call does — the free tier works and needs no card. Mint a key at tgmcharts.com/developers/keys and send it as Authorization: Bearer tgm_live_…; each tool call is metered at 2 units.
Which MCP clients can connect?
Any client that speaks MCP over streamable HTTP with a stateless server — Claude Code (claude mcp add --transport http), Claude Desktop, and other clients that accept an HTTP MCP URL plus an Authorization header.