@tickerbot/mcp-server 0.4.0 → 0.4.1

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
@@ -68,7 +68,7 @@ Add to `.vscode/mcp.json` in your workspace:
68
68
 
69
69
  ## Tools
70
70
 
71
- The tools are whatever the hosted server lists when the bridge starts. At the time of this release that is 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.
71
+ The tools are whatever the hosted server lists when the bridge starts. At the time of this release that is 35 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). History answers `series` keyed by symbol, one flat row per grain step, for one ticker or a comma list. `tickerbot_list_events` and `tickerbot_search_news` were renamed `tickerbot_query_events` and `tickerbot_query_news`; the old names still work, as deprecated tools, until 2027-01-12. An argument a tool does not declare is sent to the API, which answers `unknown_parameter` for it.
72
72
 
73
73
  | Tool | Endpoint |
74
74
  | --- | --- |
@@ -87,24 +87,26 @@ The tools are whatever the hosted server lists when the bridge starts. At the ti
87
87
  | `tickerbot_get_bars` | `GET /v2/tickers/{ticker}/bars/{interval}` |
88
88
  | `tickerbot_get_ticker_coverage` | `GET /v2/tickers/{ticker}/coverage` |
89
89
  | `tickerbot_get_etf_holdings` | `GET /v2/tickers/{ticker}/holdings` |
90
- | `tickerbot_list_events` | `GET /v2/events` |
90
+ | `tickerbot_query_events` | `GET /v2/events` |
91
+ | `tickerbot_list_events` | `GET /v2/events` (deprecated: use `tickerbot_query_events`; works until 2027-01-12) |
91
92
  | `tickerbot_list_event_kinds` | `GET /v2/events/kinds` |
92
93
  | `tickerbot_subscribe_events` | `POST /v2/events/subscribe` |
93
- | `tickerbot_search_news` | `GET /v2/news` |
94
+ | `tickerbot_query_news` | `GET /v2/news` |
95
+ | `tickerbot_search_news` | `GET /v2/news` (deprecated: use `tickerbot_query_news`; works until 2027-01-12) |
94
96
  | `tickerbot_subscribe_news` | `POST /v2/news/subscribe` |
95
97
  | `tickerbot_list_universes` | `GET /v2/universes` |
96
98
  | `tickerbot_create_universe` | `POST /v2/universes` |
97
- | `tickerbot_get_universe` | `GET /v2/universes/{id}` |
98
- | `tickerbot_update_universe` | `PATCH /v2/universes/{id}` |
99
- | `tickerbot_delete_universe` | `DELETE /v2/universes/{id}` |
99
+ | `tickerbot_get_universe` | `GET /v2/universes/{universe}` |
100
+ | `tickerbot_update_universe` | `PATCH /v2/universes/{universe}` |
101
+ | `tickerbot_delete_universe` | `DELETE /v2/universes/{universe}` |
100
102
  | `tickerbot_list_webhooks` | `GET /v2/webhooks` |
101
- | `tickerbot_get_webhook` | `GET /v2/webhooks/{id}` |
102
- | `tickerbot_update_webhook` | `PATCH /v2/webhooks/{id}` |
103
- | `tickerbot_delete_webhook` | `DELETE /v2/webhooks/{id}` |
104
- | `tickerbot_list_webhook_deliveries` | `GET /v2/webhooks/{id}/deliveries` |
105
- | `tickerbot_redeliver_webhook_delivery` | `POST /v2/webhooks/{id}/deliveries/{delivery_id}/redeliver` |
106
- | `tickerbot_enable_webhook` | `POST /v2/webhooks/{id}/enable` |
107
- | `tickerbot_test_webhook` | `POST /v2/webhooks/{id}/test` |
103
+ | `tickerbot_get_webhook` | `GET /v2/webhooks/{webhook}` |
104
+ | `tickerbot_update_webhook` | `PATCH /v2/webhooks/{webhook}` |
105
+ | `tickerbot_enable_webhook` | `PATCH /v2/webhooks/{webhook}` (deprecated: use `tickerbot_update_webhook` with `enabled: true`; works until 2027-01-12) |
106
+ | `tickerbot_delete_webhook` | `DELETE /v2/webhooks/{webhook}` |
107
+ | `tickerbot_list_webhook_deliveries` | `GET /v2/webhooks/{webhook}/deliveries` |
108
+ | `tickerbot_redeliver_webhook_delivery` | `POST /v2/webhooks/{webhook}/deliveries/{delivery}/redeliver` |
109
+ | `tickerbot_test_webhook` | `POST /v2/webhooks/{webhook}/test` |
108
110
 
109
111
  Strategies are not exposed via MCP — see the [REST API docs](https://tickerbot.io/api) for those.
110
112
 
package/dist/handler.js CHANGED
@@ -113,14 +113,28 @@ function buildRequest(tool, args, baseUrl) {
113
113
  const body = {};
114
114
  let bodyHasContent = false;
115
115
  for (const [key, value] of Object.entries(args)) {
116
- if (value === undefined || value === null || value === '')
117
- continue;
118
116
  // 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.
117
+ // (endpoint.accepts, TB-570), sent where the route reads them. The name
118
+ // is judged BEFORE the blank skip (TB-749): any other argument, blank
119
+ // included, is forwarded so the API answers 400 `unknown_parameter`
120
+ // instead of the call silently succeeding without it. A query param on
121
+ // GET, a body field otherwise.
121
122
  const where = tool.endpoint.paramLocation[key] ?? tool.endpoint.accepts?.[key];
122
- if (!where)
123
- continue; // unknown param, ignore
123
+ if (!where) {
124
+ if (value === undefined)
125
+ continue;
126
+ if (tool.endpoint.method === 'GET') {
127
+ query.append(key, value === null ? '' : typeof value === 'object' ? JSON.stringify(value) : String(value));
128
+ }
129
+ else {
130
+ body[key] = value;
131
+ bodyHasContent = true;
132
+ }
133
+ continue;
134
+ }
135
+ // A blank DECLARED param means "not sent".
136
+ if (value === undefined || value === null || value === '')
137
+ continue;
124
138
  if (where === 'path') {
125
139
  // An older path-param name fills the slot the docs name it by
126
140
  // (endpoint.pathAliases, TB-570 step 3: `id` → {universe}).
@@ -138,11 +152,6 @@ function buildRequest(tool, args, baseUrl) {
138
152
  bodyHasContent = true;
139
153
  }
140
154
  }
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
155
  // Fixed body fields (endpoint.fixedBody: a deprecated tool built from its
147
156
  // successor, tickerbot_enable_webhook = PATCH `enabled: true`).
148
157
  for (const [k, v] of Object.entries(tool.endpoint.fixedBody ?? {})) {
package/dist/tools.d.ts CHANGED
@@ -19,9 +19,6 @@ export interface ToolDef {
19
19
  /** An older path-param name -> the slot the docs name it by (TB-570
20
20
  * step 3: `id` fills {universe} / {webhook}, `delivery_id` {delivery}). */
21
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
22
  /** Body fields every call sends (a deprecated tool built from its
26
23
  * successor: tickerbot_enable_webhook is PATCH `enabled: true`). */
27
24
  fixedBody?: Record<string, unknown>;
@@ -32,6 +29,8 @@ interface JsonSchemaProp {
32
29
  description: string;
33
30
  enum?: readonly string[];
34
31
  default?: unknown;
32
+ /** A regex the value must match (an id form, a date). */
33
+ pattern?: string;
35
34
  items?: {
36
35
  type: string;
37
36
  };