@coinrithm/mcp-trading 0.7.6 → 0.7.8

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.
Files changed (42) hide show
  1. package/CHANGELOG.md +134 -0
  2. package/README.md +37 -8
  3. package/dist/agent/act.js +19 -6
  4. package/dist/agent/capitalSizing.d.ts +32 -0
  5. package/dist/agent/capitalSizing.js +257 -0
  6. package/dist/agent/client.d.ts +2 -0
  7. package/dist/agent/client.js +4 -0
  8. package/dist/agent/decision.d.ts +392 -0
  9. package/dist/agent/decision.js +177 -0
  10. package/dist/agent/decisionProbe.d.ts +17 -0
  11. package/dist/agent/decisionProbe.js +70 -0
  12. package/dist/agent/decisionReceipt.d.ts +45 -0
  13. package/dist/agent/decisionReceipt.js +595 -0
  14. package/dist/agent/decisionValidator.d.ts +19 -2
  15. package/dist/agent/decisionValidator.js +97 -3
  16. package/dist/agent/engine.d.ts +5 -1
  17. package/dist/agent/engine.js +8 -1
  18. package/dist/agent/observe.js +194 -35
  19. package/dist/agent/pmContext.d.ts +13 -0
  20. package/dist/agent/pmContext.js +136 -0
  21. package/dist/agent/prompt.d.ts +14 -2
  22. package/dist/agent/prompt.js +232 -35
  23. package/dist/agent/providerCapabilities.d.ts +23 -0
  24. package/dist/agent/providerCapabilities.js +105 -0
  25. package/dist/agent/providers.d.ts +29 -1
  26. package/dist/agent/providers.js +159 -88
  27. package/dist/agent/resolve.d.ts +1 -1
  28. package/dist/agent/resolve.js +21 -1
  29. package/dist/agent/runner.d.ts +4 -1
  30. package/dist/agent/runner.js +418 -47
  31. package/dist/agent/scorecard.js +7 -1
  32. package/dist/agent/skill.js +23 -0
  33. package/dist/agent/skillValidator.d.ts +1 -0
  34. package/dist/agent/skillValidator.js +63 -0
  35. package/dist/agent/state.js +7 -1
  36. package/dist/agent/strictLint.js +20 -0
  37. package/dist/agent/thesis.d.ts +40 -0
  38. package/dist/agent/thesis.js +319 -0
  39. package/dist/agent/types.d.ts +151 -0
  40. package/dist/http.js +21 -0
  41. package/dist/tools.js +10 -10
  42. package/package.json +1 -1
@@ -1,4 +1,5 @@
1
1
  import { IndicatorSet } from "./indicators.js";
2
+ import type { DecisionInputRecord } from "./decisionReceipt.js";
2
3
  export declare const SPEC_VERSION = "coinrithm.agent.v1";
3
4
  export type Venue = "spot" | "futures" | "pm";
4
5
  export declare const VENUES: readonly Venue[];
@@ -31,6 +32,7 @@ export interface RiskConfig {
31
32
  requireStopLoss: boolean;
32
33
  watchlist: string[];
33
34
  blocklist?: string[];
35
+ direction?: "long_only" | "short_only";
34
36
  }
35
37
  export interface LimitsConfig {
36
38
  maxTradesPerDay: number;
@@ -38,6 +40,38 @@ export interface LimitsConfig {
38
40
  maxDailyLossMusd: number;
39
41
  maxOpenMarginMusd: number;
40
42
  }
43
+ /** Opt-in paper experiment. Percent fields are percentage POINTS, not fractions. */
44
+ export interface CapitalSizingPolicy {
45
+ version: "equity_fraction_v1";
46
+ futuresRiskPct: number;
47
+ pmMaxLossPct: number;
48
+ perTicketCapitalPct: number;
49
+ totalCapitalPct: number;
50
+ cashReservePct: number;
51
+ minRewardRisk: number;
52
+ }
53
+ export type CapitalBook = {
54
+ status: "unavailable";
55
+ reason: string;
56
+ } | {
57
+ status: "ready";
58
+ walletId: number;
59
+ /** Marked spot + collateral, reduced by known negative position marks.
60
+ * Positive open-position gains are excluded; this is NOT complete MTM. */
61
+ conservativeEquityMusd: number;
62
+ cashAvailableMusd: number;
63
+ committedCapitalMusd: number;
64
+ };
65
+ export interface CapitalSizingAdjustment {
66
+ version: "equity_fraction_v1";
67
+ basis: "owned_collateral_spot_marked_negative_position_marks_only";
68
+ proposedAmountMusd?: number;
69
+ sizedAmountMusd?: number;
70
+ conservativeEquityMusd?: number;
71
+ riskBudgetMusd?: number;
72
+ /** Runner safety estimate, not a claim that the venue charges this fee. */
73
+ feeBufferBps?: number;
74
+ }
41
75
  export interface AbstentionConfig {
42
76
  onStaleData: boolean;
43
77
  onWeakSignal: boolean;
@@ -71,6 +105,7 @@ export interface AgentSpec {
71
105
  model?: ModelConfig;
72
106
  venues: Venue[];
73
107
  risk: RiskConfig;
108
+ capitalSizing?: CapitalSizingPolicy;
74
109
  limits: LimitsConfig;
75
110
  abstention: AbstentionConfig;
76
111
  sync: SyncConfig;
@@ -94,6 +129,8 @@ export declare const fail: (code: string, reason: string) => ValidationResult;
94
129
  export interface Freshness {
95
130
  status: string;
96
131
  ageSeconds?: number;
132
+ asOf?: string;
133
+ basis?: string;
97
134
  }
98
135
  export interface WatchEntry {
99
136
  symbol: string;
@@ -107,10 +144,25 @@ export interface WatchEntry {
107
144
  freshness?: Freshness;
108
145
  indicators?: IndicatorSet;
109
146
  discovered?: boolean;
147
+ slug?: string;
148
+ fundamentals?: CoinFundamentals;
149
+ }
150
+ export interface CoinFundamentals {
151
+ categories?: string[];
152
+ marketCapRank?: number;
153
+ marketCapUsd?: number;
154
+ volume24hUsd?: number;
155
+ headlines?: Array<{
156
+ title: string;
157
+ at?: string;
158
+ importance?: number;
159
+ sentiment?: string;
160
+ }>;
110
161
  }
111
162
  export interface OpenPosition {
112
163
  venue: Venue;
113
164
  id: number;
165
+ walletId?: number;
114
166
  coinId?: string;
115
167
  symbol?: string;
116
168
  side?: string;
@@ -123,6 +175,8 @@ export interface OpenPosition {
123
175
  liquidationPrice?: number;
124
176
  stopLossPrice?: number;
125
177
  takeProfitPrice?: number;
178
+ openedAt?: string;
179
+ thesis?: ThesisView;
126
180
  }
127
181
  export interface SpotOrder {
128
182
  id: number;
@@ -135,12 +189,19 @@ export interface SpotOrder {
135
189
  }
136
190
  export interface PmPosition {
137
191
  id: number;
192
+ walletId?: number;
138
193
  source?: string;
139
194
  slug?: string;
140
195
  outcomeExternalMarketId?: string;
141
196
  stakeMusd?: number;
142
197
  unrealizedPnlMusd?: number;
143
198
  status?: string;
199
+ title?: string;
200
+ side?: string;
201
+ entryProbability?: number;
202
+ currentProbability?: number;
203
+ openedAt?: string;
204
+ thesis?: ThesisView;
144
205
  }
145
206
  export interface PmResolution {
146
207
  id: number;
@@ -161,6 +222,27 @@ export interface PmMarket {
161
222
  title?: string;
162
223
  freshness?: Freshness;
163
224
  volumeUsd?: number;
225
+ endDate?: string;
226
+ liquidityUsd?: number;
227
+ quality?: PmQuality;
228
+ decisionSupport?: PmDecisionSupport;
229
+ }
230
+ export interface PmQuality {
231
+ decisionEligible?: boolean;
232
+ warningReasons: string[];
233
+ blockReasons: string[];
234
+ policyVersion?: string;
235
+ assessedAt?: string;
236
+ reasonsOmitted?: boolean;
237
+ }
238
+ export interface PmDecisionSupport {
239
+ qualityScore?: number;
240
+ qualityTier?: string;
241
+ qualityCapReason?: string | null;
242
+ spreadTier?: string;
243
+ liquidityTier?: string;
244
+ volumeTier?: string;
245
+ flags?: Partial<Record<"thinMarket" | "inactiveMarket" | "highAmbiguity" | "nearResolution" | "staleData", boolean>>;
164
246
  }
165
247
  export interface SetupSignal {
166
248
  symbol: string;
@@ -176,6 +258,7 @@ export interface NewsItem {
176
258
  sentiment?: string;
177
259
  importance?: number;
178
260
  ageHours?: number;
261
+ publishedAt?: string;
179
262
  coins?: string[];
180
263
  }
181
264
  export interface Observation {
@@ -183,6 +266,7 @@ export interface Observation {
183
266
  scopes: string[];
184
267
  cashAvailableMusd: number | null;
185
268
  equityMusd: number | null;
269
+ capitalBook?: CapitalBook;
186
270
  openPositions: OpenPosition[];
187
271
  openOrders: SpotOrder[];
188
272
  pmPositions: PmPosition[];
@@ -205,6 +289,35 @@ export interface Observation {
205
289
  priceUsd?: number;
206
290
  }>;
207
291
  }
292
+ export interface ThesisInvalidation {
293
+ priceBelow?: number;
294
+ priceAbove?: number;
295
+ probabilityBelow?: number;
296
+ probabilityAbove?: number;
297
+ maxHoldMinutes?: number;
298
+ catalyst?: string;
299
+ }
300
+ export interface Thesis {
301
+ summary: string;
302
+ invalidation: ThesisInvalidation;
303
+ }
304
+ export interface PositionThesis extends Thesis {
305
+ venue: Venue;
306
+ positionId: number;
307
+ symbol?: string;
308
+ side?: string;
309
+ source?: string;
310
+ slug?: string;
311
+ outcomeExternalMarketId?: string;
312
+ openedAt: string;
313
+ entryPrice?: number;
314
+ entryProbability?: number;
315
+ }
316
+ export interface ThesisView extends Thesis {
317
+ holdMinutes: number;
318
+ status: "intact" | "invalidated";
319
+ invalidatedBy?: string;
320
+ }
208
321
  export type ProposedAction = {
209
322
  type: "futures_open";
210
323
  symbol: string;
@@ -215,6 +328,7 @@ export type ProposedAction = {
215
328
  takeProfitPrice?: number | null;
216
329
  confidence?: number;
217
330
  rationaleSummary?: string;
331
+ thesis?: Thesis;
218
332
  } | {
219
333
  type: "futures_close";
220
334
  positionId: number;
@@ -236,6 +350,7 @@ export type ProposedAction = {
236
350
  stopPrice?: number;
237
351
  confidence?: number;
238
352
  rationaleSummary?: string;
353
+ thesis?: Thesis;
239
354
  } | {
240
355
  type: "spot_cancel";
241
356
  orderId: number;
@@ -249,6 +364,7 @@ export type ProposedAction = {
249
364
  confidence?: number;
250
365
  rationaleSummary?: string;
251
366
  forecastProbability?: number;
367
+ thesis?: Thesis;
252
368
  };
253
369
  export type ActionVenue = Venue;
254
370
  export declare function actionVenue(a: ProposedAction): ActionVenue;
@@ -272,7 +388,14 @@ export interface QuoteEvidence {
272
388
  entryPrice?: number;
273
389
  liquidationPrice?: number;
274
390
  executionPrice?: number;
391
+ entryProbability?: number;
392
+ stakeMusd?: number;
393
+ sharesEstimate?: number;
275
394
  estimatedCostMusd?: number;
395
+ estimatedFeeMusd?: number;
396
+ futuresFeeBps?: number;
397
+ estimatedEntryFeeMusd?: number;
398
+ cashRequiredMusd?: number;
276
399
  freshness?: Freshness;
277
400
  openBlocked?: boolean;
278
401
  openBlockReasons?: unknown;
@@ -281,6 +404,7 @@ export interface RunState {
281
404
  runId: string;
282
405
  cyclesRun: number;
283
406
  writesToday: number;
407
+ riskIncreasesToday: number;
284
408
  realizedPnlMusd: number;
285
409
  peakRealizedMusd: number;
286
410
  consecutiveRejectCycles: number;
@@ -303,6 +427,7 @@ export interface RunState {
303
427
  at: string;
304
428
  did: string;
305
429
  }>;
430
+ theses?: Record<string, PositionThesis>;
306
431
  }
307
432
  export interface AgentTrace {
308
433
  runId?: string;
@@ -329,8 +454,11 @@ export interface PlannedAction {
329
454
  quote?: QuoteEvidence;
330
455
  executed?: boolean;
331
456
  result?: unknown;
457
+ capitalSizing?: CapitalSizingAdjustment;
332
458
  }
333
459
  export interface CycleResult {
460
+ /** Private non-enumerable evidence. Never forward through AgentTrace/public APIs. */
461
+ decisionInputRecord?: DecisionInputRecord;
334
462
  decision: "skip" | "act";
335
463
  skipReason?: string;
336
464
  rationale?: string;
@@ -340,6 +468,16 @@ export interface CycleResult {
340
468
  modelFailed?: boolean;
341
469
  disabled?: boolean;
342
470
  disabledReason?: string;
471
+ /** Reliability slice 1 (2026-08-26): a PERMANENT provider/model failure
472
+ * (404/410/decommission class) no longer disables the agent. The runner
473
+ * reports the hold; the scheduler aggregates holds into a fleet-wide
474
+ * provider circuit (skip-claiming + backoff probes). User pauses, revoked
475
+ * credentials, drawdown and safety stops keep using `disabled`. */
476
+ providerHold?: {
477
+ provider: string;
478
+ model: string;
479
+ error: string;
480
+ };
343
481
  live: boolean;
344
482
  observationHash?: string;
345
483
  indicatorVersion?: string;
@@ -348,6 +486,19 @@ export interface CycleResult {
348
486
  tokensIn?: number;
349
487
  tokensOut?: number;
350
488
  estimatedCostUsd?: number;
489
+ effectiveProvider?: string;
490
+ effectiveModel?: string;
491
+ routeReason?: string;
492
+ routeAttempts?: Array<{
493
+ provider: string;
494
+ model: string;
495
+ outcome: "success" | "failed" | "deferred";
496
+ failureClass?: "capacity" | "permanent" | "transient" | "malformed";
497
+ status?: number;
498
+ retryAfterMs?: number;
499
+ latencyMs: number;
500
+ error?: string;
501
+ }>;
351
502
  decisionType?: "act" | "skip" | "gate_skip" | "model_error";
352
503
  writeAttempted?: number;
353
504
  writeAccepted?: number;
package/dist/http.js CHANGED
@@ -79,6 +79,27 @@ async function main() {
79
79
  },
80
80
  });
81
81
  });
82
+ // robots.txt for THIS host. robots.txt is per-HOST, so www.coinrithm.com's
83
+ // file never governed mcp.coinrithm.com — a separate origin that had no
84
+ // route of its own. The origin 404'd and Cloudflare answered with its
85
+ // managed content-signals boilerplate: 1,248 bytes of comments carrying ZERO
86
+ // User-agent/Disallow/Allow lines, which a crawler reads as "crawl
87
+ // everything". That is the identical failure that cost api.coinrithm.com
88
+ // 15.4% of the site's 90-day crawl budget (4,468 of 29,100 GSC requests)
89
+ // before it was closed on 2026-08-20.
90
+ //
91
+ // Nothing here is indexable: GET / is a JSON service descriptor, GET /mcp is
92
+ // a 405, and the real surface is POST-only streamable HTTP. The human-facing
93
+ // documentation crawlers should index lives on www.coinrithm.com
94
+ // (/en/agentic-trading, /en/prediction-markets/api), which links here.
95
+ //
96
+ // SAFE FOR MCP CLIENTS AND REGISTRIES: robots.txt is advisory to CRAWLERS
97
+ // only. MCP clients, Smithery and the MCP registry POST /mcp or GET /healthz
98
+ // directly and never consult robots.txt, so this cannot gate discovery,
99
+ // initialization or tool listing. Do not "fix" a registry problem here.
100
+ app.get("/robots.txt", (_req, res) => {
101
+ res.type("text/plain").send("User-agent: *\nDisallow: /\n");
102
+ });
82
103
  app.get("/mcp", (_req, res) => {
83
104
  res.status(405).json({
84
105
  error: "method_not_allowed",
package/dist/tools.js CHANGED
@@ -971,16 +971,16 @@ export function registerTools(server, client) {
971
971
  }, async ({ runId, agentTrace }, extra) => present(await client.exportLedger({ runId }, requestKey(extra), agentTrace)));
972
972
  server.registerTool("get_arena_leaderboard", {
973
973
  title: "Get Agent Arena leaderboard",
974
- description: "The public Agent Arena: opted-in agents ranked by total realized PnL " +
975
- "(mUSD) across spot, futures, and prediction markets, with per-venue " +
976
- "breakdown and win rate. Only agents with at least minDecidedTrades " +
977
- "decided (win+loss) trades rank (currently 3 — echoed in the " +
978
- "response); demo/house agents seed the board until live agents " +
979
- "qualify. Rows also carry a 44-day sparkline, badges, rankDelta, " +
980
- "biggestWinMusd, and the self-reported model label. Pass " +
981
- "window='7d'|'30d' for the weekly/monthly board — re-ranked by PnL " +
982
- "realized inside the window (badges/biggestWin and the min-decided " +
983
- "gate stay all-time). Use it to see the field and where you stand — pair " +
974
+ description: "The public Agent Arena across spot, futures, and prediction markets. " +
975
+ "The response publishes the arena-ranking-v1 contract: five decided " +
976
+ "trades qualify an agent for normal ordering; positive realized PnL is " +
977
+ "weighted by the 95% Wilson win-confidence lower bound; non-positive " +
978
+ "PnL is used directly. Agents below five remain listed after qualified " +
979
+ "agents; fewer than 20 decided trades is a separate small-sample " +
980
+ "warning. Rows carry per-venue results, a 90-day sparkline, badges, " +
981
+ "rankDelta, biggestWinMusd, and a self-reported model label. Pass " +
982
+ "window='today'|'24h'|'7d'|'30d'|'3m'|'all'. Use it to see the field " +
983
+ "and where you stand — pair " +
984
984
  "with get_performance (your own scorecard) and get_arena_agent (drill " +
985
985
  "into one handle). Public data: agent names + performance only. " +
986
986
  PAPER_NOTE,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coinrithm/mcp-trading",
3
- "version": "0.7.6",
3
+ "version": "0.7.8",
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",