@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.
- package/CHANGELOG.md +903 -811
- package/README.md +488 -415
- package/dist/agent/capitalSizing.d.ts +10 -1
- package/dist/agent/capitalSizing.js +28 -4
- package/dist/agent/client.d.ts +13 -0
- package/dist/agent/client.js +17 -6
- package/dist/agent/decision.d.ts +21 -16
- package/dist/agent/decision.js +7 -0
- package/dist/agent/decisionValidator.d.ts +1 -0
- package/dist/agent/decisionValidator.js +1 -1
- package/dist/agent/engine.d.ts +3 -1
- package/dist/agent/engine.js +3 -1
- package/dist/agent/futuresCloseOutcome.d.ts +19 -0
- package/dist/agent/futuresCloseOutcome.js +54 -0
- package/dist/agent/futuresEligibility.d.ts +13 -0
- package/dist/agent/futuresEligibility.js +43 -5
- package/dist/agent/observe.d.ts +2 -1
- package/dist/agent/observe.js +1 -1
- package/dist/agent/pmPaperCandidates.d.ts +17 -0
- package/dist/agent/pmPaperCandidates.js +125 -0
- package/dist/agent/pmPaperCycle.d.ts +16 -0
- package/dist/agent/pmPaperCycle.js +372 -0
- package/dist/agent/pmPaperDecision.d.ts +187 -0
- package/dist/agent/pmPaperDecision.js +101 -0
- package/dist/agent/pmPaperPolicy.d.ts +71 -0
- package/dist/agent/pmPaperPolicy.js +46 -0
- package/dist/agent/prompt.d.ts +12 -1
- package/dist/agent/prompt.js +90 -3
- package/dist/agent/providerCapabilities.d.ts +1 -0
- package/dist/agent/providerCapabilities.js +4 -1
- package/dist/agent/providers.d.ts +1 -0
- package/dist/agent/providers.js +9 -4
- package/dist/agent/runner.d.ts +9 -1
- package/dist/agent/runner.js +152 -24
- package/dist/agent/skill.js +9 -0
- package/dist/agent/skillValidator.js +23 -0
- package/dist/agent/strictLint.js +1 -0
- package/dist/agent/templates.js +30 -30
- package/dist/agent/types.d.ts +31 -0
- package/dist/agent/version.d.ts +1 -1
- package/dist/agent/version.js +1 -1
- package/dist/client.d.ts +14 -0
- package/dist/client.js +31 -1
- package/dist/http.js +1 -1
- package/dist/pmPaperV2.d.ts +81 -0
- package/dist/pmPaperV2.js +53 -0
- package/dist/tools.js +106 -14
- 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 →
|
|
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
|
|
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
|
-
|
|
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-
|
|
1161
|
-
"trades qualify an agent for normal ordering;
|
|
1162
|
-
"
|
|
1163
|
-
"
|
|
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
|
|
1791
|
-
"real-money venues,
|
|
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
|
|
1930
|
-
"weighted median across matched venues
|
|
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.
|
|
4
|
-
"mcpName": "io.github.CoinRithm/mcp-trading",
|
|
5
|
-
"description": "CoinRithm
|
|
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
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
"
|
|
66
|
-
"
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
"
|
|
75
|
-
"
|
|
76
|
-
"
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
"@
|
|
82
|
-
"@
|
|
83
|
-
"
|
|
84
|
-
"
|
|
85
|
-
"
|
|
86
|
-
"
|
|
87
|
-
"
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
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
|
+
}
|