@michaleffffff/mcp-trading-server 2.9.2 → 3.0.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.
package/CHANGELOG.md ADDED
@@ -0,0 +1,22 @@
1
+ # Changelog
2
+
3
+ ## 3.0.0 - 2026-03-17
4
+
5
+ ### Breaking Changes
6
+ - Removed legacy account balance tools:
7
+ - `get_account_info`
8
+ - `get_balances`
9
+ - `get_margin_balance`
10
+ - Added unified replacement:
11
+ - `get_account`
12
+
13
+ ### Added
14
+ - `TOOL_EXAMPLES.md` handbook with practical examples for all exposed tools.
15
+ - Standardized AI-friendly error envelope with `status/error/code/hint/action`.
16
+
17
+ ### Changed
18
+ - Updated prompts and README to use `get_account` and the new examples handbook.
19
+ - Improved `search_market` behavior for empty keyword usage.
20
+ - Read-only tool responses now surface non-zero SDK `code` as structured MCP errors.
21
+ - `get_account` now supports partial snapshots (`meta.partial=true`) when one section fails.
22
+ - Regression suite now validates `get_account` and handles optional `cancel_all_orders` mutation path safely.
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # MYX MCP Trading Server v2
1
+ # MYX MCP Trading Server
2
2
 
3
3
  A production-ready MCP (Model Context Protocol) server that exposes tools, resources, and prompts for AI agents.
4
4
 
@@ -6,6 +6,15 @@ This server allows AI assistants (like Claude Desktop, Cursor, etc.) to securely
6
6
 
7
7
  ---
8
8
 
9
+ # Release Notes
10
+
11
+ - Current release: **3.0.0**
12
+ - Breaking change: `get_account_info`, `get_balances`, and `get_margin_balance` were removed.
13
+ - Replacement: use `get_account` for unified wallet + trading-account balance view.
14
+ - Detailed history: `CHANGELOG.md`
15
+
16
+ ---
17
+
9
18
  # Features
10
19
 
11
20
  * MCP compliant server
@@ -115,7 +124,8 @@ The server will run using `stdio` transport and can be connected by any MCP-comp
115
124
  2. **Configure env**: Copy `.env.example` to `.env` and fill in `PRIVATE_KEY`, `RPC_URL`, etc.
116
125
  3. **Start the server**: Run `npm run build` then `npm run start` (use `npm run dev` for development).
117
126
  4. **Configure your MCP client**: Set `command/args/env` in your MCP client (see Claude Desktop example below).
118
- 5. **Common flow**: Use `search_market` to get `poolId`, then optionally `get_market_price` / `get_oracle_price` to view prices, and finally use `open_position_simple` (recommended) to open a position.
127
+ 5. **Common flow**: Use `search_market` (or `get_market_list`) to get `poolId`, then optionally `get_market_price` / `get_oracle_price` to view prices, and finally use `open_position_simple` (recommended) to open a position.
128
+ 6. **Tool examples**: See `TOOL_EXAMPLES.md` for practical examples for every tool, common workflows, and parameter-unit guidance.
119
129
 
120
130
  **Minimal open position example:**
121
131
 
@@ -152,6 +162,57 @@ The server will run using `stdio` transport and can be connected by any MCP-comp
152
162
  - **Slippage**: `slippagePct` uses 4-decimal raw units: `100` = `1%`, `50` = `0.5%`, `1000` = `10%`.
153
163
  - **Note**: Some account-transfer tools (e.g. `account_deposit`, `account_withdraw`, `check_approval`) use **raw integer strings**.
154
164
 
165
+ ## P0 Reliability Contract (AI-friendly)
166
+
167
+ Starting with P0, tool failures are normalized to a structured JSON envelope:
168
+
169
+ ```json
170
+ {
171
+ "status": "error",
172
+ "error": {
173
+ "tool": "execute_trade",
174
+ "code": "INVALID_PARAM",
175
+ "message": "Invalid arguments for tool \"execute_trade\".",
176
+ "hint": "Fix \"positionId\": positionId must be empty string for new position, or a bytes32 hex string.",
177
+ "action": "Call list_tools and resend valid arguments.",
178
+ "details": {
179
+ "issues": [
180
+ {
181
+ "field": "positionId",
182
+ "code": "custom",
183
+ "message": "positionId must be empty string for new position, or a bytes32 hex string."
184
+ }
185
+ ]
186
+ }
187
+ }
188
+ }
189
+ ```
190
+
191
+ Common error codes:
192
+ - `INVALID_PARAM`: input schema/field error.
193
+ - `INSUFFICIENT_BALANCE`: wallet or trading-account amount is not enough.
194
+ - `INSUFFICIENT_ALLOWANCE`: token approval/allowance is insufficient.
195
+ - `NOT_FOUND`: bad tool name or bad identifiers (`poolId`, `orderId`, `marketId`).
196
+ - `TIMEOUT`: tx confirmation/query timeout.
197
+ - `NETWORK_ERROR`: RPC or network issue.
198
+
199
+ Search behavior in P0:
200
+ - `search_market` now accepts empty `keyword` and returns active markets.
201
+ - When `search_market` returns empty/unstable data, server-side fallback uses SDK `api.getMarketList()` and `api.getPoolList()` to rebuild active-market results.
202
+ - For robust discovery, you can also call `get_market_list` directly.
203
+
204
+ Example:
205
+
206
+ ```json
207
+ {
208
+ "name": "search_market",
209
+ "arguments": {
210
+ "keyword": "",
211
+ "limit": 20
212
+ }
213
+ }
214
+ ```
215
+
155
216
  ---
156
217
 
157
218
  ## Secure Deployment Template (Systemd Example)
@@ -223,7 +284,9 @@ Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
223
284
 
224
285
  # Tools
225
286
 
226
- The server exposes 38 tools categorized for AI:
287
+ The server exposes 39 tools categorized for AI:
288
+
289
+ For practical tool-by-tool examples, see: `TOOL_EXAMPLES.md`
227
290
 
228
291
  ### Trading Operations
229
292
  * **open_position_simple**: High-level open position helper (recommended). Computes price/size/tradingFee internally.
@@ -248,9 +311,14 @@ The server exposes 38 tools categorized for AI:
248
311
 
249
312
  ### Account & Portfolio
250
313
  * **get_positions**: Get all open positions for the current account.
251
- * **get_balances**: Get the account balances for different tokens.
314
+ * **get_account**: Unified account snapshot. Clearly separates **wallet balance** and **trading-account balance** (provide `poolId` for full trading-account metrics).
252
315
  * **get_account_vip_info**: Query account VIP tier details.
253
- * **position_history**, **open_orders**...
316
+ * **get_position_history**, **get_open_orders**, **get_order_history**...
317
+
318
+ `get_account` note:
319
+ - `poolId` omitted: wallet-focused snapshot only.
320
+ - `poolId` provided: wallet + trading-account + margin snapshot.
321
+ - If one section fails (wallet or trading-account), the tool may return a **partial** snapshot with `meta.partial=true` and section-level `error` details.
254
322
 
255
323
  ### Liquidity Provision (LP)
256
324
  * **manage_liquidity**: Add or withdraw liquidity from a BASE or QUOTE pool.
@@ -297,6 +365,34 @@ Example MCP client usage workflow:
297
365
  3. Call the `search_market` tool (e.g., `keyword: "ETH"`) to retrieve the `poolId`.
298
366
  4. Call `open_position_simple` passing the retrieved `poolId` to open a 10x long position.
299
367
 
368
+ ## Limit Order Lifecycle (P0)
369
+
370
+ Use this query/mutation loop for limit-order management:
371
+
372
+ 1. Place order with `execute_trade` (`orderType=LIMIT`).
373
+ 2. Query active orders with `get_open_orders`.
374
+ 3. Check historical fills/cancellations with `get_order_history`.
375
+ 4. Cancel one order via `cancel_order` or batch via `cancel_all_orders`.
376
+
377
+ Minimal query examples:
378
+
379
+ ```json
380
+ {
381
+ "name": "get_open_orders",
382
+ "arguments": {}
383
+ }
384
+ ```
385
+
386
+ ```json
387
+ {
388
+ "name": "get_order_history",
389
+ "arguments": {
390
+ "poolId": "0x...",
391
+ "limit": 20
392
+ }
393
+ }
394
+ ```
395
+
300
396
  Example integration scripts are located in:
301
397
  `examples/basicUsage.ts`
302
398
 
@@ -0,0 +1,536 @@
1
+ # MYX MCP Tool Examples Handbook
2
+
3
+ This handbook is designed for AI assistants and integrators.
4
+ It includes:
5
+ - clear parameter unit rules,
6
+ - common end-to-end workflows,
7
+ - at least one practical call example for every exposed tool.
8
+
9
+ > All examples use MCP call payload shape:
10
+ > `{ "name": "<tool_name>", "arguments": { ... } }`
11
+
12
+ ---
13
+
14
+ ## 1) Parameter Units & Precision (Important)
15
+
16
+ - **Human-readable by default** (many trading tools): `"100"` means 100 quote tokens (e.g., USDC).
17
+ - **Raw-unit override**: use `"raw:<integer>"` when supported by the tool.
18
+ - **Price precision**: many low-level trading paths expect **30-decimal raw price**.
19
+ - **Token amount precision**: depends on token decimals (e.g., USDC often 6).
20
+ - **Slippage (`slippagePct`)**: 4-decimal integer style (e.g., `100 = 1%`, `50 = 0.5%`).
21
+ - **Approval tool** (`check_approval`) uses **raw integer amount**.
22
+
23
+ ---
24
+
25
+ ## 2) Common Operation Flows
26
+
27
+ ## Flow A: Discover Market → Open Position (Recommended)
28
+ 1. `search_market` (keyword or empty keyword list)
29
+ 2. `get_market_detail` / `get_market_price`
30
+ 3. `get_account` (with `poolId`)
31
+ 4. `open_position_simple` (preferred high-level execution)
32
+
33
+ ## Flow B: Limit Order Lifecycle
34
+ 1. `execute_trade` with `orderType=LIMIT`
35
+ 2. `get_open_orders`
36
+ 3. `get_order_history`
37
+ 4. `cancel_order` or `cancel_all_orders`
38
+
39
+ ## Flow C: Balance Troubleshooting
40
+ 1. `get_account` (without `poolId`) → wallet view
41
+ 2. `get_account` (with `poolId`) → trading-account + margin
42
+ 3. `account_deposit` / `account_withdraw` as needed
43
+
44
+ ---
45
+
46
+ ## 3) Tool-by-Tool Practical Examples
47
+
48
+ ## Trading Operations
49
+
50
+ ### `open_position_simple`
51
+ ```json
52
+ {
53
+ "name": "open_position_simple",
54
+ "arguments": {
55
+ "keyword": "BTC",
56
+ "direction": "LONG",
57
+ "collateralAmount": "100",
58
+ "leverage": 5,
59
+ "orderType": "MARKET",
60
+ "autoDeposit": false,
61
+ "dryRun": true
62
+ }
63
+ }
64
+ ```
65
+
66
+ ### `execute_trade`
67
+ ```json
68
+ {
69
+ "name": "execute_trade",
70
+ "arguments": {
71
+ "poolId": "0xPOOL_ID",
72
+ "positionId": "",
73
+ "orderType": "MARKET",
74
+ "direction": "LONG",
75
+ "collateralAmount": "100",
76
+ "size": "0.01",
77
+ "price": "65000",
78
+ "timeInForce": 0,
79
+ "postOnly": false,
80
+ "slippagePct": "100",
81
+ "executionFeeToken": "0xQUOTE_TOKEN",
82
+ "leverage": 5,
83
+ "tradingFee": "raw:100000",
84
+ "marketId": "0xMARKET_ID"
85
+ }
86
+ }
87
+ ```
88
+
89
+ ### `close_position`
90
+ ```json
91
+ {
92
+ "name": "close_position",
93
+ "arguments": {
94
+ "poolId": "0xPOOL_ID",
95
+ "positionId": "0xPOSITION_ID",
96
+ "orderType": "MARKET",
97
+ "direction": "LONG",
98
+ "collateralAmount": "0",
99
+ "size": "0.01",
100
+ "price": "65000",
101
+ "timeInForce": 0,
102
+ "postOnly": false,
103
+ "slippagePct": "100",
104
+ "executionFeeToken": "0xQUOTE_TOKEN",
105
+ "leverage": 5
106
+ }
107
+ }
108
+ ```
109
+
110
+ ### `close_all_positions`
111
+ ```json
112
+ {
113
+ "name": "close_all_positions",
114
+ "arguments": {
115
+ "poolId": "0xPOOL_ID",
116
+ "slippagePct": "200"
117
+ }
118
+ }
119
+ ```
120
+
121
+ ### `cancel_order`
122
+ ```json
123
+ {
124
+ "name": "cancel_order",
125
+ "arguments": {
126
+ "orderId": "0xORDER_ID"
127
+ }
128
+ }
129
+ ```
130
+
131
+ ### `cancel_all_orders`
132
+ ```json
133
+ {
134
+ "name": "cancel_all_orders",
135
+ "arguments": {
136
+ "orderIds": [
137
+ "0xORDER_ID_1",
138
+ "0xORDER_ID_2"
139
+ ]
140
+ }
141
+ }
142
+ ```
143
+
144
+ ### `set_tp_sl`
145
+ ```json
146
+ {
147
+ "name": "set_tp_sl",
148
+ "arguments": {
149
+ "poolId": "0xPOOL_ID",
150
+ "positionId": "0xPOSITION_ID",
151
+ "direction": "LONG",
152
+ "leverage": 5,
153
+ "executionFeeToken": "0xQUOTE_TOKEN",
154
+ "tpTriggerType": "GTE",
155
+ "tpPrice": "70000",
156
+ "tpSize": "0.01",
157
+ "slTriggerType": "LTE",
158
+ "slPrice": "60000",
159
+ "slSize": "0.01",
160
+ "slippagePct": "100"
161
+ }
162
+ }
163
+ ```
164
+
165
+ ### `update_order_tp_sl`
166
+ ```json
167
+ {
168
+ "name": "update_order_tp_sl",
169
+ "arguments": {
170
+ "orderId": "0xORDER_ID",
171
+ "marketId": "0xMARKET_ID",
172
+ "size": "0.01",
173
+ "price": "65000",
174
+ "tpPrice": "70000",
175
+ "tpSize": "0.005",
176
+ "slPrice": "60000",
177
+ "slSize": "0.005",
178
+ "useOrderCollateral": true,
179
+ "quoteToken": "0xQUOTE_TOKEN"
180
+ }
181
+ }
182
+ ```
183
+
184
+ ### `adjust_margin`
185
+ ```json
186
+ {
187
+ "name": "adjust_margin",
188
+ "arguments": {
189
+ "poolId": "0xPOOL_ID",
190
+ "positionId": "0xPOSITION_ID",
191
+ "adjustAmount": "1000000"
192
+ }
193
+ }
194
+ ```
195
+
196
+ ### `check_approval`
197
+ ```json
198
+ {
199
+ "name": "check_approval",
200
+ "arguments": {
201
+ "amount": "100000000",
202
+ "autoApprove": false
203
+ }
204
+ }
205
+ ```
206
+
207
+ ### `get_user_trading_fee_rate`
208
+ ```json
209
+ {
210
+ "name": "get_user_trading_fee_rate",
211
+ "arguments": {
212
+ "assetClass": 1,
213
+ "riskTier": 1
214
+ }
215
+ }
216
+ ```
217
+
218
+ ### `get_network_fee`
219
+ ```json
220
+ {
221
+ "name": "get_network_fee",
222
+ "arguments": {
223
+ "marketId": "0xMARKET_ID"
224
+ }
225
+ }
226
+ ```
227
+
228
+ ## Market Data
229
+
230
+ ### `search_market`
231
+ ```json
232
+ {
233
+ "name": "search_market",
234
+ "arguments": {
235
+ "keyword": "ETH",
236
+ "limit": 10
237
+ }
238
+ }
239
+ ```
240
+
241
+ ### `search_market` (list active markets)
242
+ ```json
243
+ {
244
+ "name": "search_market",
245
+ "arguments": {
246
+ "keyword": "",
247
+ "limit": 20
248
+ }
249
+ }
250
+ ```
251
+ Note: this tool may internally fallback to SDK `api.getMarketList()` / `api.getPoolList()` when direct search is empty.
252
+
253
+ ### `get_market_list`
254
+ ```json
255
+ {
256
+ "name": "get_market_list",
257
+ "arguments": {
258
+ "limit": 50
259
+ }
260
+ }
261
+ ```
262
+
263
+ ### `get_market_list_raw`
264
+ ```json
265
+ {
266
+ "name": "get_market_list_raw",
267
+ "arguments": {}
268
+ }
269
+ ```
270
+
271
+ ### `get_pool_list`
272
+ ```json
273
+ {
274
+ "name": "get_pool_list",
275
+ "arguments": {}
276
+ }
277
+ ```
278
+
279
+ ### `get_market_detail`
280
+ ```json
281
+ {
282
+ "name": "get_market_detail",
283
+ "arguments": {
284
+ "poolId": "BTC"
285
+ }
286
+ }
287
+ ```
288
+
289
+ ### `get_pool_info`
290
+ ```json
291
+ {
292
+ "name": "get_pool_info",
293
+ "arguments": {
294
+ "poolId": "0xPOOL_ID"
295
+ }
296
+ }
297
+ ```
298
+
299
+ ### `get_liquidity_info`
300
+ ```json
301
+ {
302
+ "name": "get_liquidity_info",
303
+ "arguments": {
304
+ "poolId": "0xPOOL_ID",
305
+ "marketPrice": "6500000000000000000000000000000000"
306
+ }
307
+ }
308
+ ```
309
+
310
+ ### `get_pool_level_config`
311
+ ```json
312
+ {
313
+ "name": "get_pool_level_config",
314
+ "arguments": {
315
+ "poolId": "0xPOOL_ID"
316
+ }
317
+ }
318
+ ```
319
+
320
+ ### `get_market_price`
321
+ ```json
322
+ {
323
+ "name": "get_market_price",
324
+ "arguments": {
325
+ "poolId": "0xPOOL_ID"
326
+ }
327
+ }
328
+ ```
329
+
330
+ ### `get_oracle_price`
331
+ ```json
332
+ {
333
+ "name": "get_oracle_price",
334
+ "arguments": {
335
+ "poolId": "0xPOOL_ID"
336
+ }
337
+ }
338
+ ```
339
+
340
+ ### `get_kline`
341
+ ```json
342
+ {
343
+ "name": "get_kline",
344
+ "arguments": {
345
+ "poolId": "0xPOOL_ID",
346
+ "interval": "15m",
347
+ "limit": 100
348
+ }
349
+ }
350
+ ```
351
+
352
+ ### `get_kline_latest_bar`
353
+ ```json
354
+ {
355
+ "name": "get_kline_latest_bar",
356
+ "arguments": {
357
+ "poolId": "0xPOOL_ID",
358
+ "interval": "1m"
359
+ }
360
+ }
361
+ ```
362
+
363
+ ### `get_all_tickers`
364
+ ```json
365
+ {
366
+ "name": "get_all_tickers",
367
+ "arguments": {}
368
+ }
369
+ ```
370
+
371
+ ### `get_pool_symbol_all`
372
+ ```json
373
+ {
374
+ "name": "get_pool_symbol_all",
375
+ "arguments": {}
376
+ }
377
+ ```
378
+
379
+ ### `get_base_detail`
380
+ ```json
381
+ {
382
+ "name": "get_base_detail",
383
+ "arguments": {
384
+ "baseAddress": "0xBASE_TOKEN"
385
+ }
386
+ }
387
+ ```
388
+
389
+ ## Account & Query
390
+
391
+ ### `get_account`
392
+ ```json
393
+ {
394
+ "name": "get_account",
395
+ "arguments": {
396
+ "poolId": "0xPOOL_ID"
397
+ }
398
+ }
399
+ ```
400
+
401
+ If one section fails, check `data.meta.partial` and section-level `error` fields.
402
+
403
+ ### `get_account` (wallet-only view)
404
+ ```json
405
+ {
406
+ "name": "get_account",
407
+ "arguments": {}
408
+ }
409
+ ```
410
+
411
+ ### `get_positions`
412
+ ```json
413
+ {
414
+ "name": "get_positions",
415
+ "arguments": {}
416
+ }
417
+ ```
418
+
419
+ ### `get_open_orders`
420
+ ```json
421
+ {
422
+ "name": "get_open_orders",
423
+ "arguments": {}
424
+ }
425
+ ```
426
+
427
+ ### `get_order_history`
428
+ ```json
429
+ {
430
+ "name": "get_order_history",
431
+ "arguments": {
432
+ "poolId": "0xPOOL_ID",
433
+ "limit": 20
434
+ }
435
+ }
436
+ ```
437
+
438
+ ### `get_position_history`
439
+ ```json
440
+ {
441
+ "name": "get_position_history",
442
+ "arguments": {
443
+ "poolId": "0xPOOL_ID",
444
+ "limit": 20
445
+ }
446
+ }
447
+ ```
448
+
449
+ ### `get_trade_flow`
450
+ ```json
451
+ {
452
+ "name": "get_trade_flow",
453
+ "arguments": {
454
+ "limit": 20
455
+ }
456
+ }
457
+ ```
458
+
459
+ ### `get_account_vip_info`
460
+ ```json
461
+ {
462
+ "name": "get_account_vip_info",
463
+ "arguments": {}
464
+ }
465
+ ```
466
+
467
+ ### `account_deposit`
468
+ ```json
469
+ {
470
+ "name": "account_deposit",
471
+ "arguments": {
472
+ "amount": "100",
473
+ "tokenAddress": "0xQUOTE_TOKEN"
474
+ }
475
+ }
476
+ ```
477
+
478
+ ### `account_withdraw`
479
+ ```json
480
+ {
481
+ "name": "account_withdraw",
482
+ "arguments": {
483
+ "poolId": "0xPOOL_ID",
484
+ "amount": "50",
485
+ "isQuoteToken": true
486
+ }
487
+ }
488
+ ```
489
+
490
+ ## Liquidity / LP
491
+
492
+ ### `manage_liquidity`
493
+ ```json
494
+ {
495
+ "name": "manage_liquidity",
496
+ "arguments": {
497
+ "action": "deposit",
498
+ "poolType": "QUOTE",
499
+ "poolId": "0xPOOL_ID",
500
+ "amount": 100,
501
+ "slippage": 0.01
502
+ }
503
+ }
504
+ ```
505
+
506
+ ### `get_lp_price`
507
+ ```json
508
+ {
509
+ "name": "get_lp_price",
510
+ "arguments": {
511
+ "poolType": "QUOTE",
512
+ "poolId": "0xPOOL_ID"
513
+ }
514
+ }
515
+ ```
516
+
517
+ ### `create_perp_market`
518
+ ```json
519
+ {
520
+ "name": "create_perp_market",
521
+ "arguments": {
522
+ "baseToken": "0xBASE_TOKEN",
523
+ "marketId": "0xMARKET_CONFIG_HASH"
524
+ }
525
+ }
526
+ ```
527
+
528
+ ---
529
+
530
+ ## 4) Practical Tips for AI Agents
531
+
532
+ - Always discover/validate `poolId` before mutation tools.
533
+ - Prefer `open_position_simple` for new-position UX unless strict low-level control is required.
534
+ - Before trading, call `get_account` and `check_approval`.
535
+ - For limit-order support conversations, include `get_open_orders` and `get_order_history` in the loop.
536
+ - If any mutation fails, read structured error fields: `error.code`, `error.hint`, `error.action`.