@pgnio/helios-mcp 0.2.8 → 0.2.9
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/dist/{chunk-V453JYRN.mjs → chunk-7TMDGB6C.mjs} +64 -31
- package/dist/{chunk-UHFLF3UG.mjs → chunk-LMZEWQVW.mjs} +62 -29
- package/dist/cli.js +40 -14
- package/dist/cli.mjs +1 -1
- package/dist/index.d.mts +15 -9
- package/dist/index.d.ts +15 -9
- package/dist/index.js +40 -14
- package/dist/index.mjs +1 -1
- package/docs/ai-agent-indicators/00_columns.txt +3 -1
- package/package.json +1 -1
- package/dist/chunk-52XY4KRG.mjs +0 -3038
- package/dist/chunk-7EDI4KLD.mjs +0 -3042
- package/dist/chunk-EIAUO3XE.mjs +0 -2955
- package/dist/chunk-NCF7ASJB.mjs +0 -2986
- package/dist/chunk-NWGWXYTS.mjs +0 -2964
- package/dist/chunk-UYCUR7QV.mjs +0 -2994
- package/dist/chunk-WLCFIWFP.mjs +0 -3048
- package/dist/chunk-XE6HRID3.mjs +0 -2992
package/dist/cli.js
CHANGED
|
@@ -139,19 +139,21 @@ var protectiveOrderKindSchema = import_zod.z.enum(["STOP_LOSS", "TAKE_PROFIT"]);
|
|
|
139
139
|
var protectiveOrderSideSchema = import_zod.z.enum(["BUY", "SELL"]);
|
|
140
140
|
var protectiveOrderPositionSideSchema = import_zod.z.enum(["BOTH", "LONG", "SHORT"]);
|
|
141
141
|
var protectiveOrderSchema = import_zod.z.object({
|
|
142
|
+
/** Helios's record id: what helios_positions_delete_tp_sl takes (the Hyperliquid order id works there too). */
|
|
142
143
|
id: import_zod.z.string(),
|
|
143
|
-
|
|
144
|
-
|
|
144
|
+
/** The Hyperliquid order id (named after the retired Binance field). */
|
|
145
|
+
binanceOrderId: import_zod.z.number().int().nonnegative().nullish(),
|
|
146
|
+
clientOrderId: import_zod.z.string().nullish(),
|
|
145
147
|
symbol: import_zod.z.string(),
|
|
146
148
|
side: protectiveOrderSideSchema,
|
|
147
|
-
positionSide: protectiveOrderPositionSideSchema,
|
|
149
|
+
positionSide: protectiveOrderPositionSideSchema.nullish().transform((value) => value ?? "BOTH"),
|
|
148
150
|
status: import_zod.z.string(),
|
|
149
151
|
kind: protectiveOrderKindSchema,
|
|
150
|
-
groupId: import_zod.z.string(),
|
|
151
|
-
stopPrice: import_zod.z.string().
|
|
152
|
-
parentClientOrderId: import_zod.z.string().
|
|
153
|
-
assetId: import_zod.z.number().int().nonnegative().
|
|
154
|
-
createdAt: import_zod.z.string().
|
|
152
|
+
groupId: import_zod.z.string().nullish(),
|
|
153
|
+
stopPrice: import_zod.z.union([import_zod.z.string(), import_zod.z.number()]).nullish().transform((value) => value == null ? value : String(value)),
|
|
154
|
+
parentClientOrderId: import_zod.z.string().nullish(),
|
|
155
|
+
assetId: import_zod.z.number().int().nonnegative().nullish(),
|
|
156
|
+
createdAt: import_zod.z.string().nullish()
|
|
155
157
|
});
|
|
156
158
|
var hyperliquidPortfolioSnapshotSchema = import_zod.z.object({
|
|
157
159
|
provider: import_zod.z.literal("hyperliquid"),
|
|
@@ -160,6 +162,7 @@ var hyperliquidPortfolioSnapshotSchema = import_zod.z.object({
|
|
|
160
162
|
totalMargin: import_zod.z.number(),
|
|
161
163
|
unrealizedPnl: import_zod.z.number(),
|
|
162
164
|
positions: import_zod.z.array(openPositionSchema),
|
|
165
|
+
/** Unreadable entries are dropped (see readProtectiveOrders) rather than failing the read. */
|
|
163
166
|
protectiveOrders: import_zod.z.array(protectiveOrderSchema)
|
|
164
167
|
});
|
|
165
168
|
var portfolioInputSchema = import_zod.z.object({
|
|
@@ -354,6 +357,8 @@ var closePositionInputSchema = import_zod.z.object({
|
|
|
354
357
|
});
|
|
355
358
|
var closePositionResultSchema = import_zod.z.object({
|
|
356
359
|
status: import_zod.z.literal("submitted"),
|
|
360
|
+
/** `no_position`: nothing was open on this coin, so no order was sent. Absent from older data-bridges. */
|
|
361
|
+
outcome: import_zod.z.enum(["closed", "no_position"]).optional(),
|
|
357
362
|
provider: providerSchema.optional(),
|
|
358
363
|
symbol: import_zod.z.string(),
|
|
359
364
|
mode: import_zod.z.literal("FULL"),
|
|
@@ -544,7 +549,8 @@ var HeliosAgentDataBridgeClient = class {
|
|
|
544
549
|
}
|
|
545
550
|
return portfolioSnapshotSchema.parse({
|
|
546
551
|
...result,
|
|
547
|
-
provider: parsedInput.provider
|
|
552
|
+
provider: parsedInput.provider,
|
|
553
|
+
protectiveOrders: readProtectiveOrders(result.protectiveOrders)
|
|
548
554
|
});
|
|
549
555
|
}
|
|
550
556
|
async getLedgerFills(accessToken, input = {}) {
|
|
@@ -597,7 +603,7 @@ var HeliosAgentDataBridgeClient = class {
|
|
|
597
603
|
}
|
|
598
604
|
async closePosition(accessToken, input) {
|
|
599
605
|
const parsedInput = closePositionInputSchema.parse(input);
|
|
600
|
-
await this.request(
|
|
606
|
+
const payload = await this.request(
|
|
601
607
|
accessToken,
|
|
602
608
|
"positions.close",
|
|
603
609
|
{
|
|
@@ -608,8 +614,10 @@ var HeliosAgentDataBridgeClient = class {
|
|
|
608
614
|
},
|
|
609
615
|
"POST"
|
|
610
616
|
);
|
|
617
|
+
const outcome = this.tryUnwrapResult(payload)?.outcome;
|
|
611
618
|
return closePositionResultSchema.parse({
|
|
612
619
|
status: "submitted",
|
|
620
|
+
...outcome === "closed" || outcome === "no_position" ? { outcome } : {},
|
|
613
621
|
provider: parsedInput.provider,
|
|
614
622
|
symbol: parsedInput.symbol,
|
|
615
623
|
mode: "FULL",
|
|
@@ -707,6 +715,14 @@ var HeliosAgentDataBridgeClient = class {
|
|
|
707
715
|
});
|
|
708
716
|
}
|
|
709
717
|
}
|
|
718
|
+
/** The result of a mutation older data-bridges answer with nothing; null when there is none. */
|
|
719
|
+
tryUnwrapResult(payload) {
|
|
720
|
+
try {
|
|
721
|
+
return this.unwrapResult(payload) ?? null;
|
|
722
|
+
} catch {
|
|
723
|
+
return null;
|
|
724
|
+
}
|
|
725
|
+
}
|
|
710
726
|
unwrapResult(payload) {
|
|
711
727
|
if (!payload || typeof payload !== "object") {
|
|
712
728
|
throw new HeliosAgentApiError({
|
|
@@ -767,6 +783,13 @@ var HeliosAgentDataBridgeClient = class {
|
|
|
767
783
|
return envelope;
|
|
768
784
|
}
|
|
769
785
|
};
|
|
786
|
+
function readProtectiveOrders(value) {
|
|
787
|
+
if (!Array.isArray(value)) return [];
|
|
788
|
+
return value.flatMap((entry) => {
|
|
789
|
+
const parsed = protectiveOrderSchema.safeParse(entry);
|
|
790
|
+
return parsed.success ? [parsed.data] : [];
|
|
791
|
+
});
|
|
792
|
+
}
|
|
770
793
|
var DEFAULT_AGENT_REFRESH_WINDOW_MS = 60 * 1e3;
|
|
771
794
|
var agentConnectionStatusSchema = import_zod3.z.enum([
|
|
772
795
|
"disconnected",
|
|
@@ -1220,6 +1243,9 @@ var HeliosAgentMcpDocsService = class {
|
|
|
1220
1243
|
}
|
|
1221
1244
|
async getDocument(input) {
|
|
1222
1245
|
const documentPath = resolveDocumentPath(this.docsRoot, input.path);
|
|
1246
|
+
if (!(0, import_node_fs.existsSync)(documentPath) || !(0, import_node_fs.statSync)(documentPath).isFile()) {
|
|
1247
|
+
throw new Error(`No document "${input.path}". helios_docs_get_index lists the documents.`);
|
|
1248
|
+
}
|
|
1223
1249
|
const body = (0, import_node_fs.readFileSync)(documentPath, "utf8");
|
|
1224
1250
|
const stats = (0, import_node_fs.statSync)(documentPath);
|
|
1225
1251
|
const relativePath = toPosixPath(import_node_path.default.relative(this.docsRoot, documentPath));
|
|
@@ -2522,7 +2548,7 @@ function createHeliosAccountToolDefinitions(service) {
|
|
|
2522
2548
|
{
|
|
2523
2549
|
name: "helios_portfolio_get",
|
|
2524
2550
|
title: "Get Helios Portfolio",
|
|
2525
|
-
description: "Returns
|
|
2551
|
+
description: "Returns balances, open positions and their TP/SL (protectiveOrders, each with the id helios_positions_delete_tp_sl takes). Provider may be omitted if one is already pinned with helios_provider_set_active.",
|
|
2526
2552
|
inputSchema: providerSelectionInputSchema,
|
|
2527
2553
|
async execute(input) {
|
|
2528
2554
|
const result = portfolioToolOutputSchema.parse(await service.getPortfolio(input));
|
|
@@ -2759,7 +2785,7 @@ function createHeliosTradingToolDefinitions(service) {
|
|
|
2759
2785
|
content: [
|
|
2760
2786
|
{
|
|
2761
2787
|
type: "text",
|
|
2762
|
-
text: result.status
|
|
2788
|
+
text: result.status !== "connected" ? result.message : result.closure.outcome === "no_position" ? `No open ${result.closure.symbol} position: nothing was closed and no order was sent.` : `Sent a market order closing the full ${result.closure.provider ?? input.provider ?? "hyperliquid"} ${result.closure.symbol} position. Check helios_positions_get_open to confirm.`
|
|
2763
2789
|
}
|
|
2764
2790
|
],
|
|
2765
2791
|
structuredContent: result.status === "connected" ? result : {
|
|
@@ -2793,7 +2819,7 @@ function createHeliosTradingToolDefinitions(service) {
|
|
|
2793
2819
|
{
|
|
2794
2820
|
name: "helios_positions_delete_tp_sl",
|
|
2795
2821
|
title: "Delete Helios TP/SL",
|
|
2796
|
-
description: "Deletes
|
|
2822
|
+
description: "Deletes a take-profit or stop-loss. orderId is the id from helios_portfolio_get protectiveOrders, or the Hyperliquid order id of the TP/SL. Provider may be omitted if one is already pinned with helios_provider_set_active.",
|
|
2797
2823
|
inputSchema: deleteTpSlInputSchema,
|
|
2798
2824
|
async execute(input) {
|
|
2799
2825
|
const result = deleteTpSlToolOutputSchema.parse(await service.deleteTpSl(input));
|
|
@@ -2886,7 +2912,7 @@ async function createHeliosAgentMcpServer(options) {
|
|
|
2886
2912
|
const { McpServer } = await import("@modelcontextprotocol/sdk/server/mcp.js");
|
|
2887
2913
|
const server = new McpServer({
|
|
2888
2914
|
name: "helios",
|
|
2889
|
-
version: "0.2.
|
|
2915
|
+
version: "0.2.9"
|
|
2890
2916
|
});
|
|
2891
2917
|
const sessionStore = options.sessionStore ?? new FileAgentSessionStore(options.sessionPath ?? getDefaultHeliosAgentMcpSessionPath());
|
|
2892
2918
|
const client = new HeliosAgentAuthClient({
|
package/dist/cli.mjs
CHANGED
package/dist/index.d.mts
CHANGED
|
@@ -94,28 +94,28 @@ declare const portfolioSnapshotSchema: z.ZodObject<{
|
|
|
94
94
|
}, z.core.$strip>>;
|
|
95
95
|
protectiveOrders: z.ZodArray<z.ZodObject<{
|
|
96
96
|
id: z.ZodString;
|
|
97
|
-
binanceOrderId: z.ZodOptional<z.ZodNumber
|
|
98
|
-
clientOrderId: z.ZodOptional<z.ZodString
|
|
97
|
+
binanceOrderId: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
98
|
+
clientOrderId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
99
99
|
symbol: z.ZodString;
|
|
100
100
|
side: z.ZodEnum<{
|
|
101
101
|
BUY: "BUY";
|
|
102
102
|
SELL: "SELL";
|
|
103
103
|
}>;
|
|
104
|
-
positionSide: z.ZodEnum<{
|
|
104
|
+
positionSide: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
105
105
|
LONG: "LONG";
|
|
106
106
|
SHORT: "SHORT";
|
|
107
107
|
BOTH: "BOTH";
|
|
108
|
-
}
|
|
108
|
+
}>>>, z.ZodTransform<"LONG" | "SHORT" | "BOTH", "LONG" | "SHORT" | "BOTH" | null | undefined>>;
|
|
109
109
|
status: z.ZodString;
|
|
110
110
|
kind: z.ZodEnum<{
|
|
111
111
|
STOP_LOSS: "STOP_LOSS";
|
|
112
112
|
TAKE_PROFIT: "TAKE_PROFIT";
|
|
113
113
|
}>;
|
|
114
|
-
groupId: z.ZodString
|
|
115
|
-
stopPrice: z.ZodOptional<z.ZodString
|
|
116
|
-
parentClientOrderId: z.ZodOptional<z.ZodString
|
|
117
|
-
assetId: z.ZodOptional<z.ZodNumber
|
|
118
|
-
createdAt: z.ZodString
|
|
114
|
+
groupId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
115
|
+
stopPrice: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>>, z.ZodTransform<string | null | undefined, string | number | null | undefined>>;
|
|
116
|
+
parentClientOrderId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
117
|
+
assetId: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
118
|
+
createdAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
119
119
|
}, z.core.$strip>>;
|
|
120
120
|
}, z.core.$strip>;
|
|
121
121
|
declare const ledgerFillsInputSchema: z.ZodObject<{
|
|
@@ -440,6 +440,10 @@ declare const closePositionInputSchema: z.ZodObject<{
|
|
|
440
440
|
}, z.core.$strip>;
|
|
441
441
|
declare const closePositionResultSchema: z.ZodObject<{
|
|
442
442
|
status: z.ZodLiteral<"submitted">;
|
|
443
|
+
outcome: z.ZodOptional<z.ZodEnum<{
|
|
444
|
+
closed: "closed";
|
|
445
|
+
no_position: "no_position";
|
|
446
|
+
}>>;
|
|
443
447
|
provider: z.ZodOptional<z.ZodEnum<{
|
|
444
448
|
hyperliquid: "hyperliquid";
|
|
445
449
|
}>>;
|
|
@@ -606,6 +610,8 @@ declare class HeliosAgentDataBridgeClient {
|
|
|
606
610
|
private request;
|
|
607
611
|
private buildProcedureUrl;
|
|
608
612
|
private parseJson;
|
|
613
|
+
/** The result of a mutation older data-bridges answer with nothing; null when there is none. */
|
|
614
|
+
private tryUnwrapResult;
|
|
609
615
|
private unwrapResult;
|
|
610
616
|
private extractErrorCode;
|
|
611
617
|
private extractErrorMessage;
|
package/dist/index.d.ts
CHANGED
|
@@ -94,28 +94,28 @@ declare const portfolioSnapshotSchema: z.ZodObject<{
|
|
|
94
94
|
}, z.core.$strip>>;
|
|
95
95
|
protectiveOrders: z.ZodArray<z.ZodObject<{
|
|
96
96
|
id: z.ZodString;
|
|
97
|
-
binanceOrderId: z.ZodOptional<z.ZodNumber
|
|
98
|
-
clientOrderId: z.ZodOptional<z.ZodString
|
|
97
|
+
binanceOrderId: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
98
|
+
clientOrderId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
99
99
|
symbol: z.ZodString;
|
|
100
100
|
side: z.ZodEnum<{
|
|
101
101
|
BUY: "BUY";
|
|
102
102
|
SELL: "SELL";
|
|
103
103
|
}>;
|
|
104
|
-
positionSide: z.ZodEnum<{
|
|
104
|
+
positionSide: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
105
105
|
LONG: "LONG";
|
|
106
106
|
SHORT: "SHORT";
|
|
107
107
|
BOTH: "BOTH";
|
|
108
|
-
}
|
|
108
|
+
}>>>, z.ZodTransform<"LONG" | "SHORT" | "BOTH", "LONG" | "SHORT" | "BOTH" | null | undefined>>;
|
|
109
109
|
status: z.ZodString;
|
|
110
110
|
kind: z.ZodEnum<{
|
|
111
111
|
STOP_LOSS: "STOP_LOSS";
|
|
112
112
|
TAKE_PROFIT: "TAKE_PROFIT";
|
|
113
113
|
}>;
|
|
114
|
-
groupId: z.ZodString
|
|
115
|
-
stopPrice: z.ZodOptional<z.ZodString
|
|
116
|
-
parentClientOrderId: z.ZodOptional<z.ZodString
|
|
117
|
-
assetId: z.ZodOptional<z.ZodNumber
|
|
118
|
-
createdAt: z.ZodString
|
|
114
|
+
groupId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
115
|
+
stopPrice: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>>, z.ZodTransform<string | null | undefined, string | number | null | undefined>>;
|
|
116
|
+
parentClientOrderId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
117
|
+
assetId: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
118
|
+
createdAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
119
119
|
}, z.core.$strip>>;
|
|
120
120
|
}, z.core.$strip>;
|
|
121
121
|
declare const ledgerFillsInputSchema: z.ZodObject<{
|
|
@@ -440,6 +440,10 @@ declare const closePositionInputSchema: z.ZodObject<{
|
|
|
440
440
|
}, z.core.$strip>;
|
|
441
441
|
declare const closePositionResultSchema: z.ZodObject<{
|
|
442
442
|
status: z.ZodLiteral<"submitted">;
|
|
443
|
+
outcome: z.ZodOptional<z.ZodEnum<{
|
|
444
|
+
closed: "closed";
|
|
445
|
+
no_position: "no_position";
|
|
446
|
+
}>>;
|
|
443
447
|
provider: z.ZodOptional<z.ZodEnum<{
|
|
444
448
|
hyperliquid: "hyperliquid";
|
|
445
449
|
}>>;
|
|
@@ -606,6 +610,8 @@ declare class HeliosAgentDataBridgeClient {
|
|
|
606
610
|
private request;
|
|
607
611
|
private buildProcedureUrl;
|
|
608
612
|
private parseJson;
|
|
613
|
+
/** The result of a mutation older data-bridges answer with nothing; null when there is none. */
|
|
614
|
+
private tryUnwrapResult;
|
|
609
615
|
private unwrapResult;
|
|
610
616
|
private extractErrorCode;
|
|
611
617
|
private extractErrorMessage;
|
package/dist/index.js
CHANGED
|
@@ -179,19 +179,21 @@ var protectiveOrderKindSchema = import_zod.z.enum(["STOP_LOSS", "TAKE_PROFIT"]);
|
|
|
179
179
|
var protectiveOrderSideSchema = import_zod.z.enum(["BUY", "SELL"]);
|
|
180
180
|
var protectiveOrderPositionSideSchema = import_zod.z.enum(["BOTH", "LONG", "SHORT"]);
|
|
181
181
|
var protectiveOrderSchema = import_zod.z.object({
|
|
182
|
+
/** Helios's record id: what helios_positions_delete_tp_sl takes (the Hyperliquid order id works there too). */
|
|
182
183
|
id: import_zod.z.string(),
|
|
183
|
-
|
|
184
|
-
|
|
184
|
+
/** The Hyperliquid order id (named after the retired Binance field). */
|
|
185
|
+
binanceOrderId: import_zod.z.number().int().nonnegative().nullish(),
|
|
186
|
+
clientOrderId: import_zod.z.string().nullish(),
|
|
185
187
|
symbol: import_zod.z.string(),
|
|
186
188
|
side: protectiveOrderSideSchema,
|
|
187
|
-
positionSide: protectiveOrderPositionSideSchema,
|
|
189
|
+
positionSide: protectiveOrderPositionSideSchema.nullish().transform((value) => value ?? "BOTH"),
|
|
188
190
|
status: import_zod.z.string(),
|
|
189
191
|
kind: protectiveOrderKindSchema,
|
|
190
|
-
groupId: import_zod.z.string(),
|
|
191
|
-
stopPrice: import_zod.z.string().
|
|
192
|
-
parentClientOrderId: import_zod.z.string().
|
|
193
|
-
assetId: import_zod.z.number().int().nonnegative().
|
|
194
|
-
createdAt: import_zod.z.string().
|
|
192
|
+
groupId: import_zod.z.string().nullish(),
|
|
193
|
+
stopPrice: import_zod.z.union([import_zod.z.string(), import_zod.z.number()]).nullish().transform((value) => value == null ? value : String(value)),
|
|
194
|
+
parentClientOrderId: import_zod.z.string().nullish(),
|
|
195
|
+
assetId: import_zod.z.number().int().nonnegative().nullish(),
|
|
196
|
+
createdAt: import_zod.z.string().nullish()
|
|
195
197
|
});
|
|
196
198
|
var hyperliquidPortfolioSnapshotSchema = import_zod.z.object({
|
|
197
199
|
provider: import_zod.z.literal("hyperliquid"),
|
|
@@ -200,6 +202,7 @@ var hyperliquidPortfolioSnapshotSchema = import_zod.z.object({
|
|
|
200
202
|
totalMargin: import_zod.z.number(),
|
|
201
203
|
unrealizedPnl: import_zod.z.number(),
|
|
202
204
|
positions: import_zod.z.array(openPositionSchema),
|
|
205
|
+
/** Unreadable entries are dropped (see readProtectiveOrders) rather than failing the read. */
|
|
203
206
|
protectiveOrders: import_zod.z.array(protectiveOrderSchema)
|
|
204
207
|
});
|
|
205
208
|
var portfolioInputSchema = import_zod.z.object({
|
|
@@ -394,6 +397,8 @@ var closePositionInputSchema = import_zod.z.object({
|
|
|
394
397
|
});
|
|
395
398
|
var closePositionResultSchema = import_zod.z.object({
|
|
396
399
|
status: import_zod.z.literal("submitted"),
|
|
400
|
+
/** `no_position`: nothing was open on this coin, so no order was sent. Absent from older data-bridges. */
|
|
401
|
+
outcome: import_zod.z.enum(["closed", "no_position"]).optional(),
|
|
397
402
|
provider: providerSchema.optional(),
|
|
398
403
|
symbol: import_zod.z.string(),
|
|
399
404
|
mode: import_zod.z.literal("FULL"),
|
|
@@ -584,7 +589,8 @@ var HeliosAgentDataBridgeClient = class {
|
|
|
584
589
|
}
|
|
585
590
|
return portfolioSnapshotSchema.parse({
|
|
586
591
|
...result,
|
|
587
|
-
provider: parsedInput.provider
|
|
592
|
+
provider: parsedInput.provider,
|
|
593
|
+
protectiveOrders: readProtectiveOrders(result.protectiveOrders)
|
|
588
594
|
});
|
|
589
595
|
}
|
|
590
596
|
async getLedgerFills(accessToken, input = {}) {
|
|
@@ -637,7 +643,7 @@ var HeliosAgentDataBridgeClient = class {
|
|
|
637
643
|
}
|
|
638
644
|
async closePosition(accessToken, input) {
|
|
639
645
|
const parsedInput = closePositionInputSchema.parse(input);
|
|
640
|
-
await this.request(
|
|
646
|
+
const payload = await this.request(
|
|
641
647
|
accessToken,
|
|
642
648
|
"positions.close",
|
|
643
649
|
{
|
|
@@ -648,8 +654,10 @@ var HeliosAgentDataBridgeClient = class {
|
|
|
648
654
|
},
|
|
649
655
|
"POST"
|
|
650
656
|
);
|
|
657
|
+
const outcome = this.tryUnwrapResult(payload)?.outcome;
|
|
651
658
|
return closePositionResultSchema.parse({
|
|
652
659
|
status: "submitted",
|
|
660
|
+
...outcome === "closed" || outcome === "no_position" ? { outcome } : {},
|
|
653
661
|
provider: parsedInput.provider,
|
|
654
662
|
symbol: parsedInput.symbol,
|
|
655
663
|
mode: "FULL",
|
|
@@ -747,6 +755,14 @@ var HeliosAgentDataBridgeClient = class {
|
|
|
747
755
|
});
|
|
748
756
|
}
|
|
749
757
|
}
|
|
758
|
+
/** The result of a mutation older data-bridges answer with nothing; null when there is none. */
|
|
759
|
+
tryUnwrapResult(payload) {
|
|
760
|
+
try {
|
|
761
|
+
return this.unwrapResult(payload) ?? null;
|
|
762
|
+
} catch {
|
|
763
|
+
return null;
|
|
764
|
+
}
|
|
765
|
+
}
|
|
750
766
|
unwrapResult(payload) {
|
|
751
767
|
if (!payload || typeof payload !== "object") {
|
|
752
768
|
throw new HeliosAgentApiError({
|
|
@@ -807,6 +823,13 @@ var HeliosAgentDataBridgeClient = class {
|
|
|
807
823
|
return envelope;
|
|
808
824
|
}
|
|
809
825
|
};
|
|
826
|
+
function readProtectiveOrders(value) {
|
|
827
|
+
if (!Array.isArray(value)) return [];
|
|
828
|
+
return value.flatMap((entry) => {
|
|
829
|
+
const parsed = protectiveOrderSchema.safeParse(entry);
|
|
830
|
+
return parsed.success ? [parsed.data] : [];
|
|
831
|
+
});
|
|
832
|
+
}
|
|
810
833
|
var DEFAULT_AGENT_REFRESH_WINDOW_MS = 60 * 1e3;
|
|
811
834
|
var agentConnectionStatusSchema = import_zod3.z.enum([
|
|
812
835
|
"disconnected",
|
|
@@ -1260,6 +1283,9 @@ var HeliosAgentMcpDocsService = class {
|
|
|
1260
1283
|
}
|
|
1261
1284
|
async getDocument(input) {
|
|
1262
1285
|
const documentPath = resolveDocumentPath(this.docsRoot, input.path);
|
|
1286
|
+
if (!(0, import_node_fs.existsSync)(documentPath) || !(0, import_node_fs.statSync)(documentPath).isFile()) {
|
|
1287
|
+
throw new Error(`No document "${input.path}". helios_docs_get_index lists the documents.`);
|
|
1288
|
+
}
|
|
1263
1289
|
const body = (0, import_node_fs.readFileSync)(documentPath, "utf8");
|
|
1264
1290
|
const stats = (0, import_node_fs.statSync)(documentPath);
|
|
1265
1291
|
const relativePath = toPosixPath(import_node_path.default.relative(this.docsRoot, documentPath));
|
|
@@ -2596,7 +2622,7 @@ function createHeliosAccountToolDefinitions(service) {
|
|
|
2596
2622
|
{
|
|
2597
2623
|
name: "helios_portfolio_get",
|
|
2598
2624
|
title: "Get Helios Portfolio",
|
|
2599
|
-
description: "Returns
|
|
2625
|
+
description: "Returns balances, open positions and their TP/SL (protectiveOrders, each with the id helios_positions_delete_tp_sl takes). Provider may be omitted if one is already pinned with helios_provider_set_active.",
|
|
2600
2626
|
inputSchema: providerSelectionInputSchema,
|
|
2601
2627
|
async execute(input) {
|
|
2602
2628
|
const result = portfolioToolOutputSchema.parse(await service.getPortfolio(input));
|
|
@@ -2833,7 +2859,7 @@ function createHeliosTradingToolDefinitions(service) {
|
|
|
2833
2859
|
content: [
|
|
2834
2860
|
{
|
|
2835
2861
|
type: "text",
|
|
2836
|
-
text: result.status
|
|
2862
|
+
text: result.status !== "connected" ? result.message : result.closure.outcome === "no_position" ? `No open ${result.closure.symbol} position: nothing was closed and no order was sent.` : `Sent a market order closing the full ${result.closure.provider ?? input.provider ?? "hyperliquid"} ${result.closure.symbol} position. Check helios_positions_get_open to confirm.`
|
|
2837
2863
|
}
|
|
2838
2864
|
],
|
|
2839
2865
|
structuredContent: result.status === "connected" ? result : {
|
|
@@ -2867,7 +2893,7 @@ function createHeliosTradingToolDefinitions(service) {
|
|
|
2867
2893
|
{
|
|
2868
2894
|
name: "helios_positions_delete_tp_sl",
|
|
2869
2895
|
title: "Delete Helios TP/SL",
|
|
2870
|
-
description: "Deletes
|
|
2896
|
+
description: "Deletes a take-profit or stop-loss. orderId is the id from helios_portfolio_get protectiveOrders, or the Hyperliquid order id of the TP/SL. Provider may be omitted if one is already pinned with helios_provider_set_active.",
|
|
2871
2897
|
inputSchema: deleteTpSlInputSchema,
|
|
2872
2898
|
async execute(input) {
|
|
2873
2899
|
const result = deleteTpSlToolOutputSchema.parse(await service.deleteTpSl(input));
|
|
@@ -2960,7 +2986,7 @@ async function createHeliosAgentMcpServer(options) {
|
|
|
2960
2986
|
const { McpServer } = await import("@modelcontextprotocol/sdk/server/mcp.js");
|
|
2961
2987
|
const server = new McpServer({
|
|
2962
2988
|
name: "helios",
|
|
2963
|
-
version: "0.2.
|
|
2989
|
+
version: "0.2.9"
|
|
2964
2990
|
});
|
|
2965
2991
|
const sessionStore = options.sessionStore ?? new FileAgentSessionStore(options.sessionPath ?? getDefaultHeliosAgentMcpSessionPath());
|
|
2966
2992
|
const client = new HeliosAgentAuthClient({
|
package/dist/index.mjs
CHANGED
|
@@ -71,4 +71,6 @@ WHAT HAS HELD UP IN BACKTESTS (out of sample, last 2 years)
|
|
|
71
71
|
- Buying a sharp turn up (hmiv > 0, r15m and r1h turning positive) in a coin whose
|
|
72
72
|
reg is BREAKDOWN or CRASH, especially when the whole market is down (os high, Mti < 0).
|
|
73
73
|
- Fading stretched moves beat chasing them.
|
|
74
|
-
- Shorts did not hold up. Edges are small
|
|
74
|
+
- Shorts did not hold up. Edges are small: about +0.1% a trade after a 0.38% round-trip cost,
|
|
75
|
+
on holds of 1-3 days. Frequent in-and-out trading pays fees without that edge.
|
|
76
|
+
Size small, always use a stop.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pgnio/helios-mcp",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.9",
|
|
4
4
|
"description": "Helios MCP server: connect an AI agent to your Helios account to read markets and your portfolio and to trade on Hyperliquid. Most apps can use the hosted URL https://helios.pgn.io/mcp instead.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"homepage": "https://helios.pgn.io/?connect=ai",
|