outsmart-agent 1.0.0-alpha.4 → 1.0.0-alpha.6

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.
@@ -21,7 +21,8 @@
21
21
  "./skills/outsmart-trenching",
22
22
  "./skills/outsmart-devving-coins",
23
23
  "./skills/outsmart-prediction-markets",
24
- "./skills/outsmart-survival"
24
+ "./skills/outsmart-survival",
25
+ "./skills/outsmart-percolator-perps"
25
26
  ],
26
27
  "agents": [
27
28
  "./agents/solana-trading-expert.md"
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # outsmart-agent
2
2
 
3
- DeFi survival toolkit for AI agents on Solana. Trade, LP, snipe, trench, dev coins, and farm across 18 DEX protocols. Earn your own existence.
3
+ DeFi survival toolkit for AI agents on Solana. Trade, LP, snipe, trench, dev coins, operate perp exchanges, and farm across 18 DEX protocols. Earn your own existence.
4
4
 
5
5
  ```
6
6
  npx outsmart-agent
@@ -10,7 +10,7 @@ npx outsmart-agent
10
10
 
11
11
  An AI agent needs money to stay alive — compute costs, inference fees, API calls. This gives any MCP-compatible agent the tools to earn revenue on Solana through DeFi. LP farming, memecoin trenching, token launching, prediction markets, systematic DCA — whatever the market calls for.
12
12
 
13
- 23 MCP tools for execution. 8 AI skills that teach the agent **when** and **why**, not just how.
13
+ 32 MCP tools for execution. 9 AI skills that teach the agent **when** and **why**, not just how.
14
14
 
15
15
  ## Quick Start
16
16
 
@@ -51,23 +51,33 @@ npx skills add outsmartchad/outsmart-agent
51
51
 
52
52
  ## MCP Tools
53
53
 
54
- ### DEX Tools (14)
54
+ ### DEX Tools (11)
55
+
56
+ | Tool | What |
57
+ |------|------|
58
+ | `dex_buy` | Buy tokens with SOL on any DEX |
59
+ | `dex_sell` | Sell tokens (percentage-based) |
60
+ | `dex_quote` | On-chain price from a pool |
61
+ | `dex_snipe` | Competitive buy with Jito MEV tip |
62
+ | `dex_find_pool` | Find pool address for a token pair |
63
+ | `dex_create_pool` | Create DAMM v2 pool on Meteora |
64
+ | `dex_add_liquidity` | Add LP (DLMM bins, DAMM v2 full-range) |
65
+ | `dex_remove_liquidity` | Remove LP |
66
+ | `dex_claim_fees` | Collect swap fees from LP |
67
+ | `dex_list_positions` | Your LP positions in a pool |
68
+ | `dex_list_dexes` | All 18 adapters + capabilities |
69
+
70
+ ### Launchpad Tools (1)
71
+
72
+ | Tool | What |
73
+ |------|------|
74
+ | `launchpad_create_coin` | Launch token on PumpFun |
75
+
76
+ ### Solana Tools (2)
55
77
 
56
78
  | Tool | What |
57
79
  |------|------|
58
- | `solana_buy` | Buy tokens with SOL on any DEX |
59
- | `solana_sell` | Sell tokens (percentage-based) |
60
- | `solana_quote` | On-chain price from a pool |
61
- | `solana_snipe` | Competitive buy with Jito MEV tip |
62
- | `solana_find_pool` | Find pool address for a token pair |
63
- | `solana_create_pool` | Create DAMM v2 pool on Meteora |
64
- | `solana_create_token` | Launch token on PumpFun |
65
- | `solana_add_liquidity` | Add LP (DLMM bins, DAMM v2 full-range) |
66
- | `solana_remove_liquidity` | Remove LP |
67
- | `solana_claim_fees` | Collect swap fees from LP |
68
- | `solana_list_positions` | Your LP positions in a pool |
69
80
  | `solana_token_info` | DexScreener market data |
70
- | `solana_list_dexes` | All 18 adapters + capabilities |
71
81
  | `solana_wallet_balance` | SOL and token balances |
72
82
 
73
83
  ### Jupiter Tools (9)
@@ -84,9 +94,23 @@ npx skills add outsmartchad/outsmart-agent
84
94
  | `jupiter_dca_list` | List active/historical DCA orders |
85
95
  | `jupiter_dca_cancel` | Cancel a DCA order |
86
96
 
97
+ ### Percolator Perp Tools (9)
98
+
99
+ | Tool | What |
100
+ |------|------|
101
+ | `percolator_create_market` | Create a permissionless perp exchange |
102
+ | `percolator_init_user` | Register a trader account on a market |
103
+ | `percolator_deposit` | Deposit collateral |
104
+ | `percolator_withdraw` | Withdraw collateral |
105
+ | `percolator_trade` | Open/close/modify leveraged positions |
106
+ | `percolator_push_oracle` | Update oracle price (admin-oracle mode) |
107
+ | `percolator_crank` | Run keeper crank |
108
+ | `percolator_market_state` | Read full market state |
109
+ | `percolator_insurance_lp` | Deposit/withdraw insurance fund LP |
110
+
87
111
  ## Skills
88
112
 
89
- 8 strategy skills that teach agents how to think about Solana DeFi:
113
+ 9 strategy skills that teach agents how to think about Solana DeFi:
90
114
 
91
115
  | Skill | What |
92
116
  |-------|------|
@@ -98,6 +122,7 @@ npx skills add outsmartchad/outsmart-agent
98
122
  | **outsmart-dca-grid** | Jupiter Recurring DCA + DLMM grid trading |
99
123
  | **outsmart-prediction-markets** | Probability estimation, edge calculation, Jupiter + Polymarket + Futarchy |
100
124
  | **outsmart-survival** | Capital management, survival tiers, emergency liquidation |
125
+ | **outsmart-percolator-perps** | Operating perp exchanges — market creation, LP, pricing, keeper duties |
101
126
 
102
127
  ## Supported DEXes
103
128
 
@@ -114,10 +139,11 @@ npx skills add outsmartchad/outsmart-agent
114
139
  ```
115
140
  outsmart (npm) outsmart-agent (this repo)
116
141
  ────────────── ──────────────────────────
117
- 18 DEX adapters MCP server (23 tools)
118
- TX landing providers 8 AI skills
119
- Wallet + TX helpers Agent definition
120
- DexScreener API Plugin manifest
142
+ 18 DEX adapters MCP server (32 tools)
143
+ Percolator perps 9 AI skills
144
+ TX landing providers Agent definition
145
+ Wallet + TX helpers Plugin manifest
146
+ DexScreener API
121
147
  ```
122
148
 
123
149
  `outsmart-agent` imports `outsmart` as a dependency. The MCP server is a thin wrapper — validates params, calls adapter methods, returns JSON.
@@ -145,17 +171,19 @@ Never >5% on a single trade. Take profits. Track what works. Evolve.
145
171
  | `PRIVATE_KEY` | Yes | Base58 Solana private key |
146
172
  | `MAINNET_ENDPOINT` | Yes | Solana RPC (Helius, Triton, etc.) |
147
173
  | `JUPITER_API_KEY` | No | Jupiter Ultra, Shield, Prediction, DCA |
174
+ | `DEVNET_ENDPOINT` | No | Solana devnet RPC (Percolator) |
148
175
  | `DFLOW_API_KEY` | No | DFlow |
149
176
 
150
177
  ## Roadmap
151
178
 
152
- - [x] MCP Server — 23 tools (14 DEX + 9 Jupiter), 18 DEX adapters
153
- - [x] AI Skills — 8 strategy skills
179
+ - [x] MCP Server — 32 tools (11 DEX + 1 Launchpad + 2 Solana + 9 Jupiter + 9 Percolator), 18 DEX adapters
180
+ - [x] AI Skills — 9 strategy skills
154
181
  - [x] Claude Code Plugin manifest
182
+ - [x] Percolator — Permissionless perp exchange creation, trading, LP, insurance
155
183
  - [ ] Event Streaming — Yellowstone gRPC for real-time pool creation
156
184
  - [ ] LP Manager — Autonomous rebalancing and fee compounding
157
185
  - [ ] Strategy Engine — Tier-aware capital allocation
158
- - [ ] Percolator — Permissionless perp exchange LP
186
+ - [ ] Percolator Keeper Background crank + liquidation service
159
187
 
160
188
  ## Related
161
189
 
@@ -2,21 +2,30 @@
2
2
  /**
3
3
  * outsmart-agent MCP Server
4
4
  *
5
- * Exposes 23 MCP tools wrapping the `outsmart` trading library + Jupiter APIs.
5
+ * Exposes 32 MCP tools wrapping the `outsmart` trading library + Jupiter APIs + Percolator.
6
6
  * Runs over stdio transport — start with `npx outsmart-agent`.
7
7
  *
8
- * DEX Tools (14):
9
- * solana_buy, solana_sell, solana_quote, solana_find_pool, solana_snipe,
10
- * solana_create_pool, solana_create_token,
11
- * solana_add_liquidity, solana_remove_liquidity, solana_claim_fees,
12
- * solana_list_positions, solana_token_info, solana_list_dexes,
13
- * solana_wallet_balance
8
+ * DEX Tools (11):
9
+ * dex_buy, dex_sell, dex_quote, dex_find_pool, dex_snipe,
10
+ * dex_create_pool, dex_add_liquidity, dex_remove_liquidity,
11
+ * dex_claim_fees, dex_list_positions, dex_list_dexes
12
+ *
13
+ * Launchpad Tools (1):
14
+ * launchpad_create_coin
15
+ *
16
+ * Solana Tools (2):
17
+ * solana_token_info, solana_wallet_balance
14
18
  *
15
19
  * Jupiter Tools (9):
16
20
  * jupiter_shield,
17
21
  * jupiter_prediction_events, jupiter_prediction_market,
18
22
  * jupiter_prediction_order, jupiter_prediction_positions, jupiter_prediction_claim,
19
23
  * jupiter_dca_create, jupiter_dca_list, jupiter_dca_cancel
24
+ *
25
+ * Percolator Perp Tools (9):
26
+ * percolator_create_market, percolator_trade, percolator_deposit,
27
+ * percolator_withdraw, percolator_market_state, percolator_list_markets,
28
+ * percolator_push_price, percolator_crank, percolator_insurance_lp
20
29
  */
21
30
  export {};
22
31
  //# sourceMappingURL=server.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;GAkBG"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG"}
@@ -3,21 +3,30 @@
3
3
  /**
4
4
  * outsmart-agent MCP Server
5
5
  *
6
- * Exposes 23 MCP tools wrapping the `outsmart` trading library + Jupiter APIs.
6
+ * Exposes 32 MCP tools wrapping the `outsmart` trading library + Jupiter APIs + Percolator.
7
7
  * Runs over stdio transport — start with `npx outsmart-agent`.
8
8
  *
9
- * DEX Tools (14):
10
- * solana_buy, solana_sell, solana_quote, solana_find_pool, solana_snipe,
11
- * solana_create_pool, solana_create_token,
12
- * solana_add_liquidity, solana_remove_liquidity, solana_claim_fees,
13
- * solana_list_positions, solana_token_info, solana_list_dexes,
14
- * solana_wallet_balance
9
+ * DEX Tools (11):
10
+ * dex_buy, dex_sell, dex_quote, dex_find_pool, dex_snipe,
11
+ * dex_create_pool, dex_add_liquidity, dex_remove_liquidity,
12
+ * dex_claim_fees, dex_list_positions, dex_list_dexes
13
+ *
14
+ * Launchpad Tools (1):
15
+ * launchpad_create_coin
16
+ *
17
+ * Solana Tools (2):
18
+ * solana_token_info, solana_wallet_balance
15
19
  *
16
20
  * Jupiter Tools (9):
17
21
  * jupiter_shield,
18
22
  * jupiter_prediction_events, jupiter_prediction_market,
19
23
  * jupiter_prediction_order, jupiter_prediction_positions, jupiter_prediction_claim,
20
24
  * jupiter_dca_create, jupiter_dca_list, jupiter_dca_cancel
25
+ *
26
+ * Percolator Perp Tools (9):
27
+ * percolator_create_market, percolator_trade, percolator_deposit,
28
+ * percolator_withdraw, percolator_market_state, percolator_list_markets,
29
+ * percolator_push_price, percolator_crank, percolator_insurance_lp
21
30
  */
22
31
  Object.defineProperty(exports, "__esModule", { value: true });
23
32
  const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
@@ -33,7 +42,7 @@ function getAdapter(dex) {
33
42
  return (0, outsmart_1.getDexAdapter)(dex);
34
43
  }
35
44
  catch (err) {
36
- throw new Error(`DEX adapter "${dex}" not found. Use solana_list_dexes to see available adapters. ${err.message}`);
45
+ throw new Error(`DEX adapter "${dex}" not found. Use dex_list_dexes to see available adapters. ${err.message}`);
37
46
  }
38
47
  }
39
48
  // ---------------------------------------------------------------------------
@@ -58,10 +67,10 @@ const server = new mcp_js_1.McpServer({
58
67
  version: "1.0.0-alpha.1",
59
68
  });
60
69
  // ---------------------------------------------------------------------------
61
- // Tool: solana_buy
70
+ // Tool: dex_buy
62
71
  // ---------------------------------------------------------------------------
63
72
  // @ts-expect-error — TS2589: deep type instantiation from MCP SDK generics + zod
64
- server.tool("solana_buy", "Buy tokens with SOL on a Solana DEX. For aggregators (jupiter-ultra, dflow), provide 'token'. For on-chain DEXes (raydium-*, meteora-*, orca, etc.), provide 'pool'.", {
73
+ server.tool("dex_buy", "Buy tokens with SOL on a Solana DEX. For aggregators (jupiter-ultra, dflow), provide 'token'. For on-chain DEXes (raydium-*, meteora-*, orca, etc.), provide 'pool'.", {
65
74
  dex: zod_1.z.string().describe("DEX adapter name (e.g. 'jupiter-ultra', 'raydium-cpmm', 'meteora-dlmm')"),
66
75
  pool: zod_1.z.string().optional().describe("Pool address (required for on-chain DEXes)"),
67
76
  token: zod_1.z.string().optional().describe("Token mint address (required for aggregators)"),
@@ -89,9 +98,9 @@ server.tool("solana_buy", "Buy tokens with SOL on a Solana DEX. For aggregators
89
98
  }
90
99
  });
91
100
  // ---------------------------------------------------------------------------
92
- // Tool: solana_sell
101
+ // Tool: dex_sell
93
102
  // ---------------------------------------------------------------------------
94
- server.tool("solana_sell", "Sell tokens for SOL on a Solana DEX. Specify percentage of holdings to sell (0-100).", {
103
+ server.tool("dex_sell", "Sell tokens for SOL on a Solana DEX. Specify percentage of holdings to sell (0-100).", {
95
104
  dex: zod_1.z.string().describe("DEX adapter name"),
96
105
  pool: zod_1.z.string().optional().describe("Pool address (required for on-chain DEXes)"),
97
106
  token: zod_1.z.string().optional().describe("Token mint address (required for aggregators)"),
@@ -117,9 +126,9 @@ server.tool("solana_sell", "Sell tokens for SOL on a Solana DEX. Specify percent
117
126
  }
118
127
  });
119
128
  // ---------------------------------------------------------------------------
120
- // Tool: solana_quote
129
+ // Tool: dex_quote
121
130
  // ---------------------------------------------------------------------------
122
- server.tool("solana_quote", "Get the current on-chain price from a pool. Reads directly from on-chain state.", {
131
+ server.tool("dex_quote", "Get the current on-chain price from a pool. Reads directly from on-chain state.", {
123
132
  dex: zod_1.z.string().describe("DEX adapter name"),
124
133
  pool: zod_1.z.string().describe("Pool address to read price from"),
125
134
  }, async (args) => {
@@ -136,9 +145,9 @@ server.tool("solana_quote", "Get the current on-chain price from a pool. Reads d
136
145
  }
137
146
  });
138
147
  // ---------------------------------------------------------------------------
139
- // Tool: solana_add_liquidity
148
+ // Tool: dex_add_liquidity
140
149
  // ---------------------------------------------------------------------------
141
- server.tool("solana_add_liquidity", "Add liquidity to a pool. Supports DLMM strategies (spot, curve, bid-ask) and bin configuration.", {
150
+ server.tool("dex_add_liquidity", "Add liquidity to a pool. Supports DLMM strategies (spot, curve, bid-ask) and bin configuration.", {
142
151
  dex: zod_1.z.string().describe("DEX adapter name"),
143
152
  pool: zod_1.z.string().describe("Pool address to add liquidity to"),
144
153
  amount_sol: zod_1.z.number().min(0).optional().describe("Amount of SOL to deposit"),
@@ -167,9 +176,9 @@ server.tool("solana_add_liquidity", "Add liquidity to a pool. Supports DLMM stra
167
176
  }
168
177
  });
169
178
  // ---------------------------------------------------------------------------
170
- // Tool: solana_remove_liquidity
179
+ // Tool: dex_remove_liquidity
171
180
  // ---------------------------------------------------------------------------
172
- server.tool("solana_remove_liquidity", "Remove liquidity from a pool. Specify percentage to withdraw (0-100).", {
181
+ server.tool("dex_remove_liquidity", "Remove liquidity from a pool. Specify percentage to withdraw (0-100).", {
173
182
  dex: zod_1.z.string().describe("DEX adapter name"),
174
183
  pool: zod_1.z.string().describe("Pool address"),
175
184
  percentage: zod_1.z.number().min(0).max(100).describe("Percentage of LP position to remove (100 = withdraw all)"),
@@ -192,9 +201,9 @@ server.tool("solana_remove_liquidity", "Remove liquidity from a pool. Specify pe
192
201
  }
193
202
  });
194
203
  // ---------------------------------------------------------------------------
195
- // Tool: solana_claim_fees
204
+ // Tool: dex_claim_fees
196
205
  // ---------------------------------------------------------------------------
197
- server.tool("solana_claim_fees", "Claim accumulated swap fees from LP positions in a pool.", {
206
+ server.tool("dex_claim_fees", "Claim accumulated swap fees from LP positions in a pool.", {
198
207
  dex: zod_1.z.string().describe("DEX adapter name"),
199
208
  pool: zod_1.z.string().describe("Pool address"),
200
209
  position_address: zod_1.z.string().optional().describe("Specific position to claim from"),
@@ -212,9 +221,9 @@ server.tool("solana_claim_fees", "Claim accumulated swap fees from LP positions
212
221
  }
213
222
  });
214
223
  // ---------------------------------------------------------------------------
215
- // Tool: solana_list_positions
224
+ // Tool: dex_list_positions
216
225
  // ---------------------------------------------------------------------------
217
- server.tool("solana_list_positions", "List user's LP positions in a pool. Shows token amounts, fee balances, and in-range status.", {
226
+ server.tool("dex_list_positions", "List user's LP positions in a pool. Shows token amounts, fee balances, and in-range status.", {
218
227
  dex: zod_1.z.string().describe("DEX adapter name"),
219
228
  pool: zod_1.z.string().describe("Pool address"),
220
229
  }, async (args) => {
@@ -245,9 +254,9 @@ server.tool("solana_token_info", "Get token market data from DexScreener — pri
245
254
  }
246
255
  });
247
256
  // ---------------------------------------------------------------------------
248
- // Tool: solana_list_dexes
257
+ // Tool: dex_list_dexes
249
258
  // ---------------------------------------------------------------------------
250
- server.tool("solana_list_dexes", "List all available DEX adapters and their capabilities. Optionally filter by capability.", {
259
+ server.tool("dex_list_dexes", "List all available DEX adapters and their capabilities. Optionally filter by capability.", {
251
260
  capability: zod_1.z
252
261
  .string()
253
262
  .optional()
@@ -295,9 +304,9 @@ server.tool("solana_wallet_balance", "Check SOL balance of the configured wallet
295
304
  }
296
305
  });
297
306
  // ---------------------------------------------------------------------------
298
- // Tool: solana_find_pool
307
+ // Tool: dex_find_pool
299
308
  // ---------------------------------------------------------------------------
300
- server.tool("solana_find_pool", "Find a pool address for a token pair on a specific DEX. Returns the pool address, base/quote mints, and liquidity info.", {
309
+ server.tool("dex_find_pool", "Find a pool address for a token pair on a specific DEX. Returns the pool address, base/quote mints, and liquidity info.", {
301
310
  dex: zod_1.z.string().describe("DEX adapter name (e.g. 'meteora-damm-v2', 'raydium-cpmm')"),
302
311
  base_mint: zod_1.z.string().describe("Base token mint address (the token you want to trade)"),
303
312
  quote_mint: zod_1.z.string().optional().describe("Quote token mint address (default: WSOL)"),
@@ -318,9 +327,9 @@ server.tool("solana_find_pool", "Find a pool address for a token pair on a speci
318
327
  }
319
328
  });
320
329
  // ---------------------------------------------------------------------------
321
- // Tool: solana_snipe
330
+ // Tool: dex_snipe
322
331
  // ---------------------------------------------------------------------------
323
- server.tool("solana_snipe", "Competitive buy with Jito MEV tip for faster execution. Use for time-sensitive buys where you want priority over other traders.", {
332
+ server.tool("dex_snipe", "Competitive buy with Jito MEV tip for faster execution. Use for time-sensitive buys where you want priority over other traders.", {
324
333
  dex: zod_1.z.string().describe("DEX adapter name"),
325
334
  pool: zod_1.z.string().describe("Pool address to snipe on"),
326
335
  token: zod_1.z.string().describe("Token mint address to buy"),
@@ -349,10 +358,10 @@ server.tool("solana_snipe", "Competitive buy with Jito MEV tip for faster execut
349
358
  }
350
359
  });
351
360
  // ---------------------------------------------------------------------------
352
- // Tool: solana_create_pool
361
+ // Tool: dex_create_pool
353
362
  // ---------------------------------------------------------------------------
354
363
  // @ts-expect-error — TS2589: deep type instantiation from MCP SDK generics + zod
355
- server.tool("solana_create_pool", "Create a new DAMM v2 liquidity pool on Meteora. Two modes: 'custom' (full fee schedule control) or 'config' (use pre-existing on-chain config). The alpha play is being the first pool creator on a new token — set 99% starting fee to capture early volume.", {
364
+ server.tool("dex_create_pool", "Create a new DAMM v2 liquidity pool on Meteora. Two modes: 'custom' (full fee schedule control) or 'config' (use pre-existing on-chain config). The alpha play is being the first pool creator on a new token — set 99% starting fee to capture early volume.", {
356
365
  mode: zod_1.z.enum(["custom", "config"]).describe("'custom' for full fee control, 'config' to use a pre-existing on-chain config"),
357
366
  base_mint: zod_1.z.string().describe("Base token mint address (the token)"),
358
367
  quote_mint: zod_1.z.string().optional().describe("Quote token mint (default: WSOL)"),
@@ -422,9 +431,9 @@ server.tool("solana_create_pool", "Create a new DAMM v2 liquidity pool on Meteor
422
431
  }
423
432
  });
424
433
  // ---------------------------------------------------------------------------
425
- // Tool: solana_create_token
434
+ // Tool: launchpad_create_coin
426
435
  // ---------------------------------------------------------------------------
427
- server.tool("solana_create_token", "Create a new token on PumpFun with a bonding curve. Deploys a new SPL token (6 decimals, 1B supply, mint/freeze disabled) and creates a bonding curve. The token graduates to PumpSwap AMM when the curve fills (~85 SOL).", {
436
+ server.tool("launchpad_create_coin", "Create a new token on PumpFun with a bonding curve. Deploys a new SPL token (6 decimals, 1B supply, mint/freeze disabled) and creates a bonding curve. The token graduates to PumpSwap AMM when the curve fills (~85 SOL).", {
428
437
  name: zod_1.z.string().describe("Token name (e.g. 'My Token')"),
429
438
  symbol: zod_1.z.string().describe("Token ticker (e.g. 'MYTOKEN')"),
430
439
  metadata_uri: zod_1.z.string().describe("Metadata URI — IPFS or Arweave link to JSON metadata with image"),
@@ -735,6 +744,201 @@ server.tool("jupiter_dca_cancel", "Cancel an active Jupiter DCA order. Returns r
735
744
  return err(e.message);
736
745
  }
737
746
  });
747
+ // ===========================================================================
748
+ // PERCOLATOR PERPETUAL FUTURES TOOLS (9 tools)
749
+ // ===========================================================================
750
+ const percolator = new outsmart_1.PercolatorAdapter();
751
+ // ---------------------------------------------------------------------------
752
+ // Tool: percolator_create_market
753
+ // ---------------------------------------------------------------------------
754
+ // @ts-expect-error — TS2589: deep type instantiation from MCP SDK generics + zod
755
+ server.tool("percolator_create_market", "Create a new Percolator perpetual futures market. Two oracle modes: admin-oracle (default, you push prices) or Pyth-pinned (pass pyth_feed_id, prices come from Pyth on-chain automatically). Returns slab address for all subsequent operations.", {
756
+ collateral_mint: zod_1.z.string().describe("Collateral token mint address (e.g. BONK, wSOL)"),
757
+ initial_price_e6: zod_1.z.string().describe("Initial oracle price in e6 format (1 USD = 1000000). Example: '150000' for $0.15"),
758
+ lp_collateral: zod_1.z.string().describe("Initial LP collateral in native token units (e.g. '1000000000' for 1B BONK lamports)"),
759
+ tier: zod_1.z.enum(["small", "medium", "large"]).optional().describe("Slab tier: small (256 slots, ~0.44 SOL), medium (1024, ~1.73 SOL), large (4096, ~6.91 SOL). Default: small"),
760
+ network: zod_1.z.enum(["devnet", "mainnet"]).optional().describe("Network (default: devnet)"),
761
+ pyth_feed_id: zod_1.z.string().optional().describe("Pyth feed ID hex (64 chars). If set, creates a Pyth-pinned market — no manual price pushing needed. SOL/USD: ef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d"),
762
+ }, async (args) => {
763
+ try {
764
+ const result = await percolator.createMarket({
765
+ collateralMint: args.collateral_mint,
766
+ initialPriceE6: BigInt(args.initial_price_e6),
767
+ lpCollateral: BigInt(args.lp_collateral),
768
+ tier: args.tier,
769
+ network: args.network,
770
+ pythFeedId: args.pyth_feed_id,
771
+ });
772
+ return ok(result);
773
+ }
774
+ catch (e) {
775
+ return err(e.message);
776
+ }
777
+ });
778
+ // ---------------------------------------------------------------------------
779
+ // Tool: percolator_trade
780
+ // ---------------------------------------------------------------------------
781
+ server.tool("percolator_trade", "Open, close, or modify a perpetual futures position on a Percolator market. Positive size = long, negative = short. Size is in i128 native token units.", {
782
+ slab: zod_1.z.string().describe("Slab (market) address"),
783
+ user_idx: zod_1.z.number().int().min(0).describe("Your user account index in the slab"),
784
+ lp_idx: zod_1.z.number().int().min(0).describe("LP account index to trade against"),
785
+ size: zod_1.z.string().describe("Trade size as i128 string. Positive = go long, negative = go short. Use '0' won't work — to close, use opposite size."),
786
+ network: zod_1.z.enum(["devnet", "mainnet"]).optional().describe("Network (default: devnet)"),
787
+ }, async (args) => {
788
+ try {
789
+ const sig = await percolator.trade({
790
+ slabAddress: args.slab,
791
+ userIdx: args.user_idx,
792
+ lpIdx: args.lp_idx,
793
+ size: BigInt(args.size),
794
+ network: args.network,
795
+ });
796
+ return ok({ signature: sig });
797
+ }
798
+ catch (e) {
799
+ return err(e.message);
800
+ }
801
+ });
802
+ // ---------------------------------------------------------------------------
803
+ // Tool: percolator_deposit
804
+ // ---------------------------------------------------------------------------
805
+ server.tool("percolator_deposit", "Deposit collateral into a Percolator market account (user or LP).", {
806
+ slab: zod_1.z.string().describe("Slab (market) address"),
807
+ user_idx: zod_1.z.number().int().min(0).describe("Account index to deposit into"),
808
+ amount: zod_1.z.string().describe("Amount in native token units"),
809
+ network: zod_1.z.enum(["devnet", "mainnet"]).optional(),
810
+ }, async (args) => {
811
+ try {
812
+ const sig = await percolator.deposit(args.slab, args.user_idx, BigInt(args.amount), args.network);
813
+ return ok({ signature: sig });
814
+ }
815
+ catch (e) {
816
+ return err(e.message);
817
+ }
818
+ });
819
+ // ---------------------------------------------------------------------------
820
+ // Tool: percolator_withdraw
821
+ // ---------------------------------------------------------------------------
822
+ server.tool("percolator_withdraw", "Withdraw collateral from a Percolator market account. Only available when position is flat or has sufficient margin.", {
823
+ slab: zod_1.z.string().describe("Slab (market) address"),
824
+ user_idx: zod_1.z.number().int().min(0).describe("Account index to withdraw from"),
825
+ amount: zod_1.z.string().describe("Amount in native token units"),
826
+ network: zod_1.z.enum(["devnet", "mainnet"]).optional(),
827
+ }, async (args) => {
828
+ try {
829
+ const sig = await percolator.withdraw(args.slab, args.user_idx, BigInt(args.amount), args.network);
830
+ return ok({ signature: sig });
831
+ }
832
+ catch (e) {
833
+ return err(e.message);
834
+ }
835
+ });
836
+ // ---------------------------------------------------------------------------
837
+ // Tool: percolator_market_state
838
+ // ---------------------------------------------------------------------------
839
+ server.tool("percolator_market_state", "Read the full state of a Percolator perpetual futures market: header, config, engine, risk params, and all accounts.", {
840
+ slab: zod_1.z.string().describe("Slab (market) address"),
841
+ }, async (args) => {
842
+ try {
843
+ const state = await percolator.getMarketState(args.slab);
844
+ // Serialize BigInt values for JSON output
845
+ return ok(JSON.parse(JSON.stringify(state, (_key, value) => typeof value === "bigint" ? value.toString() : value)));
846
+ }
847
+ catch (e) {
848
+ return err(e.message);
849
+ }
850
+ });
851
+ // ---------------------------------------------------------------------------
852
+ // Tool: percolator_list_markets
853
+ // ---------------------------------------------------------------------------
854
+ server.tool("percolator_list_markets", "Discover all Percolator perpetual futures markets on-chain across all program tiers.", {
855
+ network: zod_1.z.enum(["devnet", "mainnet"]).optional().describe("Network (default: devnet)"),
856
+ }, async (args) => {
857
+ try {
858
+ const markets = await percolator.discoverMarkets(args.network);
859
+ return ok(JSON.parse(JSON.stringify(markets.map(m => ({
860
+ slab: m.slabAddress.toBase58(),
861
+ program: m.programId.toBase58(),
862
+ admin: m.header.admin.toBase58(),
863
+ collateralMint: m.config.collateralMint.toBase58(),
864
+ oraclePrice: m.config.authorityPriceE6.toString(),
865
+ vault: m.engine.vault.toString(),
866
+ totalOI: m.engine.totalOpenInterest.toString(),
867
+ numAccounts: m.engine.numUsedAccounts,
868
+ maxLeverage: Number(10000n / (m.params.initialMarginBps || 1n)),
869
+ tradingFeeBps: m.params.tradingFeeBps.toString(),
870
+ paused: m.header.paused,
871
+ resolved: m.header.resolved,
872
+ })), (_key, value) => typeof value === "bigint" ? value.toString() : value)));
873
+ }
874
+ catch (e) {
875
+ return err(e.message);
876
+ }
877
+ });
878
+ // ---------------------------------------------------------------------------
879
+ // Tool: percolator_push_price
880
+ // ---------------------------------------------------------------------------
881
+ server.tool("percolator_push_price", "Push a new oracle price to a Percolator market (admin/oracle authority only). Price in e6 format.", {
882
+ slab: zod_1.z.string().describe("Slab (market) address"),
883
+ price_e6: zod_1.z.string().describe("Oracle price in e6 format (1 USD = 1000000)"),
884
+ network: zod_1.z.enum(["devnet", "mainnet"]).optional(),
885
+ }, async (args) => {
886
+ try {
887
+ const sig = await percolator.pushOraclePrice(args.slab, BigInt(args.price_e6), args.network);
888
+ return ok({ signature: sig });
889
+ }
890
+ catch (e) {
891
+ return err(e.message);
892
+ }
893
+ });
894
+ // ---------------------------------------------------------------------------
895
+ // Tool: percolator_crank
896
+ // ---------------------------------------------------------------------------
897
+ server.tool("percolator_crank", "Run the permissionless keeper crank on a Percolator market. Updates funding rates and processes maintenance.", {
898
+ slab: zod_1.z.string().describe("Slab (market) address"),
899
+ network: zod_1.z.enum(["devnet", "mainnet"]).optional(),
900
+ }, async (args) => {
901
+ try {
902
+ const sig = await percolator.crank(args.slab, args.network);
903
+ return ok({ signature: sig });
904
+ }
905
+ catch (e) {
906
+ return err(e.message);
907
+ }
908
+ });
909
+ // ---------------------------------------------------------------------------
910
+ // Tool: percolator_insurance_lp
911
+ // ---------------------------------------------------------------------------
912
+ // @ts-expect-error — TS2589: deep type instantiation from MCP SDK generics + zod
913
+ server.tool("percolator_insurance_lp", "Manage Percolator insurance fund: create mint, deposit, or withdraw insurance LP tokens.", {
914
+ slab: zod_1.z.string().describe("Slab (market) address"),
915
+ action: zod_1.z.enum(["create_mint", "deposit", "withdraw"]).describe("Action: create_mint (one-time), deposit, or withdraw"),
916
+ amount: zod_1.z.string().optional().describe("Amount in native units (required for deposit/withdraw)"),
917
+ network: zod_1.z.enum(["devnet", "mainnet"]).optional(),
918
+ }, async (args) => {
919
+ try {
920
+ let sig;
921
+ switch (args.action) {
922
+ case "create_mint":
923
+ sig = await percolator.createInsuranceMint(args.slab, args.network);
924
+ break;
925
+ case "deposit":
926
+ if (!args.amount)
927
+ return err("amount is required for deposit");
928
+ sig = await percolator.depositInsuranceLP(args.slab, BigInt(args.amount), args.network);
929
+ break;
930
+ case "withdraw":
931
+ if (!args.amount)
932
+ return err("amount is required for withdraw");
933
+ sig = await percolator.withdrawInsuranceLP(args.slab, BigInt(args.amount), args.network);
934
+ break;
935
+ }
936
+ return ok({ signature: sig });
937
+ }
938
+ catch (e) {
939
+ return err(e.message);
940
+ }
941
+ });
738
942
  // ---------------------------------------------------------------------------
739
943
  // Start server
740
944
  // ---------------------------------------------------------------------------