flash-trade-mcp 0.3.5 → 0.4.0

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 (2) hide show
  1. package/dist/index.js +214 -19
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -49236,7 +49236,7 @@ class FlashApiClient {
49236
49236
  // src/tools/health.ts
49237
49237
  function registerHealthTools(server, client) {
49238
49238
  server.registerTool("health_check", {
49239
- description: "Check if the Flash Trade API is running and responsive. Returns account counts and service status. Call this first to verify connectivity before using other tools."
49239
+ description: "Verify Flash Trade API connectivity and status. Call this first before any other tool. Returns service status and account counts."
49240
49240
  }, async () => {
49241
49241
  const health = await client.getHealth();
49242
49242
  const lines = [`Status: ${health.status}`];
@@ -49250,7 +49250,7 @@ function registerHealthTools(server, client) {
49250
49250
  });
49251
49251
  }
49252
49252
 
49253
- // src/tools/markets.ts
49253
+ // src/tools/shared/custody-map.ts
49254
49254
  var VIRTUAL_CUSTODY_MAP = {
49255
49255
  "6bthDsp8pcGBGKVKCKZjV5JfuSUNRo62RG4hQHj1u4CK": { symbol: "BNB", pool: "Crypto.1", maxLeverage: "60.00" },
49256
49256
  A8SKWb3pwbFUtxLQhnpUTfy7CkxBpWGvTLYyJyWHCMWv: { symbol: "PYTH", pool: "Governance.1", maxLeverage: "60.00" },
@@ -49270,6 +49270,13 @@ var VIRTUAL_CUSTODY_MAP = {
49270
49270
  RQNURQjDbq2Yah2udtFTNT7TjR15vsPV3oJNnwYher8: { symbol: "TSLA", pool: "Equity.1", maxLeverage: "12.00" },
49271
49271
  ArnD1faZVVkkewX4HUSoDuht46egAtVvhDTFMJn3DkFo: { symbol: "SAMO", pool: "Community.3", maxLeverage: "50.00" }
49272
49272
  };
49273
+ function formatPriceUsd(data) {
49274
+ const price = parseFloat(data.price);
49275
+ const exp = parseFloat(data.exponent);
49276
+ if (isNaN(price) || isNaN(exp))
49277
+ return "?";
49278
+ return (price * Math.pow(10, exp)).toFixed(2);
49279
+ }
49273
49280
  function buildCustodySymbolMap(poolData) {
49274
49281
  const map3 = new Map;
49275
49282
  for (const pool of poolData.pools) {
@@ -49288,6 +49295,8 @@ function buildCustodySymbolMap(poolData) {
49288
49295
  }
49289
49296
  return map3;
49290
49297
  }
49298
+
49299
+ // src/tools/markets.ts
49291
49300
  function formatMarketsSummary(markets, custodyInfo) {
49292
49301
  const lines = [
49293
49302
  `${markets.length} markets available:
@@ -49317,7 +49326,7 @@ Use get_market with a pubkey for full details. Use get_prices for current oracle
49317
49326
  }
49318
49327
  function registerMarketTools(server, client) {
49319
49328
  server.registerTool("get_markets", {
49320
- description: "List all available perpetual futures markets on Flash Trade. Returns a compact summary table with symbol, side (Long/Short), pool, max leverage, and market pubkey. For full details on a specific market, use get_market with the pubkey."
49329
+ description: "List all available perpetual futures markets. Returns a summary table with symbol, side, pool, max leverage, and pubkey. For a trading-ready view with prices, use get_trading_overview instead."
49321
49330
  }, async () => {
49322
49331
  const [markets, poolData] = await Promise.all([
49323
49332
  client.getMarkets(),
@@ -49370,10 +49379,26 @@ Use get_pool with a pubkey for full details. Use get_pool_data for AUM and utili
49370
49379
  // src/tools/custodies.ts
49371
49380
  function registerCustodyTools(server, client) {
49372
49381
  server.registerTool("get_custodies", {
49373
- description: "List all custody accounts. Custodies hold the actual tokens for each asset in a pool (e.g., the USDC custody, the SOL custody). Returns custody pubkeys, token info, and utilization metrics."
49382
+ description: "List all custody accounts (token vaults) across pools. Returns a compact summary with symbol, mint, and pubkey. Use get_custody with a specific pubkey for full details (utilization, fees, limits)."
49374
49383
  }, async () => {
49375
49384
  const custodies = await client.getCustodies();
49376
- return { content: [{ type: "text", text: JSON.stringify(custodies, null, 2) }] };
49385
+ const lines = [
49386
+ `${custodies.length} custody accounts:
49387
+ `,
49388
+ "Symbol | Mint | Pubkey",
49389
+ "-----------|----------------------------------------------|----------------------------------------------"
49390
+ ];
49391
+ for (const c of custodies) {
49392
+ const acct = c.account ?? {};
49393
+ const mintObj = typeof acct.mint === "object" ? acct.mint : null;
49394
+ const symbol2 = (acct.symbol ?? mintObj?.symbol ?? "?").toString().padEnd(10);
49395
+ const mint = (mintObj?.key ?? (typeof acct.mint === "string" ? acct.mint : "?")).toString().slice(0, 44).padEnd(44);
49396
+ lines.push(`${symbol2} | ${mint} | ${c.pubkey}`);
49397
+ }
49398
+ lines.push(`
49399
+ Use get_custody with a pubkey for full details (utilization, fees, limits).`);
49400
+ return { content: [{ type: "text", text: lines.join(`
49401
+ `) }] };
49377
49402
  });
49378
49403
  server.registerTool("get_custody", {
49379
49404
  description: "Get detailed custody information for a specific custody account. Includes utilization, fees, and limits.",
@@ -49434,7 +49459,7 @@ function formatEnrichedPosition(p) {
49434
49459
  }
49435
49460
  function registerPositionTools(server, client) {
49436
49461
  server.registerTool("get_positions", {
49437
- description: "List perpetual positions, optionally filtered by wallet owner. Without an owner filter, returns ALL open positions (may be large). With owner, returns enriched positions with computed PnL, leverage, and liquidation price.",
49462
+ description: "List open perpetual positions. Without owner: returns all positions (large response). With owner: returns enriched positions with live PnL, leverage, and liquidation price. For a complete wallet overview, use get_account_summary instead.",
49438
49463
  inputSchema: {
49439
49464
  owner: exports_external.string().regex(/^[1-9A-HJ-NP-Za-km-z]{32,44}$/).optional().describe("Wallet pubkey to filter by. When provided, returns enriched positions with PnL, leverage, and liquidation price.")
49440
49465
  }
@@ -49455,7 +49480,7 @@ ${text}` }] };
49455
49480
  return { content: [{ type: "text", text: JSON.stringify(positions, null, 2) }] };
49456
49481
  });
49457
49482
  server.registerTool("get_position", {
49458
- description: "Get a single position by its on-chain account pubkey. Returns raw position data. For enriched data (PnL, leverage, liq price), use get_positions with the owner filter instead.",
49483
+ description: "Get a single position by its on-chain pubkey. Returns raw position data. For enriched data with PnL and leverage, use get_positions with owner or get_account_summary.",
49459
49484
  inputSchema: { pubkey: exports_external.string().regex(/^[1-9A-HJ-NP-Za-km-z]{32,44}$/).describe("Position account pubkey") }
49460
49485
  }, async ({ pubkey }) => {
49461
49486
  const position = await client.getPosition(pubkey);
@@ -49480,7 +49505,7 @@ function formatEnrichedOrder(o) {
49480
49505
  }
49481
49506
  function registerOrderTools(server, client) {
49482
49507
  server.registerTool("get_orders", {
49483
- description: "List open orders (limit orders, take-profit, stop-loss), optionally filtered by wallet owner. When owner is provided, returns enriched order data with computed trigger prices and sizes.",
49508
+ description: "List pending orders (limit, take-profit, stop-loss). With owner: returns enriched orders with computed trigger prices and sizes. Needed to find order_id (0-7) for edit_trigger_order or cancel_trigger_order.",
49484
49509
  inputSchema: {
49485
49510
  owner: exports_external.string().regex(/^[1-9A-HJ-NP-Za-km-z]{32,44}$/).optional().describe("Wallet pubkey to filter by. When provided, returns enriched orders.")
49486
49511
  }
@@ -49555,6 +49580,165 @@ function sanitizeError(e) {
49555
49580
  return msg.replace(/\[[\d,\s]{20,}\]/g, "[REDACTED]").replace(/[0-9a-fA-F]{40,}/g, "[REDACTED]").replace(/[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{40,}/g, "[REDACTED]").replace(/[A-Za-z0-9+/]{40,}={0,2}/g, "[REDACTED]");
49556
49581
  }
49557
49582
 
49583
+ // src/tools/account-summary.ts
49584
+ function registerAccountSummaryTool(server, client) {
49585
+ server.registerTool("get_account_summary", {
49586
+ description: "Get a complete wallet overview: all open positions (with PnL), all pending orders (limit/TP/SL), and current prices for held markets. " + "Recommended first call when managing a specific wallet — replaces calling get_positions + get_orders + get_prices separately.",
49587
+ inputSchema: {
49588
+ owner: exports_external.string().regex(/^[1-9A-HJ-NP-Za-km-z]{32,44}$/).describe("Wallet pubkey")
49589
+ }
49590
+ }, async ({ owner }) => {
49591
+ const [posResult, ordResult, priceResult] = await Promise.allSettled([
49592
+ client.getOwnerPositions(owner),
49593
+ client.getOwnerOrders(owner),
49594
+ client.getPrices()
49595
+ ]);
49596
+ const positions = posResult.status === "fulfilled" ? posResult.value : null;
49597
+ const orders = ordResult.status === "fulfilled" ? ordResult.value : null;
49598
+ const prices = priceResult.status === "fulfilled" ? priceResult.value : null;
49599
+ const lines = [`=== Account Summary for ${owner} ===
49600
+ `];
49601
+ const warnings = [];
49602
+ if (!positions)
49603
+ warnings.push(`Positions unavailable: ${sanitizeError(posResult.reason)}`);
49604
+ if (!orders)
49605
+ warnings.push(`Orders unavailable: ${sanitizeError(ordResult.reason)}`);
49606
+ if (!prices)
49607
+ warnings.push(`Prices unavailable: ${sanitizeError(priceResult.reason)}`);
49608
+ if (!positions) {
49609
+ lines.push(`Positions: unavailable
49610
+ `);
49611
+ } else if (positions.length === 0) {
49612
+ lines.push(`Positions: None
49613
+ `);
49614
+ } else {
49615
+ lines.push(`── ${positions.length} Position(s) ──`);
49616
+ for (const p of positions) {
49617
+ const pnl = p.pnlWithFeeUsdUi ? ` | PnL: $${p.pnlWithFeeUsdUi} (${p.pnlPercentageWithFee}%)` : "";
49618
+ lines.push(` ${p.sideUi} ${p.marketSymbol}: $${p.sizeUsdUi} @ $${p.entryPriceUi} (${p.leverageUi}x)${pnl}`);
49619
+ lines.push(` Key: ${p.key} | Liq: $${p.liquidationPriceUi}`);
49620
+ }
49621
+ lines.push("");
49622
+ }
49623
+ if (!orders) {
49624
+ lines.push(`Orders: unavailable
49625
+ `);
49626
+ } else if (orders.length === 0) {
49627
+ lines.push(`Orders: None
49628
+ `);
49629
+ } else {
49630
+ lines.push(`── Orders ──`);
49631
+ for (const o of orders) {
49632
+ for (const lo of o.limitOrders ?? []) {
49633
+ lines.push(` LIMIT ${lo.sideUi} ${lo.symbol}: $${lo.sizeUsdUi} @ $${lo.entryPriceUi} (${lo.leverageUi}x)`);
49634
+ }
49635
+ for (const tp of o.takeProfitOrders ?? []) {
49636
+ lines.push(` TP ${tp.sideUi} ${tp.symbol}: $${tp.sizeUsdUi} @ $${tp.triggerPriceUi}`);
49637
+ }
49638
+ for (const sl of o.stopLossOrders ?? []) {
49639
+ lines.push(` SL ${sl.sideUi} ${sl.symbol}: $${sl.sizeUsdUi} @ $${sl.triggerPriceUi}`);
49640
+ }
49641
+ }
49642
+ lines.push("");
49643
+ }
49644
+ if (positions && prices) {
49645
+ const marketSymbols = [...new Set(positions.map((p) => p.marketSymbol).filter((s) => !!s))];
49646
+ if (marketSymbols.length > 0) {
49647
+ lines.push("── Current Prices ──");
49648
+ for (const sym of marketSymbols) {
49649
+ const priceData = prices[sym];
49650
+ if (priceData) {
49651
+ const usd = formatPriceUsd(priceData);
49652
+ lines.push(` ${sym}: ${usd === "?" ? "price unavailable" : `$${usd}`}`);
49653
+ }
49654
+ }
49655
+ lines.push("");
49656
+ }
49657
+ }
49658
+ if (warnings.length > 0) {
49659
+ lines.push("── Warnings ──");
49660
+ for (const w of warnings)
49661
+ lines.push(` ${w}`);
49662
+ }
49663
+ return { content: [{ type: "text", text: lines.join(`
49664
+ `) }] };
49665
+ });
49666
+ }
49667
+
49668
+ // src/tools/trading-overview.ts
49669
+ function registerTradingOverviewTool(server, client) {
49670
+ server.registerTool("get_trading_overview", {
49671
+ description: "Get a trading-ready market snapshot: all markets with current oracle prices, max leverage, and pool utilization. " + "Recommended first call when planning new trades — replaces calling get_markets + get_prices + get_pool_data separately."
49672
+ }, async () => {
49673
+ const [marketsResult, pricesResult, poolResult] = await Promise.allSettled([
49674
+ client.getMarkets(),
49675
+ client.getPrices(),
49676
+ client.getPoolData()
49677
+ ]);
49678
+ const markets = marketsResult.status === "fulfilled" ? marketsResult.value : null;
49679
+ const prices = pricesResult.status === "fulfilled" ? pricesResult.value : null;
49680
+ const poolData = poolResult.status === "fulfilled" ? poolResult.value : null;
49681
+ const lines = [`=== Trading Overview ===
49682
+ `];
49683
+ const warnings = [];
49684
+ if (!markets)
49685
+ warnings.push(`Markets unavailable: ${sanitizeError(marketsResult.reason)}`);
49686
+ if (!prices)
49687
+ warnings.push(`Prices unavailable: ${sanitizeError(pricesResult.reason)}`);
49688
+ if (!poolData)
49689
+ warnings.push(`Pool data unavailable: ${sanitizeError(poolResult.reason)}`);
49690
+ if (markets) {
49691
+ const custodyInfo = poolData ? buildCustodySymbolMap(poolData) : new Map;
49692
+ lines.push("── Markets ──");
49693
+ lines.push("Symbol | Price | Side | Max Lev | Pool");
49694
+ lines.push("-----------|---------------|-------|---------|---------------");
49695
+ const enriched = markets.map((m) => {
49696
+ const info = custodyInfo.get(m.account.target_custody);
49697
+ return {
49698
+ symbol: info?.symbol ?? "UNKNOWN",
49699
+ pool: info?.pool ?? "?",
49700
+ maxLeverage: info?.maxLeverage ?? "?",
49701
+ side: m.account.side,
49702
+ open: m.account.permissions.allow_open_position
49703
+ };
49704
+ }).sort((a, b) => a.pool.localeCompare(b.pool) || a.symbol.localeCompare(b.symbol) || a.side.localeCompare(b.side));
49705
+ for (const m of enriched) {
49706
+ let priceStr = "?";
49707
+ if (prices) {
49708
+ const priceData = prices[m.symbol];
49709
+ if (priceData)
49710
+ priceStr = `$${formatPriceUsd(priceData)}`;
49711
+ }
49712
+ const status = m.open ? "" : " [CLOSED]";
49713
+ lines.push(`${m.symbol.padEnd(10)} | ${priceStr.padEnd(13)} | ${m.side.padEnd(5)} | ${m.maxLeverage.padEnd(7)} | ${m.pool}${status}`);
49714
+ }
49715
+ }
49716
+ if (poolData) {
49717
+ lines.push(`
49718
+ ── Pool Utilization ──`);
49719
+ lines.push("Pool | AUM | LP Price | Stable%");
49720
+ lines.push("---------------|----------------|-----------|--------");
49721
+ for (const p of poolData.pools) {
49722
+ const name = (p.poolName ?? "Unknown").padEnd(14);
49723
+ const aum = `$${p.lpStats?.totalPoolValueUsd ?? "?"}`.padEnd(14);
49724
+ const lp = `$${p.lpStats?.lpPrice ?? "?"}`.padEnd(9);
49725
+ const stable = `${p.lpStats?.stableCoinPercentage ?? "?"}%`;
49726
+ lines.push(`${name} | ${aum} | ${lp} | ${stable}`);
49727
+ }
49728
+ }
49729
+ if (warnings.length > 0) {
49730
+ lines.push(`
49731
+ ── Warnings ──`);
49732
+ for (const w of warnings)
49733
+ lines.push(` ${w}`);
49734
+ }
49735
+ lines.push(`
49736
+ Use open_position to trade. Use get_account_summary to check existing positions.`);
49737
+ return { content: [{ type: "text", text: lines.join(`
49738
+ `) }] };
49739
+ });
49740
+ }
49741
+
49558
49742
  // src/tools/open-position.ts
49559
49743
  function formatOpenPreview(req, res) {
49560
49744
  const lines = [
@@ -49599,7 +49783,7 @@ No transaction built (provide owner wallet pubkey to build transaction)`);
49599
49783
  }
49600
49784
  function registerOpenPositionTool(server, client) {
49601
49785
  server.registerTool("open_position", {
49602
- description: "Build a transaction to open a new perpetual position on Flash Trade. Returns a preview (entry price, fees, leverage, liquidation price) AND an unsigned transaction. The transaction must be signed by the user's wallet and submitted to Solana separately. IMPORTANT: Always present the preview to the user before they sign. This tool does NOT execute the trade. Supports both MARKET and LIMIT orders, with optional take-profit and stop-loss. COLLATERAL WARNING: Limit orders, take-profit, and stop-loss require >$10 collateral AFTER entry fees. A $10 position will have fees deducted, dropping collateral below $10 and preventing TP/SL/limit orders. Use at least $11-12 input_amount when planning to set TP/SL.",
49786
+ description: "Build a transaction to open a new perpetual futures position. Returns a preview (entry price, fees, leverage, liquidation price) AND an unsigned transaction. " + "Show the preview to the user before signing. Supports MARKET and LIMIT orders with optional TP/SL. " + "IMPORTANT: Use at least $11 input_amount if setting take_profit or stop_loss collateral after fees must exceed $10 for TP/SL to work on-chain.",
49603
49787
  inputSchema: {
49604
49788
  input_token_symbol: exports_external.string().max(16).describe('Token to pay with: "USDC", "SOL", etc.'),
49605
49789
  output_token_symbol: exports_external.string().max(16).describe('Market to trade: "SOL", "BTC", "ETH", etc.'),
@@ -49681,7 +49865,7 @@ Transaction (base64, unsigned — sign with wallet):`);
49681
49865
  }
49682
49866
  function registerClosePositionTool(server, client) {
49683
49867
  server.registerTool("close_position", {
49684
- description: "Build a transaction to close (fully or partially) an existing perpetual position. Returns a preview with PnL, fees, and receive amount, plus an unsigned transaction. For a full close, set input_usd to the position's full size. For a partial close, use a smaller amount. The transaction must be signed and submitted separately.",
49868
+ description: "Build a transaction to close (fully or partially) an existing position. Returns preview with PnL, fees, and receive amount, plus unsigned transaction. " + "For full close: set input_usd to position size. For partial: use smaller amount. Requires position_key from get_positions.",
49685
49869
  inputSchema: {
49686
49870
  position_key: exports_external.string().regex(/^[1-9A-HJ-NP-Za-km-z]{32,44}$/).describe("Position account pubkey to close"),
49687
49871
  input_usd: exports_external.string().max(32).describe('USD amount to close, e.g. "500.00" for full or "250.00" for partial'),
@@ -49815,7 +49999,7 @@ Transaction (base64, unsigned — sign with wallet):`);
49815
49999
  }
49816
50000
  function registerReversePositionTool(server, client) {
49817
50001
  server.registerTool("reverse_position", {
49818
- description: "Build a transaction to reverse a position (close current + open opposite direction). For example, close a LONG and open a SHORT with the same collateral. Returns combined close+open preview and a single unsigned transaction.",
50002
+ description: "Build a transaction to reverse a position (close current + open opposite direction). For example, close a LONG and open a SHORT with same collateral. " + "Returns combined preview and a single unsigned transaction. Requires position_key from get_positions.",
49819
50003
  inputSchema: {
49820
50004
  position_key: exports_external.string().regex(/^[1-9A-HJ-NP-Za-km-z]{32,44}$/).describe("Position account pubkey to reverse"),
49821
50005
  owner: exports_external.string().regex(/^[1-9A-HJ-NP-Za-km-z]{32,44}$/).describe("Wallet pubkey"),
@@ -56872,7 +57056,7 @@ var $VersionedTransaction = VersionedTransaction;
56872
57056
  import fs from "node:fs";
56873
57057
  function registerSignAndSendTool(server) {
56874
57058
  server.registerTool("sign_and_send", {
56875
- description: "Sign and submit a base64-encoded unsigned Solana transaction using the locally configured keypair. " + "Call this AFTER a transaction tool (open_position, close_position, add_collateral, remove_collateral, reverse_position) " + "returns a transactionBase64 string AND the user has reviewed and approved the preview. " + "The keypair is read from KEYPAIR_PATH (default: ~/.config/solana/id.json). " + "Returns the confirmed transaction signature and a Solscan link. " + "IMPORTANT: Always show the transaction preview to the user and get their approval BEFORE calling this tool. " + "This tool signs with the local keypair and submits to Solana mainnet — the action is IRREVERSIBLE. " + "NOTE: This tool never exposes private key material in its output.",
57059
+ description: "Sign and submit a base64 transaction to Solana mainnet using the local keypair. " + "Call ONLY after a transaction tool returns transactionBase64 AND the user has approved the preview. " + "IRREVERSIBLE always confirm with user first. Call immediately blockhashes expire in ~60 seconds. " + "Returns the confirmed signature and a Solscan link.",
56876
57060
  inputSchema: {
56877
57061
  transaction_base64: exports_external.string().max(1e4).describe("The base64-encoded unsigned transaction returned by a transaction tool")
56878
57062
  }
@@ -56937,13 +57121,20 @@ Signature: ${signature2}` }],
56937
57121
  const lines = [
56938
57122
  "=== Transaction Confirmed ===",
56939
57123
  `Signature: ${signature2}`,
56940
- `Explorer: https://solscan.io/tx/${signature2}`
57124
+ `Explorer: https://solscan.io/tx/${signature2}`,
57125
+ "",
57126
+ "Next: Call get_positions (with owner) to verify the position, or get_orders to check trigger orders."
56941
57127
  ];
56942
57128
  return { content: [{ type: "text", text: lines.join(`
56943
57129
  `) }] };
56944
57130
  } catch (e) {
57131
+ const msg = sanitizeError(e);
57132
+ const isBlockhashExpired = msg.includes("Blockhash not found") || msg.includes("block height exceeded");
57133
+ const hint = isBlockhashExpired ? `
57134
+
57135
+ The blockhash has expired (~60 seconds). Re-call the original transaction tool to get a fresh transaction, then call sign_and_send immediately.` : "";
56945
57136
  return {
56946
- content: [{ type: "text", text: `Transaction send failed: ${sanitizeError(e)}` }],
57137
+ content: [{ type: "text", text: `Transaction send failed: ${msg}${hint}` }],
56947
57138
  isError: true
56948
57139
  };
56949
57140
  }
@@ -56953,7 +57144,7 @@ Signature: ${signature2}` }],
56953
57144
  // src/tools/trigger-orders.ts
56954
57145
  function registerTriggerOrderTools(server, client) {
56955
57146
  server.registerTool("place_trigger_order", {
56956
- description: "Place a take-profit (TP) or stop-loss (SL) trigger order on an existing position. The trigger order will automatically close part or all of the position when the price hits the trigger level. Requires an open position for the given market/side. Returns an unsigned transaction. Up to 5 trigger orders per position.",
57147
+ description: "Place a take-profit (TP) or stop-loss (SL) trigger order on an existing position. Up to 5 per position. " + "Use preview_tp_sl first to calculate optimal trigger prices. Returns unsigned transaction.",
56957
57148
  inputSchema: {
56958
57149
  market_symbol: exports_external.string().max(16).describe('Market symbol, e.g. "SOL", "BTC", "ETH"'),
56959
57150
  side: exports_external.enum(["LONG", "SHORT"]).describe("Position side"),
@@ -56984,12 +57175,14 @@ WARNING: ${res.err}`);
56984
57175
  lines.push(`
56985
57176
  Transaction (base64, unsigned — sign with wallet):`);
56986
57177
  lines.push(res.transactionBase64);
57178
+ lines.push(`
57179
+ Next: After signing, call get_orders with owner to see the order ID for editing/canceling.`);
56987
57180
  }
56988
57181
  return { content: [{ type: "text", text: lines.join(`
56989
57182
  `) }] };
56990
57183
  });
56991
57184
  server.registerTool("edit_trigger_order", {
56992
- description: "Edit an existing take-profit or stop-loss trigger order. Change the trigger price, size, or order type without canceling and re-placing. Requires the order_id (0-7) from get_orders. Returns an unsigned transaction.",
57185
+ description: "Edit an existing TP or SL trigger order. Change trigger price, size, or type. Requires order_id (0-7) from get_orders. Returns unsigned transaction.",
56993
57186
  inputSchema: {
56994
57187
  market_symbol: exports_external.string().max(16).describe('Market symbol, e.g. "SOL", "BTC", "ETH"'),
56995
57188
  side: exports_external.enum(["LONG", "SHORT"]).describe("Position side"),
@@ -57027,7 +57220,7 @@ Transaction (base64, unsigned — sign with wallet):`);
57027
57220
  `) }] };
57028
57221
  });
57029
57222
  server.registerTool("cancel_trigger_order", {
57030
- description: "Cancel a single take-profit or stop-loss trigger order. Requires the order_id (0-7) from get_orders. Returns an unsigned transaction.",
57223
+ description: "Cancel a single TP or SL trigger order. Requires order_id (0-7) from get_orders. Returns unsigned transaction.",
57031
57224
  inputSchema: {
57032
57225
  market_symbol: exports_external.string().max(16).describe('Market symbol, e.g. "SOL", "BTC", "ETH"'),
57033
57226
  side: exports_external.enum(["LONG", "SHORT"]).describe("Position side"),
@@ -57059,7 +57252,7 @@ Transaction (base64, unsigned — sign with wallet):`);
57059
57252
  `) }] };
57060
57253
  });
57061
57254
  server.registerTool("cancel_all_trigger_orders", {
57062
- description: "Cancel ALL take-profit and stop-loss trigger orders for a market+side. Removes all TP and SL orders in one transaction. Returns an unsigned transaction.",
57255
+ description: "Cancel ALL TP and SL trigger orders for a market+side in one transaction. Returns unsigned transaction.",
57063
57256
  inputSchema: {
57064
57257
  market_symbol: exports_external.string().max(16).describe('Market symbol, e.g. "SOL", "BTC", "ETH"'),
57065
57258
  side: exports_external.enum(["LONG", "SHORT"]).describe("Position side"),
@@ -57098,6 +57291,8 @@ function registerReadTools(server, client) {
57098
57291
  registerPositionTools(server, client);
57099
57292
  registerOrderTools(server, client);
57100
57293
  registerPoolDataTools(server, client);
57294
+ registerAccountSummaryTool(server, client);
57295
+ registerTradingOverviewTool(server, client);
57101
57296
  }
57102
57297
  function registerTransactionTools(server, client) {
57103
57298
  registerOpenPositionTool(server, client);
@@ -57181,7 +57376,7 @@ try {
57181
57376
  const client = new FlashApiClient(config2);
57182
57377
  const server = new McpServer({
57183
57378
  name: "flash-trade",
57184
- version: "0.3.5"
57379
+ version: "0.4.0"
57185
57380
  }, {
57186
57381
  capabilities: {
57187
57382
  tools: {},
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flash-trade-mcp",
3
- "version": "0.3.5",
3
+ "version": "0.4.0",
4
4
  "description": "MCP server for Flash Trade — perpetual futures DEX on Solana. Provides AI agents with typed tools for trading, position management, and market data.",
5
5
  "module": "src/index.ts",
6
6
  "main": "dist/index.js",