@coinrithm/mcp-trading 0.7.5 → 0.7.6

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.
@@ -50,10 +50,20 @@ export const OBJECTIVE_PRIMARIES = [
50
50
  // slice. `websearch` = external lookups (an injection surface + a cost — it can
51
51
  // inform reasoning but NEVER widen a cap, since caps live in the runner);
52
52
  // `indicators` = runner-computed RSI/MACD/etc. fed into the observation.
53
+ // `universe_scan` (2026-08-18, direct user request): each cycle the runner
54
+ // pulls the top 24h movers across CoinRithm's tracked coin universe, resolves
55
+ // the top few into FULL watch entries (price, sentiment, indicators when that
56
+ // capability is also on) and appends them to the observation marked
57
+ // `discovered: true`. Downstream is unchanged by design: a discovered entry
58
+ // passes through the exact same risk gates as a watchlist symbol (blocklist
59
+ // still wins, caps/SL rules unchanged) — the capability widens the CANDIDATE
60
+ // SET for one cycle, never any cap. Off by default; without it the universe
61
+ // is invisible and only manual watchlist pairs are analyzed.
53
62
  export const ALLOWED_CAPABILITIES = [
54
63
  "websearch",
55
64
  "indicators",
56
65
  "news",
66
+ "universe_scan",
57
67
  ];
58
68
  export const ok = () => ({ valid: true });
59
69
  export const fail = (code, reason) => ({
@@ -5,7 +5,7 @@ export declare const COINRITHM_API: {
5
5
  readonly kind: "coinrithm-agent-api";
6
6
  readonly baseUrl: "https://api.coinrithm.com";
7
7
  readonly mcpUrl: "https://mcp.coinrithm.com/mcp";
8
- readonly openapiVersion: "1.6.0";
8
+ readonly openapiVersion: "1.7.0";
9
9
  readonly mcpPackage: "@coinrithm/mcp-trading";
10
10
  readonly mcpVersion: string;
11
11
  };
@@ -20,7 +20,7 @@ export const COINRITHM_API = {
20
20
  mcpUrl: "https://mcp.coinrithm.com/mcp",
21
21
  // The API CONTRACT version (openapi.yaml info.version). Versioned independently
22
22
  // from the npm package below — hand-bump this when the OpenAPI contract changes.
23
- openapiVersion: "1.6.0",
23
+ openapiVersion: "1.7.0",
24
24
  mcpPackage: "@coinrithm/mcp-trading",
25
25
  mcpVersion: PACKAGE_VERSION,
26
26
  };
package/dist/client.d.ts CHANGED
@@ -83,6 +83,7 @@ export declare class CoinRithmClient {
83
83
  }): Promise<ApiResult>;
84
84
  getPublicPmCanonicalDetail(key: string): Promise<ApiResult>;
85
85
  getPublicPmVolumeHistory(): Promise<ApiResult>;
86
+ getPublicCryptoMovers(direction: "gainers" | "losers", limit?: number): Promise<ApiResult>;
86
87
  whoami(apiKey?: string, agentTrace?: AgentTrace): Promise<ApiResult>;
87
88
  getPortfolio(query?: {
88
89
  fiat?: string;
package/dist/client.js CHANGED
@@ -236,6 +236,16 @@ export class CoinRithmClient {
236
236
  getPublicPmVolumeHistory() {
237
237
  return this.publicRequest("/api/prediction-markets/volume-history");
238
238
  }
239
+ // ---- public crypto data (no key required) ----
240
+ // Top 24h movers across the tracked coin universe (user feature request,
241
+ // 2026-08-18: agents previously could only analyze manually-added pairs).
242
+ // Backend caps limit at 100; rows are {ucid, symbol, name, slug, change24h,
243
+ // currentPrice} ordered by 24h change.
244
+ getPublicCryptoMovers(direction, limit) {
245
+ return this.publicRequest(direction === "losers"
246
+ ? "/api/coins/top-losers"
247
+ : "/api/coins/top-gainers", { limit });
248
+ }
239
249
  // Every method takes an optional trailing `apiKey` (the per-request key for
240
250
  // the multi-user HTTP path). When omitted, the constructor key (stdio) is used.
241
251
  // ---- reads (scope: read) ----
package/dist/tools.d.ts CHANGED
@@ -14,6 +14,7 @@ export declare function compactPublicPmEvents(data: unknown): unknown;
14
14
  */
15
15
  export declare function compactPublicPmEvent(data: unknown): unknown;
16
16
  export declare function compactPublicPmWhales(data: unknown, limit: number): unknown;
17
+ export declare function compactPublicCryptoMovers(data: unknown): unknown;
17
18
  /**
18
19
  * Keep cross-venue disagreement clusters small enough for an agent context
19
20
  * window: each event is reduced to eventSummary (drops descriptions, images,
package/dist/tools.js CHANGED
@@ -492,6 +492,34 @@ export function compactPublicPmWhales(data, limit) {
492
492
  : data.trades;
493
493
  return { ...data, trades };
494
494
  }
495
+ // Crypto movers rows arrive as {ucid, symbol, name, slug, change24h,
496
+ // currentPrice} with the numerics as STRINGS (backend SQL fn passthrough).
497
+ // Coerce so a brain never string-compares "9.5" > "12"; drop the internal
498
+ // ucid. A row that fails coercion passes through untouched — honesty over
499
+ // polish, same rule as every other compactor here.
500
+ export function compactPublicCryptoMovers(data) {
501
+ if (!Array.isArray(data))
502
+ return data;
503
+ return data.map((row) => {
504
+ if (!isJsonRecord(row))
505
+ return row;
506
+ const change = Number(row.change24h);
507
+ const price = Number(row.currentPrice);
508
+ return {
509
+ // coinId IS the ucid the rest of the tool surface takes (get_candles,
510
+ // get_market_context, the futures quote/open path). Carrying it through
511
+ // is not cosmetic: without it the caller has to re-derive the coin from
512
+ // the SYMBOL via resolve_symbol, and symbols collide across listings —
513
+ // the round-trip can land on a different coin than the one that moved.
514
+ coinId: row.ucid,
515
+ symbol: row.symbol,
516
+ name: row.name,
517
+ slug: row.slug,
518
+ change24hPct: Number.isFinite(change) ? change : row.change24h,
519
+ priceUsd: Number.isFinite(price) ? price : row.currentPrice,
520
+ };
521
+ });
522
+ }
495
523
  const MATCH_PAIR_FIELDS = [
496
524
  "matchId",
497
525
  "confidence",
@@ -1757,4 +1785,32 @@ export function registerTools(server, client) {
1757
1785
  outputSchema: API_RESULT_OUTPUT_SCHEMA,
1758
1786
  annotations: readOnlyAnnotations("Global prediction-market volume trend"),
1759
1787
  }, async () => present(await client.getPublicPmVolumeHistory()));
1788
+ server.registerTool("get_crypto_movers", {
1789
+ title: "Top 24h crypto movers (universe scan)",
1790
+ description: "Free public scan of CoinRithm's tracked crypto universe for the " +
1791
+ "biggest 24h price moves — top gainers or top losers, ordered by " +
1792
+ "24h change percent. Use this to DISCOVER candidates beyond your " +
1793
+ "watchlist (abnormal rapid moves), then deep-analyze each candidate " +
1794
+ "with get_candles (OHLC + indicators) and get_market_context " +
1795
+ "(sentiment, news) before any trade decision. Rows carry coinId, " +
1796
+ "symbol, name, slug, change24hPct and priceUsd; data refreshes on the " +
1797
+ "~60s core price tick. Pass the row's coinId straight to get_candles " +
1798
+ "/ get_market_context — do NOT re-resolve it from the symbol, since " +
1799
+ "symbols collide across listings. No API key required.",
1800
+ inputSchema: {
1801
+ direction: z
1802
+ .enum(["gainers", "losers"])
1803
+ .optional()
1804
+ .describe("Scan direction (default gainers)."),
1805
+ limit: z
1806
+ .number()
1807
+ .int()
1808
+ .min(1)
1809
+ .max(100)
1810
+ .optional()
1811
+ .describe("Rows to return, 1-100 (default 20)."),
1812
+ },
1813
+ outputSchema: API_RESULT_OUTPUT_SCHEMA,
1814
+ annotations: readOnlyAnnotations("Top 24h crypto movers"),
1815
+ }, async ({ direction, limit }) => present(mapSuccessfulBody(await client.getPublicCryptoMovers(direction ?? "gainers", limit ?? 20), compactPublicCryptoMovers)));
1760
1816
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coinrithm/mcp-trading",
3
- "version": "0.7.5",
3
+ "version": "0.7.6",
4
4
  "mcpName": "io.github.CoinRithm/mcp-trading",
5
5
  "description": "CoinRithm paper-trading toolkit: an MCP server (coinrithm-mcp) AND a self-host agent runner (coinrithm-agent) for spot, futures, and prediction markets with a user-minted API key.",
6
6
  "type": "module",