# io.github.tickerbot/mcp-server (remote · api.tickerbot.io)

The stock market, in SQL — scan, replay, or subscribe across ~12k US tickers and top 100 cryptos.

- Trust score: 74/100 (medium)
- Change this week: +7
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-08-03

## Components

- remote · `api.tickerbot.io`: 74/100 (this document), [markdown](https://verifymcp.io/servers/tickerbot-mcp-server/api.md), [page](https://verifymcp.io/servers/tickerbot-mcp-server/api)
- npm · `@tickerbot/mcp-server`: 78/100, [markdown](https://verifymcp.io/servers/tickerbot-mcp-server/tickerbot-mcp-server.md), [page](https://verifymcp.io/servers/tickerbot-mcp-server/tickerbot-mcp-server)

## Channel facts

- Endpoint: `https://api.tickerbot.io/mcp`
- Transports: `streamable-http`
- Auth: `required`
- Version: `0.1.3`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically against the live server, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-08-03.

- **Endpoint Security**: 89/100
  - The endpoint's TLS certificate is valid, in date, and uses a strong key.
  - Authorisation is enforced on tool calls, advertised via RFC 9728 protected-resource metadata. Discovery is public, which costs nothing: no tool can be invoked without a token.
  - HTTPS is enforced; there's no plaintext access path.
  - HSTS check failed: the Strict-Transport-Security header is absent.
  - DNSSEC check failed: this domain isn't protected by DNSSEC.
  - The authorisation server offers only Dynamic Client Registration (RFC 7591), which MCP 2026-07-28 deprecated in favour of Client ID Metadata Documents.
- **Transport & Reachability**: 100/100
  - Verified streamable-http transport via a live MCP handshake.
- **Schema Quality & AI Usability**: 66/100
  - AI-judged instruction clarity (excellent).
  - Context-footprint check failed: tool/resource definitions use about 6122 tokens (~170/item across 36 items; 36 tools + 0 resources), over budget; trim descriptions and params.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 27/100
  - Stability observed for 8 of 30 days with no destabilising changes; credit accrues until the full window elapses.
- **Tool Coverage**: 100/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 100% of tool parameters carry a description.
- **Capabilities**: 20/100
  - Spec-recency check failed: implements MCP spec 2024-11-05; the latest is 2026-07-28.

## Install

### Claude

```bash
claude mcp add --transport http tickerbot-mcp-server https://api.tickerbot.io/mcp
```

### Codex

```toml
[mcp_servers.tickerbot-mcp-server]
url = "https://api.tickerbot.io/mcp"
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "tickerbot-mcp-server": {
      "type": "remote",
      "url": "https://api.tickerbot.io/mcp",
      "enabled": true
    }
  }
}
```

### OpenClaw

```bash
openclaw mcp add tickerbot-mcp-server --url https://api.tickerbot.io/mcp --transport streamable-http
```

### Hermes

```yaml
mcp_servers:
  tickerbot-mcp-server:
    url: "https://api.tickerbot.io/mcp"
```

### Other

```json
{
  "mcpServers": {
    "tickerbot-mcp-server": {
      "type": "http",
      "url": "https://api.tickerbot.io/mcp"
    }
  }
}
```

The mcpServers block is a cross-client convention. Remote transports vary, so check your client's docs.

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-08-03 (score 74, +1)

No change was recorded against any check on this day. Stability & Change Management went from 23 to 27. That category is still filling its 30-day observation window: 7 days of observed history at the previous scan, 8 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-08-01 (score 73, +5)

- [functional] We updated how we score, so this day's move reflects our rubric, not a change to the server

### 2026-07-31 (score 68, 0)

- [functional] We updated how we score, so this day's move reflects our rubric, not a change to the server

### 2026-07-29 (score 68, +1)

No change was recorded against any check on this day. Stability & Change Management went from 7 to 10. That category is still filling its 30-day observation window: 2 days of observed history at the previous scan, 3 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-07-28 (score 67, 0)

- [functional regression] Schema quality: 135 → 170

### 2026-07-27 (score 67, 0)

- [functional] We updated how we score, so this day's move reflects our rubric, not a change to the server

### 2026-07-26 (score 67)

First indexed and scored.

## MCP tools (36)

### `tickerbot_list_tickers` (~247 tokens)

List active tickers from the Tickerbot universe (~12,000 US equities + top 100 crypto). Use `tickers` for bulk lookup of named symbols (returns full rows); otherwise walks the universe alphabetically with `cursor` pagination. Supports filters: search, asset_type, exchange, sector, min_market_cap.

Input parameters:

- `asset_type` (string): Filter by asset type (e.g. "equity", "crypto").
- `cursor` (string): Opaque cursor from a prior response.
- `exchange` (string): Filter by exchange (e.g. "XNYS", "XNAS", "BATS").
- `limit` (integer): Page size. Max 1000. Default 50.
- `min_market_cap` (number): Minimum market cap in USD. Orders results by market_cap desc.
- `search` (string): Case-insensitive substring filter on ticker/name. Orders results by market_cap desc.
- `sector` (string): Exact-match sector filter (e.g. "Technology").
- `tickers` (string): Comma-separated symbols (max 50). When set, returns full rows for these symbols and pagination params are ignored.

### `tickerbot_get_ticker` (~190 tokens)

Get the full current row for one ticker — every column on the schema (price, change, indicators like rsi_14, every boolean flag like above_sma_50, fundamentals like pe_ratio). Pass `asof` (YYYY-MM-DD or ISO timestamp like 2026-07-20T15:30:00Z) for the row as it stood at that past moment — date-only gives the close of that day.

Input parameters:

- `asof` (string): Optional YYYY-MM-DD or ISO timestamp. Date-only returns the row at close of that day; a timestamp returns the row as of that moment (finest tier covering each column).
- `ticker` (string, required): Symbol. Case-insensitive. Equities: bare symbol (AAPL). Crypto: X-prefixed pair (X:BTCUSD) — bare BTC/ETH are US-listed ETFs, not spot crypto.

### `tickerbot_get_ticker_history` (~104 tokens)

Time-travel SNAPSHOT: the full wide row for one ticker as it stood at a past date (one row, not a series — for a multi-column time SERIES use tickerbot_get_ticker_history_series). Returns indicators, boolean flags, and the most-recent fundamentals known on that date. Unlimited depth on every plan.

Input parameters:

- `asof` (string, required): Target date as YYYY-MM-DD or full ISO timestamp.
- `ticker` (string, required): Symbol.

### `tickerbot_get_ticker_history_series` (~232 tokens)

Multi-column time SERIES for one ticker: pick up to 25 columns and get one flat row per interval step ({t, price, rsi_14, …}), chronological, cursor-paged backward. The transpose of tickerbot_get_signal_history (one column, one ticker → that; many columns, one ticker → this). All-time on every plan. Replaces looping asof snapshots per date.

Input parameters:

- `cursor` (string): Opaque cursor from a prior response — pages older.
- `fields` (string): Comma list of columns (max 25). Defaults to a small set intersected with the interval's schema (intraday tiers carry fewer columns than daily — e.g. market_cap is daily-only).
- `from` (string): Earliest timestamp (inclusive), YYYY-MM-DD or ISO.
- `interval` (string, required): Series granularity.
- `limit` (integer): Rows per page. Max 1000. Default 252.
- `ticker` (string, required): Ticker symbol, e.g. NVDA.
- `to` (string): Latest timestamp (inclusive).

### `tickerbot_get_ticker_events` (~140 tokens)

Get the discrete corporate-event log for one ticker — dividends, splits, and insider transactions — merged newest-first. (Analyst rating changes are NOT here; they are a separate feed.) Optional `kind` filter and `before` back-paging.

Input parameters:

- `before` (string): Return events strictly before this date (YYYY-MM-DD) — back-paging. Pass the previous response's `next_cursor`.
- `kind` (string): Filter by event kind. Omit for all three merged into one timeline.
- `limit` (integer): Page size. Max 1000. Default 100.
- `ticker` (string, required): Symbol.

### `tickerbot_get_ticker_bars` (~242 tokens)

Get OHLCV (open/high/low/close/volume) bars for one or more symbols at a given interval, oldest-first. Pass a comma-separated `ticker` list (up to 50) for a bulk response keyed by symbol. Use `asof` for a single point-in-time bar, or `before`+`limit` to back-page. `1d`/`1h` cover the full universe with full history; sub-hour intervals back-fill on demand.

Input parameters:

- `asof` (string): Return a single bar as of this date/timestamp (point-in-time).
- `before` (string): Return the N bars ending strictly before this date/timestamp (YYYY-MM-DD or epoch-ms) — back-paging.
- `cursor` (string): Continuation token from a prior response's `next_cursor` (sugar for `before`).
- `interval` (string, required): Bar interval.
- `limit` (integer): Most-recent N bars. Default 100.
- `ticker` (string, required): Symbol, or comma-separated list (up to 50) for a bulk response keyed by symbol.

### `tickerbot_get_ticker_holdings` (~107 tokens)

Get an ETF's constituent holdings and their weights, heaviest first. When the ticker is not an ETF, `is_etf` is false and `holdings` is empty. (The reverse lookup "which ETFs hold NVDA" is a scan filter on the `etf_holders` column, not this tool.)

Input parameters:

- `limit` (integer): Max holdings returned. Max 5000. Default 500.
- `ticker` (string, required): ETF symbol.

### `tickerbot_get_ticker_sectors` (~59 tokens)

Get an ETF's sector allocation (sector weights, heaviest first). When the ticker is not an ETF, `is_etf` is false and `sectors` is empty.

Input parameters:

- `ticker` (string, required): ETF symbol.

### `tickerbot_list_signals_catalog` (~146 tokens)

List the unified signal catalog: every built-in column on the schema (`kind: builtin`) plus the caller's custom signals (`kind: expression`). Built-in rows carry the audited spec metadata — description, category, update cadence, ticker coverage (`ticker_scope`), history depth (`history`/`history_since`), queryable resolutions, and asset classes. Use to discover what `q=` clauses and signal names are available before composing a scan.

Input parameters:

- `cursor` (string): Opaque cursor.
- `kind` (string): Filter by kind. Omit for both.
- `limit` (integer): Page size for custom slice. Max 200. Default 50.

### `tickerbot_get_signals_match` (~194 tokens)

Find tickers that match a single signal right now (or at a past moment with `asof`). Booleans need no condition. Numerics need a `condition` like ">70" or "<=200". Sorted by signal value desc for numerics.

Input parameters:

- `asof` (string): Optional YYYY-MM-DD or ISO timestamp. Date-only matches daily state; a timestamp matches the finest intraday state covering the query.
- `condition` (string): Required for numerics. Single bound: <op><value>, ops in (>, >=, =, !=, <, <=).
- `cursor` (string): Opaque cursor.
- `limit` (integer): Page size. Max 200. Default 50.
- `signal` (string, required): Column name on ticker (e.g. golden_cross_today, rsi_14, market_cap).
- `universe` (string): Optional universe slug.

### `tickerbot_get_signal_history` (~116 tokens)

Get the time series of one signal for one ticker at a chosen interval (1m, 1h, 1d, 1w).

Input parameters:

- `cursor` (string): Opaque cursor.
- `from` (string): Earliest bar timestamp.
- `interval` (string, required): Bar interval (`1q` = quarterly, for fundamentals).
- `limit` (integer): Page size.
- `signal` (string, required): Column name.
- `ticker` (string, required): Symbol.
- `to` (string): Latest bar timestamp.

### `tickerbot_list_signal_events` (~84 tokens)

Discrete firings of a boolean signal for one ticker, newest-first.

Input parameters:

- `cursor` (string): Opaque cursor.
- `from` (string): Earliest event timestamp.
- `limit` (integer): Page size.
- `signal` (string, required): Boolean signal column.
- `ticker` (string, required): Symbol.
- `to` (string): Latest event timestamp.

### `tickerbot_create_custom_signal` (~68 tokens)

Save a SQL WHERE expression as a named custom signal the caller can reference by name in future scans.

Input parameters:

- `description` (string): Optional human description.
- `expr` (string, required): SQL WHERE expression. Same grammar as scan `q`.
- `name` (string, required): Snake_case identifier.

### `tickerbot_update_custom_signal` (~101 tokens)

Edit one of the caller's custom signals — supply `expr`, `description`, or both. Providing `expr` recompiles it against the live column whitelist. Built-in signals are read-only; only custom signals the caller owns can be patched. Available on every plan.

Input parameters:

- `description` (string): New description.
- `expr` (string): New SQL WHERE expression. Re-validated on save.
- `name` (string, required): Custom signal slug.

### `tickerbot_delete_custom_signal` (~97 tokens)

Delete one of the caller's custom signals. Cascade-safe by default: refused with 409 if another custom signal references it (the error lists the referencing signals). Pass `force: true` to delete anyway — existing references will break on next recompile. Available on every plan.

Input parameters:

- `force` (boolean): When true, skip the reference check and delete anyway. Default false.
- `name` (string, required): Custom signal slug.

### `tickerbot_scan` (~433 tokens)

Run a SQL WHERE clause against the live ticker universe (or against a past moment with `asof` — unlimited depth on every plan). Returns matching tickers sorted by chosen column, OR — with `group_by` — aggregate rollups instead of rows (breadth stats: "count of tickers above their 200dma by sector", "median RSI by sector on 2026-03-03"). The `q` grammar is a flat WHERE: column names from the schema, AND/OR/NOT, comparison operators, numeric/string literals. No JOIN or subqueries. Example: `gap_up AND market_cap < 2000000000 AND NOT earnings_this_week`.

Input parameters:

- `asof` (string): Optional YYYY-MM-DD or ISO timestamp for a historical scan. Unlimited depth on every plan.
- `cursor` (string): Opaque cursor (row mode only).
- `dir` (string): Sort direction.
- `fields` (string): Comma-separated extra columns to include (row mode only).
- `group_by` (string): AGGREGATE MODE: 1–6 comma-separated group keys (columns or expressions, e.g. `sector`). Results become rollup rows instead of tickers.
- `having` (string): Aggregate filter (requires group_by). Example: `COUNT(*) >= 10`.
- `limit` (integer): Page size. Max 100. Default 50. Aggregate mode does not paginate — response sets `truncated: true` when groups were cut.
- `order` (string): Sort column. Default day_change_pct (rows) / tickers (aggregate).
- `q` (string, required): SQL WHERE expression. Max 4000 chars.
- `select` (string): Aggregate output items (requires group_by). Default: group keys + COUNT(*) AS tickers. Aggregates: count/avg/sum/min/max/stddev/string_agg + FILTER (WHERE …). Alias items with AS. Example: `sector, C…
- `universe` (string): Optional universe slug.

### `tickerbot_explain_scan` (~195 tokens)

Dry-run a scan query WITHOUT executing it: validates the SQL, shows the compiled predicate after custom-signal expansion, resolves universe scope and (for asof) the serving tier, and returns the planner cost/row estimate. Always returns 200 — failures come back as { valid: false, stage, error, message }. Use before subscribing a query or to debug invalid_query errors.

Input parameters:

- `asof` (string): Optional — explain the point-in-time form; reports the serving tier.
- `fields` (string): Extra columns to validate.
- `group_by` (string): Optional — explain aggregate mode.
- `having` (string): Aggregate filter (with group_by).
- `order` (string): Sort column to validate.
- `q` (string, required): The scan predicate to explain.
- `select` (string): Aggregate output items (with group_by).
- `universe` (string): Optional universe slug to resolve.

### `tickerbot_list_universes` (~137 tokens)

List universes — your saved ones and/or the built-in system universes (top_10, top_100). Filter with `owner` (like the signals catalog's `kind`): `me` (default, your own), `system` (built-ins), or `all` (both). Each row carries `system: true|false`.

Input parameters:

- `cursor` (string): Opaque cursor.
- `limit` (integer): Page size (applies to your own; system universes are a small fixed set returned in full on the first page).
- `owner` (string): Which universes to list.

### `tickerbot_list_system_universes` (~81 tokens)

List the built-in system universes (`top_10`, `top_100` — the most-actively-traded tickers by 30-day trailing dollar volume, rebalanced monthly). Available to every account regardless of plan. Use these slugs as `universe` in scans/signals or `universe_id` when subscribing.

### `tickerbot_get_universe` (~31 tokens)

Get one universe by slug, including its ticker list.

Input parameters:

- `id` (string, required): Universe slug.

### `tickerbot_create_universe` (~92 tokens)

Create a new universe (named set of tickers) for scoping future scans.

Input parameters:

- `description` (string): Optional free-form notes.
- `id` (string): Optional slug (lowercase letters, digits, underscore). Auto-generated from name if omitted. Must be unique within the account.
- `name` (string, required): Human-readable name.
- `tickers` (array, required): List of ticker symbols.

### `tickerbot_update_universe` (~140 tokens)

Update one of the caller's universes. Pass `name`/`description` to relabel, `tickers` to replace the whole list, or `add`/`remove` to adjust subsets without replacing. System universes (`top_10`/`top_100`) cannot be edited.

Input parameters:

- `add` (array): Add these tickers (deduplicated).
- `description` (string): New notes.
- `id` (string, required): Universe slug.
- `name` (string): New label.
- `remove` (array): Remove these tickers.
- `tickers` (array): Replace the full ticker list.

### `tickerbot_delete_universe` (~67 tokens)

Delete one of the caller's universes. System universes (`top_10`/`top_100`) cannot be deleted. Webhooks that reference the deleted universe will fail on their next eval, so clean those up first.

Input parameters:

- `id` (string, required): Universe slug.

### `tickerbot_list_events` (~570 tokens)

One timeline over every event log, cross-ticker: dividends, splits, insider transactions, and analyst actions ("all splits this month", "every analyst action in my universe this week"). Rows are { ticker, ts, kind, payload }, newest first; payloads match the per-ticker events and analyst-events tools. Speaks the SQL grammar over exactly (ticker, ts, kind, payload jsonb): optional `q` filters (e.g. kind='analyst' AND payload->>'action'='downgrades'), and `group_by`/`select`/`having` roll the stream up (e.g. group_by=payload->>'firm' AS firm — aggregates return `truncated: true` instead of paginating). Requires at least one bound: a ticker scope (ticker/tickers/universe) or a time window (since/until) — q alone is not a bound. For single-ticker history prefer tickerbot_get_ticker_events; for simple firm/action filtering prefer tickerbot_list_analyst_events.

Input parameters:

- `cursor` (string): Opaque cursor from a prior response — carries the original filters, pass it alone (long q values must be resent alongside it).
- `dir` (string): Aggregate-mode sort direction.
- `group_by` (string): Comma list of rollup keys — switches to aggregate rows, e.g. payload->>'firm' AS firm, or kind.
- `having` (string): Post-aggregation filter (requires group_by), e.g. COUNT(*) > 5.
- `kind` (string): Comma list of kinds to include (default all): dividend, split, insider, analyst.
- `limit` (integer): Page size. Max 1000.
- `order` (string): Aggregate-mode sort column/alias. Default: events.
- `q` (string): SQL WHERE over (ticker, ts, kind, payload jsonb) — ONLY those four identifiers. Payload fields via jsonb operators: payload->>'firm' = 'Goldman Sachs', (payload->>'shares')::numeric > 1e6.
- `select` (string): Aggregate-mode output columns (requires group_by). Default: group keys + COUNT(*) AS events.
- `since` (string): Events at or after this ISO date/datetime.
- `ticker` (string): Single-ticker filter, e.g. AAPL.
- `tickers` (string): Comma-separated tickers, max 50. Mutually exclusive with `universe`.
- `universe` (string): Universe slug (top_10, top_100, or a saved one) to scope the stream. Mutually exclusive with `tickers`.
- `until` (string): Events strictly before this ISO date/datetime.

### `tickerbot_subscribe_events` (~412 tokens)

Create an event-trigger webhook: fires when NEW events land — dividends, splits, insider filings, analyst actions ("every split in my universe", "Goldman downgrades on large caps"). TWO composable filters: `q` filters the event's TICKER STATE (market_cap > 1e10); `event_q` filters the EVENT CONTENT in the /v2/events grammar (payload->>'firm' = 'Goldman Sachs'). Paid plans (webhook slots). Deliveries carry event: "events.fired" with an events array. Latency = ingest cadence: analyst ≤1h, corporate kinds daily — NOT sub-minute like state webhooks.

Input parameters:

- `channel` (string): Delivery channel.
- `device_id` (string): Registered device id (channel mobile_push).
- `discord_url` (string): Discord incoming-webhook URL (channel discord).
- `event_q` (string): Optional event-CONTENT filter over (ticker, ts, kind, payload jsonb) — only those four identifiers, e.g. payload->>'firm' = 'Goldman Sachs' AND payload->>'action' = 'downgrades'.
- `kinds` (string, required): Comma list of kinds to fire on — any of: dividend, split, insider, analyst (e.g. "split,analyst"). NOTE: no enum here on purpose — a scalar enum would reject multi-kind values.
- `name` (string): Display name.
- `q` (string): Optional row-STATE filter evaluated against the event's ticker at fire time, e.g. market_cap > 1e10.
- `target_url` (string): HTTPS delivery URL. Omit for in-app delivery.
- `tickers` (string): Scope to specific tickers (comma list, max 50). Mutually exclusive with universe; omit both for all tickers.
- `universe` (string): Scope to a universe slug (top_10, top_100, or a saved one).

### `tickerbot_list_analyst_events` (~300 tokens)

List per-event analyst rating history (upgrades, downgrades, initiations, price-target changes) from the analyst_events archive (history back to 2012). Available on every plan. Filters are AND-combined and at least one of `ticker`, `tickers`, `since`, `until`, `firm`, or `action` is required (an unfiltered full scan is rejected). Results are newest-first; page older with `cursor` (which ignores every filter except `limit`). Each row has ticker, timestamp, firm, analyst, action, rating, previous_rating, price_target, previous_price_target, price_target_action, importance.

Input parameters:

- `action` (string): Exact rating-action filter.
- `cursor` (string): Opaque cursor from a prior response. Ignores all filters except `limit`.
- `firm` (string): Case-insensitive analyst-firm match, e.g. "Morgan Stanley".
- `limit` (integer): Page size. Max 1000 on every plan.
- `since` (string): Events at or after this ISO date/datetime.
- `ticker` (string): Single-ticker filter, e.g. AAPL. Takes precedence over `tickers`.
- `tickers` (string): Comma-separated tickers, max 50, e.g. AAPL,NVDA,MSFT.
- `until` (string): Events strictly before this ISO date/datetime.

### `tickerbot_search_news` (~274 tokens)

Search the news archive (back to 2015) with a SQL WHERE clause. Available on every plan. Columns on news_article include `time_published`, `title`, `summary`, `source`, `source_domain`, `category`, `authors`, `topics`, `tickers` (array), `overall_sentiment_score`, `overall_sentiment_label`, `url`. To filter to one ticker use `'NVDA' = ANY(tickers)` or the auto-unnest alias `tk = 'NVDA'`. Example: `q=tk='NVDA' AND time_published >= NOW() - INTERVAL '1 day'`. Supports group_by + having for aggregation (e.g. count of articles per day).

Input parameters:

- `cursor` (string): Opaque cursor.
- `dir` (string): Sort direction.
- `group_by` (string): Comma-separated columns for aggregation.
- `having` (string): WHERE-style filter on aggregates. Requires group_by.
- `limit` (integer): Page size.
- `order` (string): Sort column or SELECT alias. Default time_published (non-aggregate) or volume (aggregate).
- `q` (string, required): SQL WHERE on news_article. Required.
- `select` (string): Comma-separated columns to include. Defaults to a slim set.

### `tickerbot_subscribe_ticker` (~228 tokens)

Register a webhook that fires when one ticker matches a condition. `condition` is a SQL WHERE-clause fragment scoped to that ticker (e.g. "rsi_14 > 70 AND relative_volume > 2"). Pass `target_url` for an https POST, or `channel:"discord"` + `discord_url` to post to Discord; omit for in-app.

Input parameters:

- `cadence` (string): Evaluation cadence.
- `channel` (string): Delivery channel: `webhook` (POST to target_url), `discord` (embed to discord_url), or `in_app` (dashboard only). Inferred from the URL you pass if omitted.
- `condition` (string, required): SQL WHERE fragment evaluated for this ticker.
- `discord_url` (string): Discord incoming-webhook URL (https://discord.com/api/webhooks/…). Required when channel is "discord".
- `name` (string): Human-readable label.
- `target_url` (string): Optional https URL for the `webhook` channel; omit for in-app.
- `ticker` (string, required): Symbol.

### `tickerbot_subscribe_signal` (~278 tokens)

Register a webhook that fires when a signal turns true (booleans) or its value crosses a condition (numerics). Optional `ticker` restricts to one symbol; omit to watch the whole universe. Pass `target_url` for an https POST, or `channel:"discord"` + `discord_url` to post to Discord; omit for in-app.

Input parameters:

- `cadence` (string): Evaluation cadence.
- `channel` (string): Delivery channel: `webhook` (POST to target_url), `discord` (embed to discord_url), or `in_app` (dashboard only). Inferred from the URL you pass if omitted.
- `condition` (string): Required for numerics: single bound like ">70" or "<=200". Ignored for booleans.
- `discord_url` (string): Discord incoming-webhook URL (https://discord.com/api/webhooks/…). Required when channel is "discord".
- `name` (string): Human-readable label.
- `signal` (string, required): Column name (e.g. golden_cross_today, rsi_14).
- `target_url` (string): Optional https URL for the `webhook` channel; omit for in-app.
- `ticker` (string): Optional ticker to restrict the watch to one symbol.
- `universe` (string): Optional universe slug.

### `tickerbot_subscribe_scan` (~257 tokens)

Register a webhook that fires when matches for a scan query change. Pass `target_url` for an https POST, or `channel:"discord"` + `discord_url` to post an embed to Discord; omit for in-app delivery in the dashboard. `cadence` is real-time (1m) by default; throttle to hourly or nyse_open. Use to satisfy "alert me when this happens" prompts.

Input parameters:

- `cadence` (string): Evaluation cadence.
- `channel` (string): Delivery channel: `webhook` (POST to target_url), `discord` (embed to discord_url), or `in_app` (dashboard only). Inferred from the URL you pass if omitted.
- `discord_url` (string): Discord incoming-webhook URL (https://discord.com/api/webhooks/…). Required when channel is "discord".
- `name` (string): Human-readable label. Defaults to a truncated version of the query.
- `q` (string, required): SQL WHERE expression — same grammar as scan.
- `target_url` (string): Optional https URL to POST matches to (the `webhook` channel). Omit for in-app delivery.
- `universe` (string): Optional universe slug to scope the watch.

### `tickerbot_list_webhooks` (~82 tokens)

List the caller's webhook subscriptions (rules created via the subscribe tools), newest-first. Use `status` to filter to active or disabled rules.

Input parameters:

- `cursor` (string): Opaque cursor.
- `limit` (integer): Page size. Max 100. Default 50.
- `status` (string): Filter by status. Omit for all.

### `tickerbot_get_webhook` (~63 tokens)

Fetch one webhook subscription by id (current state, match-set, schedule). Account-scoped: any key on the account can read any of the account's webhooks.

Input parameters:

- `id` (string, required): Webhook id (looks like `wh_…`).

### `tickerbot_list_webhook_deliveries` (~102 tokens)

List recent deliveries (pings and fires) for a webhook, newest-first — for diagnosing failures. Returns metadata only (status, attempt, response code, error); the POST body is not stored.

Input parameters:

- `cursor` (string): Opaque cursor.
- `id` (string, required): Webhook id.
- `limit` (integer): Page size. Max 100. Default 50.
- `status` (string): Filter by delivery status.

### `tickerbot_test_webhook` (~135 tokens)

Send a real-shape `webhook.fired` POST to the webhook's target_url synchronously, right now. The body is byte-identical to a real fire (same signing); the test marker rides in an `X-Tickerbot-Test: true` header. Returns the inline outcome (`delivered`, `http_status`, `elapsed_ms`, `error`). One-shot — a failed test never retries and never auto-disables the webhook. Fails with 400 if the webhook has no target_url (in-app deliveries have nothing to fire over the wire).

Input parameters:

- `id` (string, required): Webhook id.

### `tickerbot_enable_webhook` (~68 tokens)

Re-enable a disabled webhook — flips it back to `active` and clears its match-state so the next eval treats every currently-matching ticker as new. Use after fixing whatever caused auto-disable. No-op on an already-active webhook.

Input parameters:

- `id` (string, required): Webhook id.

### `tickerbot_delete_webhook` (~50 tokens)

Delete a webhook subscription by id. Use after listing webhooks when the user wants to remove an alert.

Input parameters:

- `id` (string, required): Webhook id (looks like `wh_…`).

## Diagnostics

Captured diagnostic sections: TLS, DNSSEC, Authorisation, Transports. The full working is on the page: https://verifymcp.io/servers/tickerbot-mcp-server/api#diagnostics

## Score history

- 2026-08-03: 74
- 2026-08-02: 73
- 2026-08-01: 73
- 2026-07-31: 68
- 2026-07-29: 68
- 2026-07-28: 67
- 2026-07-27: 67
- 2026-07-26: 67

## Links

- Remote endpoint: https://api.tickerbot.io/mcp
- Authorisation metadata: https://api.tickerbot.io/.well-known/oauth-protected-resource/mcp
- Repository: https://github.com/tickerbot/tickerbot-mcp
- Website: https://tickerbot.io/mcp-server
- Changelog RSS feed: https://verifymcp.io/servers/tickerbot-mcp-server/api/changelog.xml
- Changelog JSON feed: https://verifymcp.io/servers/tickerbot-mcp-server/api/changelog.json
- HTML version of this page: https://verifymcp.io/servers/tickerbot-mcp-server/api
