@tickerbot/mcp-server 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -66,29 +66,43 @@ Add to `.vscode/mcp.json` in your workspace:
66
66
 
67
67
  ## Tools
68
68
 
69
- 19 tools covering tickers, signals, scans, universes, news, and webhook subscriptions.
69
+ 33 tools covering scans, signals, tickers (state, history, bars, coverage, ETF holdings), events and their kinds, news, universes and webhook subscriptions (scan, signal, ticker, events and news). Bars and History answer `data`: one symbol gives its rows, a comma list gives them keyed by symbol.
70
70
 
71
71
  | Tool | Endpoint |
72
72
  | --- | --- |
73
+ | `tickerbot_scan` | `POST /v2/scan` |
74
+ | `tickerbot_subscribe_scan` | `POST /v2/scan/subscribe` |
75
+ | `tickerbot_list_signals` | `GET /v2/signals` |
76
+ | `tickerbot_create_custom_signal` | `POST /v2/signals` |
77
+ | `tickerbot_get_signal` | `GET /v2/signals/{signal}` |
78
+ | `tickerbot_update_custom_signal` | `PATCH /v2/signals/{signal}` |
79
+ | `tickerbot_delete_custom_signal` | `DELETE /v2/signals/{signal}` |
80
+ | `tickerbot_subscribe_signal` | `POST /v2/signals/{signal}/subscribe` |
73
81
  | `tickerbot_list_tickers` | `GET /v2/tickers` |
74
82
  | `tickerbot_get_ticker` | `GET /v2/tickers/{ticker}` |
75
- | `tickerbot_get_ticker_history` | `GET /v2/tickers/{ticker}/history` |
76
- | `tickerbot_get_ticker_events` | `GET /v2/tickers/{ticker}/events` |
77
- | `tickerbot_list_signals_catalog` | `GET /v2/signals` |
78
- | `tickerbot_get_signals_match` | `GET /v2/signals/{signal}` |
79
- | `tickerbot_get_signal_history` | `GET /v2/signals/{signal}/{ticker}/history/{interval}` |
80
- | `tickerbot_list_signal_events` | `GET /v2/signals/{signal}/{ticker}/events` |
81
- | `tickerbot_scan` | `GET /v2/scan` (live or `asof`) |
83
+ | `tickerbot_get_history` | `GET /v2/tickers/{ticker}/history` |
84
+ | `tickerbot_subscribe_ticker` | `POST /v2/tickers/{ticker}/subscribe` |
85
+ | `tickerbot_get_bars` | `GET /v2/tickers/{ticker}/bars/{interval}` |
86
+ | `tickerbot_get_ticker_coverage` | `GET /v2/tickers/{ticker}/coverage` |
87
+ | `tickerbot_get_etf_holdings` | `GET /v2/tickers/{ticker}/holdings` |
88
+ | `tickerbot_list_events` | `GET /v2/events` |
89
+ | `tickerbot_list_event_kinds` | `GET /v2/events/kinds` |
90
+ | `tickerbot_subscribe_events` | `POST /v2/events/subscribe` |
91
+ | `tickerbot_search_news` | `GET /v2/news` |
92
+ | `tickerbot_subscribe_news` | `POST /v2/news/subscribe` |
82
93
  | `tickerbot_list_universes` | `GET /v2/universes` |
83
- | `tickerbot_get_universe` | `GET /v2/universes/{id}` |
84
94
  | `tickerbot_create_universe` | `POST /v2/universes` |
85
- | `tickerbot_create_custom_signal` | `POST /v2/signals` |
86
- | `tickerbot_search_news` | `GET /v2/news/scan` |
87
- | `tickerbot_subscribe_scan` | `POST /v2/scan/subscribe` |
88
- | `tickerbot_subscribe_signal` | `POST /v2/signals/{signal}/subscribe` |
89
- | `tickerbot_subscribe_ticker` | `POST /v2/tickers/{ticker}/subscribe` |
95
+ | `tickerbot_get_universe` | `GET /v2/universes/{id}` |
96
+ | `tickerbot_update_universe` | `PATCH /v2/universes/{id}` |
97
+ | `tickerbot_delete_universe` | `DELETE /v2/universes/{id}` |
90
98
  | `tickerbot_list_webhooks` | `GET /v2/webhooks` |
99
+ | `tickerbot_get_webhook` | `GET /v2/webhooks/{id}` |
100
+ | `tickerbot_update_webhook` | `PATCH /v2/webhooks/{id}` |
91
101
  | `tickerbot_delete_webhook` | `DELETE /v2/webhooks/{id}` |
102
+ | `tickerbot_list_webhook_deliveries` | `GET /v2/webhooks/{id}/deliveries` |
103
+ | `tickerbot_redeliver_webhook_delivery` | `POST /v2/webhooks/{id}/deliveries/{delivery_id}/redeliver` |
104
+ | `tickerbot_enable_webhook` | `POST /v2/webhooks/{id}/enable` |
105
+ | `tickerbot_test_webhook` | `POST /v2/webhooks/{id}/test` |
92
106
 
93
107
  Strategies are not exposed via MCP — see the [REST API docs](https://tickerbot.io/api) for those.
94
108
 
package/dist/handler.js CHANGED
@@ -115,11 +115,16 @@ function buildRequest(tool, args, baseUrl) {
115
115
  for (const [key, value] of Object.entries(args)) {
116
116
  if (value === undefined || value === null || value === '')
117
117
  continue;
118
- const where = tool.endpoint.paramLocation[key];
118
+ // Declared params first; then the older names the route still accepts
119
+ // (endpoint.accepts, TB-570), sent where the route reads them. Anything
120
+ // else is ignored. Mirrors main_service/mcp/handler.js.
121
+ const where = tool.endpoint.paramLocation[key] ?? tool.endpoint.accepts?.[key];
119
122
  if (!where)
120
123
  continue; // unknown param, ignore
121
124
  if (where === 'path') {
122
- const token = `{${key}}`;
125
+ // An older path-param name fills the slot the docs name it by
126
+ // (endpoint.pathAliases, TB-570 step 3: `id` → {universe}).
127
+ const token = `{${tool.endpoint.pathAliases?.[key] ?? key}}`;
123
128
  if (!path.includes(token)) {
124
129
  throw new ToolError(`Tool ${tool.name} declares path param "${key}" but path template "${tool.endpoint.path}" has no {${key}} placeholder.`);
125
130
  }
@@ -133,6 +138,17 @@ function buildRequest(tool, args, baseUrl) {
133
138
  bodyHasContent = true;
134
139
  }
135
140
  }
141
+ // Fixed query values the tool always sends (endpoint.fixedQuery, TB-570
142
+ // step 3: `api_version=2027-01-12` on Bars and History, so they answer
143
+ // `data` — one symbol: its rows; a comma list: keyed by symbol).
144
+ for (const [k, v] of Object.entries(tool.endpoint.fixedQuery ?? {}))
145
+ query.set(k, String(v));
146
+ // Fixed body fields (endpoint.fixedBody: a deprecated tool built from its
147
+ // successor, tickerbot_enable_webhook = PATCH `enabled: true`).
148
+ for (const [k, v] of Object.entries(tool.endpoint.fixedBody ?? {})) {
149
+ body[k] = v;
150
+ bodyHasContent = true;
151
+ }
136
152
  // Verify no path placeholders left unfilled
137
153
  const unfilled = path.match(/\{([a-zA-Z_]+)\}/);
138
154
  if (unfilled) {
package/dist/index.js CHANGED
@@ -18,8 +18,10 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
18
18
  import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
19
19
  import { tools as bakedTools } from './tools.js';
20
20
  import { runTool, ToolError } from './handler.js';
21
- const SERVER_NAME = '@tickerbot/mcp-server';
22
- const SERVER_VERSION = '0.1.0';
21
+ import { createRequire } from 'node:module';
22
+ // package.json is the one place the version lives; the hardcoded '0.1.0'
23
+ // this replaced was reported to every client through 0.2.1.
24
+ const { name: SERVER_NAME, version: SERVER_VERSION } = createRequire(import.meta.url)('../package.json');
23
25
  const DEFAULT_BASE_URL = 'https://api.tickerbot.io';
24
26
  const DISCOVERY_TIMEOUT_MS = 3000;
25
27
  async function fetchLiveCatalog(baseUrl) {
package/dist/tools.d.ts CHANGED
@@ -13,6 +13,18 @@ export interface ToolDef {
13
13
  path: string;
14
14
  /** Where each declared input param goes. */
15
15
  paramLocation: Record<string, ParamLocation>;
16
+ /** Older names the route still accepts (TB-570): not in the
17
+ * inputSchema, but sent where the route reads them if passed. */
18
+ accepts?: Record<string, ParamLocation>;
19
+ /** An older path-param name -> the slot the docs name it by (TB-570
20
+ * step 3: `id` fills {universe} / {webhook}, `delivery_id` {delivery}). */
21
+ pathAliases?: Record<string, string>;
22
+ /** Query values every call sends (TB-570 step 3: `api_version`, so
23
+ * Bars and History answer the `data` shape the descriptions name). */
24
+ fixedQuery?: Record<string, string>;
25
+ /** Body fields every call sends (a deprecated tool built from its
26
+ * successor: tickerbot_enable_webhook is PATCH `enabled: true`). */
27
+ fixedBody?: Record<string, unknown>;
16
28
  };
17
29
  }
18
30
  interface JsonSchemaProp {