@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/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
- binanceOrderId: import_zod.z.number().int().nonnegative().optional(),
144
- clientOrderId: import_zod.z.string().optional(),
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().optional(),
152
- parentClientOrderId: import_zod.z.string().optional(),
153
- assetId: import_zod.z.number().int().nonnegative().optional(),
154
- createdAt: import_zod.z.string().datetime()
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 a provider-specific portfolio snapshot. Provider may be omitted if one is already pinned with helios_provider_set_active.",
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 === "connected" ? `Submitted Helios full close for ${result.closure.provider ?? input.provider} ${result.closure.symbol}.` : result.message
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 an existing Helios take-profit or stop-loss order by order id. Provider may be omitted if one is already pinned with helios_provider_set_active.",
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.8"
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
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  createHeliosAgentMcpServer
4
- } from "./chunk-UHFLF3UG.mjs";
4
+ } from "./chunk-7TMDGB6C.mjs";
5
5
 
6
6
  // src/cli.ts
7
7
  async function main() {
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
- binanceOrderId: import_zod.z.number().int().nonnegative().optional(),
184
- clientOrderId: import_zod.z.string().optional(),
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().optional(),
192
- parentClientOrderId: import_zod.z.string().optional(),
193
- assetId: import_zod.z.number().int().nonnegative().optional(),
194
- createdAt: import_zod.z.string().datetime()
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 a provider-specific portfolio snapshot. Provider may be omitted if one is already pinned with helios_provider_set_active.",
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 === "connected" ? `Submitted Helios full close for ${result.closure.provider ?? input.provider} ${result.closure.symbol}.` : result.message
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 an existing Helios take-profit or stop-loss order by order id. Provider may be omitted if one is already pinned with helios_provider_set_active.",
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.8"
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
@@ -29,7 +29,7 @@ import {
29
29
  topOfSnapshot,
30
30
  withDataText,
31
31
  withSnapshotDefaults
32
- } from "./chunk-UHFLF3UG.mjs";
32
+ } from "./chunk-7TMDGB6C.mjs";
33
33
  export {
34
34
  DEFAULT_SNAPSHOT_FIELDS,
35
35
  DEFAULT_SNAPSHOT_TOP,
@@ -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 (about +0.1% a trade): size small, always use a stop.
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.8",
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",