@coinrithm/mcp-trading 0.7.16 → 0.7.18

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 (48) hide show
  1. package/CHANGELOG.md +903 -811
  2. package/README.md +488 -415
  3. package/dist/agent/capitalSizing.d.ts +10 -1
  4. package/dist/agent/capitalSizing.js +28 -4
  5. package/dist/agent/client.d.ts +13 -0
  6. package/dist/agent/client.js +17 -6
  7. package/dist/agent/decision.d.ts +21 -16
  8. package/dist/agent/decision.js +7 -0
  9. package/dist/agent/decisionValidator.d.ts +1 -0
  10. package/dist/agent/decisionValidator.js +1 -1
  11. package/dist/agent/engine.d.ts +3 -1
  12. package/dist/agent/engine.js +3 -1
  13. package/dist/agent/futuresCloseOutcome.d.ts +19 -0
  14. package/dist/agent/futuresCloseOutcome.js +54 -0
  15. package/dist/agent/futuresEligibility.d.ts +13 -0
  16. package/dist/agent/futuresEligibility.js +43 -5
  17. package/dist/agent/observe.d.ts +2 -1
  18. package/dist/agent/observe.js +1 -1
  19. package/dist/agent/pmPaperCandidates.d.ts +17 -0
  20. package/dist/agent/pmPaperCandidates.js +125 -0
  21. package/dist/agent/pmPaperCycle.d.ts +16 -0
  22. package/dist/agent/pmPaperCycle.js +372 -0
  23. package/dist/agent/pmPaperDecision.d.ts +187 -0
  24. package/dist/agent/pmPaperDecision.js +101 -0
  25. package/dist/agent/pmPaperPolicy.d.ts +71 -0
  26. package/dist/agent/pmPaperPolicy.js +46 -0
  27. package/dist/agent/prompt.d.ts +12 -1
  28. package/dist/agent/prompt.js +90 -3
  29. package/dist/agent/providerCapabilities.d.ts +1 -0
  30. package/dist/agent/providerCapabilities.js +4 -1
  31. package/dist/agent/providers.d.ts +1 -0
  32. package/dist/agent/providers.js +9 -4
  33. package/dist/agent/runner.d.ts +9 -1
  34. package/dist/agent/runner.js +152 -24
  35. package/dist/agent/skill.js +9 -0
  36. package/dist/agent/skillValidator.js +23 -0
  37. package/dist/agent/strictLint.js +1 -0
  38. package/dist/agent/templates.js +30 -30
  39. package/dist/agent/types.d.ts +31 -0
  40. package/dist/agent/version.d.ts +1 -1
  41. package/dist/agent/version.js +1 -1
  42. package/dist/client.d.ts +14 -0
  43. package/dist/client.js +31 -1
  44. package/dist/http.js +1 -1
  45. package/dist/pmPaperV2.d.ts +81 -0
  46. package/dist/pmPaperV2.js +53 -0
  47. package/dist/tools.js +106 -14
  48. package/package.json +100 -98
package/dist/client.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { type PmPaperOpen, type PmPaperClose } from "./pmPaperV2.js";
1
2
  export declare const DEFAULT_BASE_URL = "https://api.coinrithm.com";
2
3
  export declare function log(...args: unknown[]): void;
3
4
  export interface ClientConfig {
@@ -110,6 +111,7 @@ export declare class CoinRithmClient {
110
111
  updatedSince?: string;
111
112
  }, apiKey?: string, agentTrace?: AgentTrace): Promise<ApiResult>;
112
113
  getMarketContext(coinId: string, apiKey?: string, agentTrace?: AgentTrace): Promise<ApiResult>;
114
+ getSpotReference(coinId: string, apiKey?: string, agentTrace?: AgentTrace): Promise<ApiResult>;
113
115
  getCandles(coinId: string, query?: {
114
116
  range?: "1H" | "1D" | "1W" | "1M" | "3M";
115
117
  fiat?: string;
@@ -120,6 +122,10 @@ export declare class CoinRithmClient {
120
122
  hours?: number;
121
123
  minImportance?: number;
122
124
  }, apiKey?: string, agentTrace?: AgentTrace): Promise<ApiResult>;
125
+ discoverPmPaperV2(query?: {
126
+ q?: string;
127
+ limit?: number;
128
+ }, apiKey?: string, agentTrace?: AgentTrace): Promise<ApiResult>;
123
129
  discoverPmMarkets(query?: {
124
130
  q?: string;
125
131
  source?: "all" | "kalshi" | "polymarket";
@@ -221,6 +227,14 @@ export declare class CoinRithmClient {
221
227
  fraction?: number;
222
228
  idempotencyKey: string;
223
229
  }>, apiKey?: string): Promise<ApiResult>;
230
+ openPmPaperV2(body: PmPaperOpen, apiKey?: string): Promise<ApiResult>;
231
+ replayPmPaperV2Open(body: PmPaperOpen, apiKey?: string): Promise<ApiResult>;
232
+ closePmPaperV2(body: PmPaperClose, apiKey?: string): Promise<ApiResult>;
233
+ pmPaperV2Positions(apiKey?: string, query?: {
234
+ status?: "open";
235
+ beforeId?: number;
236
+ limit?: number;
237
+ }): Promise<ApiResult>;
224
238
  openPmPosition(body: TraceableBody<{
225
239
  source: string;
226
240
  slug: string;
package/dist/client.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { PM_PAPER_V2_BASE, } from "./pmPaperV2.js";
1
2
  // Thin HTTP client for the CoinRithm agent surface (/api/agent/*).
2
3
  //
3
4
  // Auth: a user-minted API key (crk_live_…) passed as `Authorization: Bearer …`.
@@ -30,7 +31,7 @@ function resolveBaseUrl() {
30
31
  export function loadConfig() {
31
32
  const apiKey = process.env.COINRITHM_API_KEY?.trim();
32
33
  if (!apiKey) {
33
- throw new Error("COINRITHM_API_KEY is not set. Mint a key in CoinRithm → Profile → API Keys " +
34
+ throw new Error("COINRITHM_API_KEY is not set. Mint a key in CoinRithm → Settings → API Keys " +
34
35
  "and expose it to this MCP server as the COINRITHM_API_KEY environment variable.");
35
36
  }
36
37
  if (!apiKey.startsWith("crk_live_")) {
@@ -339,6 +340,9 @@ export class CoinRithmClient {
339
340
  getMarketContext(coinId, apiKey, agentTrace) {
340
341
  return this.request("GET", `/api/agent/market/${encodeURIComponent(coinId)}`, { apiKey, agentTrace });
341
342
  }
343
+ getSpotReference(coinId, apiKey, agentTrace) {
344
+ return this.request("GET", `/api/agent/spot/reference/${encodeURIComponent(coinId)}`, { apiKey, agentTrace });
345
+ }
342
346
  getCandles(coinId, query, apiKey, agentTrace) {
343
347
  return this.request("GET", `/api/agent/market/${encodeURIComponent(coinId)}/candles`, { query, apiKey, agentTrace });
344
348
  }
@@ -349,6 +353,13 @@ export class CoinRithmClient {
349
353
  agentTrace,
350
354
  });
351
355
  }
356
+ discoverPmPaperV2(query, apiKey, agentTrace) {
357
+ return this.request("GET", "/api/agent/pm/v2/discover", {
358
+ query,
359
+ apiKey,
360
+ agentTrace,
361
+ });
362
+ }
352
363
  discoverPmMarkets(query, apiKey, agentTrace) {
353
364
  return this.request("GET", "/api/agent/pm/discover", {
354
365
  query,
@@ -435,6 +446,25 @@ export class CoinRithmClient {
435
446
  closeFuturesPosition(body, apiKey) {
436
447
  return this.request("POST", "/api/agent/futures/close", { body, apiKey });
437
448
  }
449
+ // Explicit opt-in contract; API derives and authorizes the configured house tuple.
450
+ openPmPaperV2(body, apiKey) {
451
+ return this.request("POST", `${PM_PAPER_V2_BASE}/open`, { body, apiKey });
452
+ }
453
+ replayPmPaperV2Open(body, apiKey) {
454
+ return this.request("POST", `${PM_PAPER_V2_BASE}/open/replay`, {
455
+ body,
456
+ apiKey,
457
+ });
458
+ }
459
+ closePmPaperV2(body, apiKey) {
460
+ return this.request("POST", `${PM_PAPER_V2_BASE}/close`, { body, apiKey });
461
+ }
462
+ pmPaperV2Positions(apiKey, query) {
463
+ return this.request("GET", `${PM_PAPER_V2_BASE}/positions`, {
464
+ apiKey,
465
+ query,
466
+ });
467
+ }
438
468
  openPmPosition(body, apiKey) {
439
469
  return this.request("POST", "/api/agent/pm/open", { body, apiKey });
440
470
  }
package/dist/http.js CHANGED
@@ -75,7 +75,7 @@ export function createHttpApp(client, options = {}) {
75
75
  res.json({
76
76
  service: "CoinRithm MCP",
77
77
  version: SERVER_VERSION,
78
- description: "Model Context Protocol server for CoinRithm: keyless public prediction-market data tools (pm_data_*) plus paper-trading tools (spot, futures, prediction markets) with a crk_live_ API key. Paper only — never real money.",
78
+ description: "Model Context Protocol server for CoinRithm: keyless prediction-market data tools across 12 venues (pm_data_*), keyless crypto movers and Agent Arena reads, plus crypto market context and paper-trading tools (spot, futures, prediction markets) with a crk_live_ API key. Opt-in PM paper v2 and spot reference tools are off unless the server enables them. Paper only, never real money.",
79
79
  endpoint: {
80
80
  url: "https://mcp.coinrithm.com/mcp",
81
81
  method: "POST",
@@ -0,0 +1,81 @@
1
+ import { z } from "zod";
2
+ export declare const pmPaperOpenSchema: z.ZodObject<{
3
+ source: z.ZodEnum<["kalshi", "polymarket"]>;
4
+ slug: z.ZodString;
5
+ outcomeExternalMarketId: z.ZodString;
6
+ side: z.ZodEnum<["yes", "no"]>;
7
+ maxCashBudget: z.ZodEffects<z.ZodString, string, string>;
8
+ idempotencyKey: z.ZodString;
9
+ minEntryProbabilityPct: z.ZodOptional<z.ZodNullable<z.ZodEffects<z.ZodString, string, string>>>;
10
+ forecastProbability: z.ZodOptional<z.ZodNullable<z.ZodEffects<z.ZodString, string, string>>>;
11
+ thesis: z.ZodOptional<z.ZodNullable<z.ZodEffects<z.ZodString, string, string>>>;
12
+ }, "strict", z.ZodTypeAny, {
13
+ source: "kalshi" | "polymarket";
14
+ slug: string;
15
+ outcomeExternalMarketId: string;
16
+ side: "yes" | "no";
17
+ maxCashBudget: string;
18
+ idempotencyKey: string;
19
+ minEntryProbabilityPct?: string | null | undefined;
20
+ forecastProbability?: string | null | undefined;
21
+ thesis?: string | null | undefined;
22
+ }, {
23
+ source: "kalshi" | "polymarket";
24
+ slug: string;
25
+ outcomeExternalMarketId: string;
26
+ side: "yes" | "no";
27
+ maxCashBudget: string;
28
+ idempotencyKey: string;
29
+ minEntryProbabilityPct?: string | null | undefined;
30
+ forecastProbability?: string | null | undefined;
31
+ thesis?: string | null | undefined;
32
+ }>;
33
+ export declare const pmPaperCloseSchema: z.ZodObject<{
34
+ positionId: z.ZodNumber;
35
+ idempotencyKey: z.ZodString;
36
+ detail: z.ZodOptional<z.ZodNullable<z.ZodEffects<z.ZodString, string, string>>>;
37
+ }, "strict", z.ZodTypeAny, {
38
+ idempotencyKey: string;
39
+ positionId: number;
40
+ detail?: string | null | undefined;
41
+ }, {
42
+ idempotencyKey: string;
43
+ positionId: number;
44
+ detail?: string | null | undefined;
45
+ }>;
46
+ export declare const pmForecastProbabilitySchema: z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>;
47
+ export declare const pmPaperAgentOpenSchema: z.ZodObject<{
48
+ source: z.ZodEnum<["kalshi", "polymarket"]>;
49
+ slug: z.ZodString;
50
+ outcomeExternalMarketId: z.ZodString;
51
+ side: z.ZodEnum<["yes", "no"]>;
52
+ maxCashBudget: z.ZodEffects<z.ZodString, string, string>;
53
+ idempotencyKey: z.ZodString;
54
+ minEntryProbabilityPct: z.ZodOptional<z.ZodNullable<z.ZodEffects<z.ZodString, string, string>>>;
55
+ thesis: z.ZodOptional<z.ZodNullable<z.ZodEffects<z.ZodString, string, string>>>;
56
+ } & {
57
+ forecastProbability: z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>;
58
+ }, "strict", z.ZodTypeAny, {
59
+ source: "kalshi" | "polymarket";
60
+ slug: string;
61
+ outcomeExternalMarketId: string;
62
+ side: "yes" | "no";
63
+ maxCashBudget: string;
64
+ idempotencyKey: string;
65
+ forecastProbability: string;
66
+ minEntryProbabilityPct?: string | null | undefined;
67
+ thesis?: string | null | undefined;
68
+ }, {
69
+ source: "kalshi" | "polymarket";
70
+ slug: string;
71
+ outcomeExternalMarketId: string;
72
+ side: "yes" | "no";
73
+ maxCashBudget: string;
74
+ idempotencyKey: string;
75
+ forecastProbability: string;
76
+ minEntryProbabilityPct?: string | null | undefined;
77
+ thesis?: string | null | undefined;
78
+ }>;
79
+ export type PmPaperOpen = z.infer<typeof pmPaperOpenSchema>;
80
+ export type PmPaperClose = z.infer<typeof pmPaperCloseSchema>;
81
+ export declare const PM_PAPER_V2_BASE = "/api/agent/pm/v2";
@@ -0,0 +1,53 @@
1
+ import { z } from "zod";
2
+ // Exact decimal wire values; never derive a fee-inclusive budget from stakeMusd.
3
+ const decimal = z
4
+ .string()
5
+ .max(40)
6
+ .regex(/^(0|[1-9]\d*)(\.\d{1,18})?$/);
7
+ const boundedDecimal = (min, max, exclusive = false) => decimal.refine((value) => {
8
+ if (!/^(0|[1-9]\d*)(\.\d{1,18})?$/.test(value) || value.length > 40)
9
+ return false;
10
+ const [whole, fraction = ""] = value.split(".");
11
+ const scaled = BigInt(whole) * 10n ** 18n + BigInt(fraction.padEnd(18, "0"));
12
+ const lower = BigInt(min) * 10n ** 18n, upper = BigInt(max) * 10n ** 18n;
13
+ return exclusive
14
+ ? scaled > lower && scaled < upper
15
+ : scaled >= lower && scaled <= upper;
16
+ });
17
+ const text = (max) => z
18
+ .string()
19
+ .max(max)
20
+ .refine((value) => [...value].every((char) => char.charCodeAt(0) >= 32 && char.charCodeAt(0) !== 127));
21
+ export const pmPaperOpenSchema = z
22
+ .object({
23
+ source: z.enum(["kalshi", "polymarket"]),
24
+ slug: z.string().min(1).max(256),
25
+ outcomeExternalMarketId: z.string().min(1).max(256),
26
+ side: z.enum(["yes", "no"]),
27
+ maxCashBudget: boundedDecimal(10, 1000000).describe("Exact decimal string: maximum total paper cash including entry fees; 10..1000000 mUSD."),
28
+ idempotencyKey: z.string().regex(/^pm-entry:[A-Za-z0-9:_-]{1,111}$/),
29
+ minEntryProbabilityPct: boundedDecimal(0, 100).nullable().optional(),
30
+ forecastProbability: boundedDecimal(0, 100, true).nullable().optional(),
31
+ thesis: text(280).nullable().optional(),
32
+ })
33
+ .strict();
34
+ export const pmPaperCloseSchema = z
35
+ .object({
36
+ positionId: z.number().int().positive().max(2147483647),
37
+ idempotencyKey: z.string().regex(/^pm-exit:[A-Za-z0-9:_-]{1,111}$/),
38
+ detail: text(1024).nullable().optional(),
39
+ })
40
+ .strict();
41
+ // Matches backend-v2 normalizePmPaperEntryRequest (acbf1cc): the chance that
42
+ // the BOUGHT side pays out. Below 1 is read as a fraction (x100), above 1 as a
43
+ // percent; exactly 1 is ambiguous and refused; 0 and 100 are refused.
44
+ const exactlyOne = /^1(\.0{1,18})?$/;
45
+ export const pmForecastProbabilitySchema = boundedDecimal(0, 100, true)
46
+ .refine((value) => !exactlyOne.test(value))
47
+ .describe("Required exact decimal string: chance that the side you buy pays out. Percent above 1 and below 100 (e.g. 62.5), or a fraction above 0 and below 1 (0.625 = 62.5%); exactly 1 is refused.");
48
+ // API-key opens: the API answers 422 forecast_required without a forecast.
49
+ // The base schema above stays optional so stored legacy requests can replay.
50
+ export const pmPaperAgentOpenSchema = pmPaperOpenSchema
51
+ .extend({ forecastProbability: pmForecastProbabilitySchema })
52
+ .strict();
53
+ export const PM_PAPER_V2_BASE = "/api/agent/pm/v2";
package/dist/tools.js CHANGED
@@ -1,9 +1,4 @@
1
- // Registers the CoinRithm trading tools on an MCP server instance.
2
- //
3
- // Every tool wraps exactly one /api/agent/* call. Tool results return the raw
4
- // JSON body as text so the model sees the real server response (incl. error
5
- // shapes like { error, blockReasons }). HTTP-level failures are surfaced as
6
- // isError results rather than thrown so the model can react.
1
+ import { pmPaperAgentOpenSchema, pmPaperCloseSchema } from "./pmPaperV2.js";
7
2
  import { z } from "zod";
8
3
  import { bearerFromHeader } from "./client.js";
9
4
  import { PAPER_EXECUTION_VERSION } from "./executionPolicy.js";
@@ -427,9 +422,17 @@ function compactComparison(value) {
427
422
  (outcome.isShared === true ||
428
423
  (outcome.presentInA === true && outcome.presentInB === true)));
429
424
  const candidates = shared.length > 0 ? shared : outcomes;
425
+ // The API headline (summary.maxSharedOutcome*) skips a row whose legs do
426
+ // not both show trading (`bothSidesTraded: false`). Such a row is still
427
+ // listed, but ranks after every other row so it never leads as the largest
428
+ // gap. Older APIs omit the field, which ranks exactly as before.
429
+ const untraded = (outcome) => isJsonRecord(outcome) && outcome.bothSidesTraded === false ? 1 : 0;
430
430
  const ranked = candidates
431
431
  .map((outcome, index) => ({ outcome, index }))
432
432
  .sort((left, right) => {
433
+ const evidence = untraded(left.outcome) - untraded(right.outcome);
434
+ if (evidence !== 0)
435
+ return evidence;
433
436
  const a = isJsonRecord(left.outcome)
434
437
  ? Math.abs(probability(left.outcome.deltaPoints) ?? -1)
435
438
  : -1;
@@ -451,6 +454,8 @@ function compactComparison(value) {
451
454
  "presentInA",
452
455
  "presentInB",
453
456
  "isShared",
457
+ "bothSidesTraded",
458
+ "pairing",
454
459
  ])
455
460
  : outcome);
456
461
  return {
@@ -725,6 +730,32 @@ function mapSuccessfulBody(result, transform) {
725
730
  return result.ok ? { ...result, data: transform(result.data) } : result;
726
731
  }
727
732
  export function registerTools(server, client) {
733
+ // Separate opt-in inventory: never enrich existing market context or prompts.
734
+ if (process.env.COINRITHM_SPOT_REFERENCE_TOOLS_ENABLED === "true") {
735
+ server.registerTool("get_spot_reference", {
736
+ title: "Get optional spot reference",
737
+ description: "Read a separate Binance spot last-ticker reference and stored REST " +
738
+ "consensus fallback for one coinId (read scope). Reference only: " +
739
+ "stream price and rolling 24h quote volume are USDT; fallback price " +
740
+ "is USD, with no currency conversion. A 200 response can contain " +
741
+ "an unavailable stream or stale/unavailable fallback: inspect each " +
742
+ "status, reason and expiresAt. preferredSource does not establish " +
743
+ "freshness or execution eligibility. eventAt is emission, " +
744
+ "statisticsCloseAt is the ticker window close, receivedAt is " +
745
+ "acquisition and localPriceChangedAt is a local observation; " +
746
+ "lastTradeAt is unknown. This is not an executable quote, order-book " +
747
+ "depth or fill guarantee and does not replace get_market_context.",
748
+ inputSchema: {
749
+ coinId: z
750
+ .string()
751
+ .regex(/^[a-zA-Z0-9_-]{1,64}$/)
752
+ .describe("CoinRithm coinId from resolve_symbol; not an exchange pair."),
753
+ agentTrace: AGENT_TRACE_SCHEMA,
754
+ },
755
+ outputSchema: API_RESULT_OUTPUT_SCHEMA,
756
+ annotations: readOnlyAnnotations("Get optional spot reference"),
757
+ }, async ({ coinId, agentTrace }, extra) => present(await client.getSpotReference(coinId, requestKey(extra), agentTrace)));
758
+ }
728
759
  // ---------------- identity ----------------
729
760
  server.registerTool("whoami", {
730
761
  title: "Who am I (CoinRithm)",
@@ -1157,10 +1188,11 @@ export function registerTools(server, client) {
1157
1188
  server.registerTool("get_arena_leaderboard", {
1158
1189
  title: "Get Agent Arena leaderboard",
1159
1190
  description: "The public Agent Arena across spot, futures, and prediction markets. " +
1160
- "The response publishes the arena-ranking-v1 contract: five decided " +
1161
- "trades qualify an agent for normal ordering; positive realized PnL is " +
1162
- "weighted by the 95% Wilson win-confidence lower bound; non-positive " +
1163
- "PnL is used directly. Agents below five remain listed after qualified " +
1191
+ "The response publishes the arena-ranking-v2 contract: five decided " +
1192
+ "trades qualify an agent for normal ordering; the score is realized " +
1193
+ "PnL plus open losses (open gains never count); a positive score is " +
1194
+ "weighted by the 95% Wilson win-confidence lower bound; a non-positive " +
1195
+ "score is used directly. Agents below five remain listed after qualified " +
1164
1196
  "agents; fewer than 20 decided trades is a separate small-sample " +
1165
1197
  "warning. Rows carry per-venue results, a 90-day sparkline, badges, " +
1166
1198
  "rankDelta, biggestWinMusd, and a self-reported model label. Pass " +
@@ -1571,6 +1603,63 @@ export function registerTools(server, client) {
1571
1603
  provenance,
1572
1604
  agentTrace,
1573
1605
  }, requestKey(extra))));
1606
+ if (process.env.COINRITHM_PM_PAPER_V2_TOOLS_ENABLED === "true") {
1607
+ server.registerTool("discover_pm_paper_v2_markets", {
1608
+ title: "Discover PM paper v2 candidates",
1609
+ description: "For server-configured PM paper v2 house keys only (other keys get 403 house_opt_in_required). Returns Kalshi/Polymarket outcomes with exact stored native identity (nativeMarket.key) and scheduled native end, filtered to the house's configured horizon; meta.boundedSelection reports how many were excluded and why. Candidate evidence only: open_pm_paper_v2 reacquires native identity, maturity, book and fees, and may still refuse. nativeEndAt is a scheduled end, not a settlement-time guarantee. " +
1610
+ PAPER_NOTE_SHORT,
1611
+ inputSchema: {
1612
+ q: z
1613
+ .string()
1614
+ .max(100)
1615
+ .optional()
1616
+ .describe("Optional search text (title, outcome, topic)."),
1617
+ limit: z
1618
+ .number()
1619
+ .int()
1620
+ .min(1)
1621
+ .max(50)
1622
+ .optional()
1623
+ .describe("Max events before filtering (1-50, default 20)."),
1624
+ agentTrace: AGENT_TRACE_SCHEMA,
1625
+ },
1626
+ outputSchema: API_RESULT_OUTPUT_SCHEMA,
1627
+ annotations: readOnlyAnnotations("Discover PM paper v2 candidates"),
1628
+ }, async ({ q, limit, agentTrace }, extra) => present(await client.discoverPmPaperV2({ q, limit }, requestKey(extra), agentTrace)));
1629
+ server.registerTool("open_pm_paper_v2", {
1630
+ title: "Open opted-in PM paper position",
1631
+ description: "For server-configured PM paper v2 house keys only. Opens against freshly acquired native Kalshi/Polymarket depth. maxCashBudget is an explicit exact decimal TOTAL cash budget including fees, not legacy stakeMusd. forecastProbability is required: the chance the side you buy pays out (percent above 1 and below 100, or a fraction above 0 and below 1; exactly 1 is refused as ambiguous); the API refuses an open whose forecast does not exceed the fee-inclusive cost per share. Server admission defaults off. Reuse the identical pm-entry key and body after uncertain delivery. Existing legacy tools keep their behavior. " +
1632
+ PAPER_NOTE_SHORT,
1633
+ inputSchema: pmPaperAgentOpenSchema.shape,
1634
+ outputSchema: API_RESULT_OUTPUT_SCHEMA,
1635
+ annotations: mutatingAnnotations("Open opted-in PM paper position", {
1636
+ idempotent: true,
1637
+ }),
1638
+ }, async (body, extra) => present(await client.openPmPaperV2(pmPaperAgentOpenSchema.parse(body), requestKey(extra))));
1639
+ server.registerTool("close_pm_paper_v2", {
1640
+ title: "Request full PM paper exit",
1641
+ description: "Request a durable FULL exit for an owned PM paper v2 position. A 202 accepted response is pending, NOT an executed sale or final PnL. Native depth and settlement can leave an exit pending or requiring attention. Reuse the identical pm-exit key/body to reconcile; only executed:true confirms completion. Entry pauses do not stop existing exits. " +
1642
+ PAPER_NOTE_SHORT,
1643
+ inputSchema: pmPaperCloseSchema.shape,
1644
+ outputSchema: API_RESULT_OUTPUT_SCHEMA,
1645
+ annotations: mutatingAnnotations("Request full PM paper exit", {
1646
+ destructive: true,
1647
+ idempotent: true,
1648
+ }),
1649
+ }, async (body, extra) => present(await client.closePmPaperV2(pmPaperCloseSchema.parse(body), requestKey(extra))));
1650
+ server.registerTool("get_pm_paper_v2_positions", {
1651
+ title: "Read PM paper v2 positions and exit receipts",
1652
+ description: "Read the caller's bounded PM paper v2 positions, persisted exit intents and terminal accounting receipts. Pending/leased/retry/manual_attention do not establish execution or final PnL. " +
1653
+ PAPER_NOTE_SHORT,
1654
+ inputSchema: {
1655
+ status: z.literal("open").optional(),
1656
+ beforeId: z.number().int().positive().max(2147483647).optional(),
1657
+ limit: z.number().int().min(1).max(50).optional(),
1658
+ },
1659
+ outputSchema: API_RESULT_OUTPUT_SCHEMA,
1660
+ annotations: readOnlyAnnotations("Read PM paper v2 positions"),
1661
+ }, async (query, extra) => present(await client.pmPaperV2Positions(requestKey(extra), query)));
1662
+ }
1574
1663
  server.registerTool("report_pm_opportunity", {
1575
1664
  title: "Report a non-opened PM opportunity",
1576
1665
  description: "Save a durable SELF-REPORT of a prediction-market evaluation for a " +
@@ -1787,8 +1876,10 @@ export function registerTools(server, client) {
1787
1876
  "crossSourceMatches (the SAME real-world question priced on other " +
1788
1877
  "venues — read probability divergence directly from it), " +
1789
1878
  "referenceProbability when present (CoinRithm's canonical cross-venue " +
1790
- "number: the liquidity-weighted median Yes probability across matched " +
1791
- "real-money venues, with venueCount and spreadPoints — quote all " +
1879
+ "number: the size-capped weighted median Yes probability across " +
1880
+ "matched real-money venues, weighted by open interest or else " +
1881
+ "liquidity as weightBasis states, with venueCount and spreadPoints " +
1882
+ "and methodologyVersion — quote all " +
1792
1883
  "three together, venues disagree and the spread says by how much), " +
1793
1884
  "recent whale trades on the event, related events, related news, and " +
1794
1885
  "volumeHistory when present (daily volume points captured since " +
@@ -1926,8 +2017,9 @@ export function registerTools(server, client) {
1926
2017
  "deltaPoints (points, 0-100 scale) plus a summary (matchedOutcomeCount, " +
1927
2018
  "overallDeltaPoints, maxSharedOutcomeDeltaPoints); maxOverallGap/" +
1928
2019
  "maxOutcomeGap/maxConfidence are the cluster's headline numbers, and " +
1929
- "referenceProbability (when present) is CoinRithm's own liquidity-" +
1930
- "weighted median across matched venues. Orientation between matched " +
2020
+ "referenceProbability (when present) is CoinRithm's own size-capped " +
2021
+ "weighted median across matched venues (weightBasis: open_interest or " +
2022
+ "liquidity). Orientation between matched " +
1931
2023
  "markets is human/aggregator-reviewed — NEVER price-inferred — so every " +
1932
2024
  "delta is orientation-proven disagreement, not noise. requirePriced " +
1933
2025
  "(default true) drops any pair where a side is an unpriced/untraded " +
package/package.json CHANGED
@@ -1,98 +1,100 @@
1
- {
2
- "name": "@coinrithm/mcp-trading",
3
- "version": "0.7.16",
4
- "mcpName": "io.github.CoinRithm/mcp-trading",
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
- "type": "module",
7
- "author": "CoinRithm",
8
- "homepage": "https://coinrithm.com/agentic-trading",
9
- "repository": {
10
- "type": "git",
11
- "url": "git+https://github.com/CoinRithm/coinrithm-agent-trading.git",
12
- "directory": "packages/mcp-trading"
13
- },
14
- "bugs": {
15
- "url": "https://github.com/CoinRithm/coinrithm-agent-trading/issues"
16
- },
17
- "publishConfig": {
18
- "access": "public"
19
- },
20
- "bin": {
21
- "coinrithm-mcp": "dist/index.js",
22
- "coinrithm-agent": "dist/agent/index.js"
23
- },
24
- "main": "dist/index.js",
25
- "files": [
26
- "dist",
27
- "README.md",
28
- "CHANGELOG.md"
29
- ],
30
- "scripts": {
31
- "build": "tsc -p tsconfig.json",
32
- "typecheck": "tsc -p tsconfig.json --noEmit",
33
- "test": "vitest run",
34
- "test:coverage": "vitest run --coverage",
35
- "lint": "eslint src",
36
- "lint:fix": "eslint src --fix",
37
- "format": "prettier --write \"src/**/*.ts\"",
38
- "format:check": "prettier --check \"src/**/*.ts\"",
39
- "start": "node dist/index.js",
40
- "start:http": "node dist/http.js",
41
- "smoke:agent": "npm run build && node scripts/agent-smoke.mjs",
42
- "prepare": "npm run build"
43
- },
44
- "engines": {
45
- "node": ">=18"
46
- },
47
- "keywords": [
48
- "mcp",
49
- "mcp-server",
50
- "model-context-protocol",
51
- "ai-agent",
52
- "agent-trading",
53
- "trading",
54
- "paper-trading",
55
- "crypto",
56
- "futures",
57
- "prediction-markets",
58
- "polymarket",
59
- "kalshi",
60
- "claude",
61
- "chatgpt",
62
- "gemini",
63
- "cursor",
64
- "open-knowledge-format",
65
- "okf",
66
- "model-agnostic",
67
- "leaderboard",
68
- "coinrithm"
69
- ],
70
- "license": "MIT",
71
- "dependencies": {
72
- "@modelcontextprotocol/sdk": "^1.31.0",
73
- "express": "^4.21.0",
74
- "json5": "2.2.3",
75
- "yaml": "^2.5.0",
76
- "zod": "^3.23.8"
77
- },
78
- "devDependencies": {
79
- "@eslint/js": "^9.13.0",
80
- "@types/express": "^4.17.21",
81
- "@types/node": "^20.14.0",
82
- "@vitest/coverage-v8": "4.1.11",
83
- "eslint": "^9.13.0",
84
- "prettier": "^3.3.3",
85
- "typescript": "^5.5.0",
86
- "typescript-eslint": "^8.11.0",
87
- "vitest": "4.1.11"
88
- },
89
- "exports": {
90
- ".": "./dist/index.js",
91
- "./engine": {
92
- "types": "./dist/agent/engine.d.ts",
93
- "import": "./dist/agent/engine.js"
94
- },
95
- "./package.json": "./package.json",
96
- "./dist/*": "./dist/*"
97
- }
98
- }
1
+ {
2
+ "name": "@coinrithm/mcp-trading",
3
+ "version": "0.7.18",
4
+ "mcpName": "io.github.CoinRithm/mcp-trading",
5
+ "description": "CoinRithm MCP server (coinrithm-mcp) and self-host agent runner (coinrithm-agent): keyless prediction-market data across 12 venues, plus paper trading of crypto spot, futures, and prediction markets with a user-minted API key.",
6
+ "type": "module",
7
+ "author": "CoinRithm",
8
+ "homepage": "https://coinrithm.com/agentic-trading",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/CoinRithm/coinrithm-agent-trading.git",
12
+ "directory": "packages/mcp-trading"
13
+ },
14
+ "bugs": {
15
+ "url": "https://github.com/CoinRithm/coinrithm-agent-trading/issues"
16
+ },
17
+ "publishConfig": {
18
+ "access": "public"
19
+ },
20
+ "bin": {
21
+ "coinrithm-mcp": "dist/index.js",
22
+ "coinrithm-agent": "dist/agent/index.js"
23
+ },
24
+ "main": "dist/index.js",
25
+ "files": [
26
+ "dist",
27
+ "README.md",
28
+ "CHANGELOG.md"
29
+ ],
30
+ "scripts": {
31
+ "build": "tsc -p tsconfig.json",
32
+ "typecheck": "tsc -p tsconfig.json --noEmit",
33
+ "test": "vitest run",
34
+ "test:coverage": "vitest run --coverage",
35
+ "lint": "eslint src",
36
+ "lint:fix": "eslint src --fix",
37
+ "format": "prettier --write \"src/**/*.ts\"",
38
+ "format:check": "prettier --check \"src/**/*.ts\"",
39
+ "start": "node dist/index.js",
40
+ "start:http": "node dist/http.js",
41
+ "smoke:agent": "npm run build && node scripts/agent-smoke.mjs",
42
+ "prepare": "npm run build"
43
+ },
44
+ "engines": {
45
+ "node": ">=18"
46
+ },
47
+ "keywords": [
48
+ "mcp",
49
+ "mcp-server",
50
+ "model-context-protocol",
51
+ "ai-agent",
52
+ "agent-trading",
53
+ "trading",
54
+ "paper-trading",
55
+ "crypto",
56
+ "futures",
57
+ "prediction-markets",
58
+ "prediction-market-data",
59
+ "market-data",
60
+ "polymarket",
61
+ "kalshi",
62
+ "claude",
63
+ "chatgpt",
64
+ "gemini",
65
+ "cursor",
66
+ "open-knowledge-format",
67
+ "okf",
68
+ "model-agnostic",
69
+ "leaderboard",
70
+ "coinrithm"
71
+ ],
72
+ "license": "MIT",
73
+ "dependencies": {
74
+ "@modelcontextprotocol/sdk": "^1.31.0",
75
+ "express": "^4.21.0",
76
+ "json5": "2.2.3",
77
+ "yaml": "^2.5.0",
78
+ "zod": "^3.23.8"
79
+ },
80
+ "devDependencies": {
81
+ "@eslint/js": "^9.13.0",
82
+ "@types/express": "^4.17.21",
83
+ "@types/node": "^20.14.0",
84
+ "@vitest/coverage-v8": "4.1.11",
85
+ "eslint": "^9.13.0",
86
+ "prettier": "^3.3.3",
87
+ "typescript": "^5.5.0",
88
+ "typescript-eslint": "^8.11.0",
89
+ "vitest": "4.1.11"
90
+ },
91
+ "exports": {
92
+ ".": "./dist/index.js",
93
+ "./engine": {
94
+ "types": "./dist/agent/engine.d.ts",
95
+ "import": "./dist/agent/engine.js"
96
+ },
97
+ "./package.json": "./package.json",
98
+ "./dist/*": "./dist/*"
99
+ }
100
+ }