@okx_ai/okx-trade-mcp 1.2.7 → 1.2.8-beta.2
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/index.js +94 -75
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1534,7 +1534,7 @@ function registerAccountTools() {
|
|
|
1534
1534
|
{
|
|
1535
1535
|
name: "account_get_asset_balance",
|
|
1536
1536
|
module: "account",
|
|
1537
|
-
description: "Get funding account balance (asset account). Different from account_get_balance which queries the trading account.",
|
|
1537
|
+
description: "Get funding account balance (asset account). Different from account_get_balance which queries the trading account. Optionally includes total asset valuation across all account types (trading, funding, earn, etc.).",
|
|
1538
1538
|
isWrite: false,
|
|
1539
1539
|
inputSchema: {
|
|
1540
1540
|
type: "object",
|
|
@@ -1542,17 +1542,41 @@ function registerAccountTools() {
|
|
|
1542
1542
|
ccy: {
|
|
1543
1543
|
type: "string",
|
|
1544
1544
|
description: "e.g. BTC or BTC,ETH. Omit for all."
|
|
1545
|
+
},
|
|
1546
|
+
showValuation: {
|
|
1547
|
+
type: "boolean",
|
|
1548
|
+
description: "Include total asset valuation breakdown by account type (trading/funding/earn). Default false."
|
|
1545
1549
|
}
|
|
1546
1550
|
}
|
|
1547
1551
|
},
|
|
1548
1552
|
handler: async (rawArgs, context) => {
|
|
1549
1553
|
const args = asRecord(rawArgs);
|
|
1550
|
-
const
|
|
1554
|
+
const ccy = readString(args, "ccy");
|
|
1555
|
+
const showValuation = readBoolean(args, "showValuation");
|
|
1556
|
+
if (showValuation) {
|
|
1557
|
+
const balanceResp2 = await context.client.privateGet(
|
|
1558
|
+
"/api/v5/asset/balances",
|
|
1559
|
+
compactObject({ ccy }),
|
|
1560
|
+
privateRateLimit("account_get_asset_balance", 6)
|
|
1561
|
+
);
|
|
1562
|
+
let valuationData = null;
|
|
1563
|
+
try {
|
|
1564
|
+
const valuationResp = await context.client.privateGet(
|
|
1565
|
+
"/api/v5/asset/asset-valuation",
|
|
1566
|
+
{},
|
|
1567
|
+
privateRateLimit("account_get_asset_valuation", 1)
|
|
1568
|
+
);
|
|
1569
|
+
valuationData = valuationResp.data;
|
|
1570
|
+
} catch {
|
|
1571
|
+
}
|
|
1572
|
+
return { ...normalizeResponse(balanceResp2), valuation: valuationData };
|
|
1573
|
+
}
|
|
1574
|
+
const balanceResp = await context.client.privateGet(
|
|
1551
1575
|
"/api/v5/asset/balances",
|
|
1552
|
-
compactObject({ ccy
|
|
1576
|
+
compactObject({ ccy }),
|
|
1553
1577
|
privateRateLimit("account_get_asset_balance", 6)
|
|
1554
1578
|
);
|
|
1555
|
-
return normalizeResponse(
|
|
1579
|
+
return normalizeResponse(balanceResp);
|
|
1556
1580
|
}
|
|
1557
1581
|
},
|
|
1558
1582
|
{
|
|
@@ -2967,6 +2991,39 @@ function registerGridTools() {
|
|
|
2967
2991
|
];
|
|
2968
2992
|
}
|
|
2969
2993
|
var BASE = "/api/v5/tradingBot/dca";
|
|
2994
|
+
function buildTriggerParam(args, algoOrdType) {
|
|
2995
|
+
const triggerStrategy = readString(args, "triggerStrategy") ?? "instant";
|
|
2996
|
+
if (triggerStrategy === "price" && algoOrdType === "spot_dca") {
|
|
2997
|
+
throw new OkxApiError(
|
|
2998
|
+
"triggerStrategy 'price' is only supported for contract_dca. spot_dca supports: instant, rsi",
|
|
2999
|
+
{ code: "VALIDATION", endpoint: `${BASE}/create` }
|
|
3000
|
+
);
|
|
3001
|
+
}
|
|
3002
|
+
const param = { triggerAction: "start", triggerStrategy };
|
|
3003
|
+
if (triggerStrategy === "price") {
|
|
3004
|
+
param["triggerPx"] = requireString(args, "triggerPx");
|
|
3005
|
+
const triggerCond = readString(args, "triggerCond");
|
|
3006
|
+
if (triggerCond) param["triggerCond"] = triggerCond;
|
|
3007
|
+
} else if (triggerStrategy === "rsi") {
|
|
3008
|
+
param["triggerCond"] = requireString(args, "triggerCond");
|
|
3009
|
+
param["thold"] = requireString(args, "thold");
|
|
3010
|
+
param["timeframe"] = requireString(args, "timeframe");
|
|
3011
|
+
param["timePeriod"] = readString(args, "timePeriod") ?? "14";
|
|
3012
|
+
}
|
|
3013
|
+
return param;
|
|
3014
|
+
}
|
|
3015
|
+
function validateSafetyOrderParams(args, maxSafetyOrds) {
|
|
3016
|
+
if (Number(maxSafetyOrds) <= 0) return;
|
|
3017
|
+
const required = ["safetyOrdAmt", "pxSteps", "pxStepsMult", "volMult"];
|
|
3018
|
+
for (const field of required) {
|
|
3019
|
+
if (!readString(args, field)) {
|
|
3020
|
+
throw new OkxApiError(`${field} is required when maxSafetyOrds > 0`, {
|
|
3021
|
+
code: "VALIDATION",
|
|
3022
|
+
endpoint: `${BASE}/create`
|
|
3023
|
+
});
|
|
3024
|
+
}
|
|
3025
|
+
}
|
|
3026
|
+
}
|
|
2970
3027
|
function normalizeWrite2(response) {
|
|
2971
3028
|
const data = response.data;
|
|
2972
3029
|
if (Array.isArray(data) && data.length > 0) {
|
|
@@ -3036,57 +3093,11 @@ function registerDcaTools() {
|
|
|
3036
3093
|
endpoint: `${BASE}/create`
|
|
3037
3094
|
});
|
|
3038
3095
|
}
|
|
3039
|
-
const
|
|
3040
|
-
if (triggerStrategy === "price" && algoOrdType === "spot_dca") {
|
|
3041
|
-
throw new OkxApiError("triggerStrategy 'price' is only supported for contract_dca. spot_dca supports: instant, rsi", {
|
|
3042
|
-
code: "VALIDATION",
|
|
3043
|
-
endpoint: `${BASE}/create`
|
|
3044
|
-
});
|
|
3045
|
-
}
|
|
3046
|
-
const triggerParam = {
|
|
3047
|
-
triggerAction: "start",
|
|
3048
|
-
triggerStrategy
|
|
3049
|
-
};
|
|
3050
|
-
if (triggerStrategy === "price") {
|
|
3051
|
-
triggerParam["triggerPx"] = requireString(args, "triggerPx");
|
|
3052
|
-
const triggerCond = readString(args, "triggerCond");
|
|
3053
|
-
if (triggerCond) {
|
|
3054
|
-
triggerParam["triggerCond"] = triggerCond;
|
|
3055
|
-
}
|
|
3056
|
-
} else if (triggerStrategy === "rsi") {
|
|
3057
|
-
triggerParam["triggerCond"] = requireString(args, "triggerCond");
|
|
3058
|
-
triggerParam["thold"] = requireString(args, "thold");
|
|
3059
|
-
triggerParam["timeframe"] = requireString(args, "timeframe");
|
|
3060
|
-
const timePeriod = readString(args, "timePeriod");
|
|
3061
|
-
triggerParam["timePeriod"] = timePeriod ?? "14";
|
|
3062
|
-
}
|
|
3096
|
+
const triggerParam = buildTriggerParam(args, algoOrdType);
|
|
3063
3097
|
const maxSafetyOrds = requireString(args, "maxSafetyOrds");
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
code: "VALIDATION",
|
|
3068
|
-
endpoint: `${BASE}/create`
|
|
3069
|
-
});
|
|
3070
|
-
}
|
|
3071
|
-
if (!readString(args, "pxSteps")) {
|
|
3072
|
-
throw new OkxApiError("pxSteps is required when maxSafetyOrds > 0", {
|
|
3073
|
-
code: "VALIDATION",
|
|
3074
|
-
endpoint: `${BASE}/create`
|
|
3075
|
-
});
|
|
3076
|
-
}
|
|
3077
|
-
if (!readString(args, "pxStepsMult")) {
|
|
3078
|
-
throw new OkxApiError("pxStepsMult is required when maxSafetyOrds > 0", {
|
|
3079
|
-
code: "VALIDATION",
|
|
3080
|
-
endpoint: `${BASE}/create`
|
|
3081
|
-
});
|
|
3082
|
-
}
|
|
3083
|
-
if (!readString(args, "volMult")) {
|
|
3084
|
-
throw new OkxApiError("volMult is required when maxSafetyOrds > 0", {
|
|
3085
|
-
code: "VALIDATION",
|
|
3086
|
-
endpoint: `${BASE}/create`
|
|
3087
|
-
});
|
|
3088
|
-
}
|
|
3089
|
-
}
|
|
3098
|
+
validateSafetyOrderParams(args, maxSafetyOrds);
|
|
3099
|
+
const allowReinvestRaw = args["allowReinvest"];
|
|
3100
|
+
const allowReinvest = allowReinvestRaw !== void 0 ? allowReinvestRaw === true || allowReinvestRaw === "true" : void 0;
|
|
3090
3101
|
const response = await context.client.privatePost(
|
|
3091
3102
|
`${BASE}/create`,
|
|
3092
3103
|
compactObject({
|
|
@@ -3103,7 +3114,7 @@ function registerDcaTools() {
|
|
|
3103
3114
|
tpPct: requireString(args, "tpPct"),
|
|
3104
3115
|
slPct: readString(args, "slPct"),
|
|
3105
3116
|
slMode: readString(args, "slMode"),
|
|
3106
|
-
allowReinvest
|
|
3117
|
+
allowReinvest,
|
|
3107
3118
|
triggerParams: [triggerParam],
|
|
3108
3119
|
tag: context.config.sourceTag,
|
|
3109
3120
|
algoClOrdId: readString(args, "algoClOrdId"),
|
|
@@ -4663,6 +4674,7 @@ function registerFuturesTools() {
|
|
|
4663
4674
|
}
|
|
4664
4675
|
];
|
|
4665
4676
|
}
|
|
4677
|
+
var TWO_DAYS_MS = 2 * 24 * 60 * 60 * 1e3;
|
|
4666
4678
|
function registerMarketTools() {
|
|
4667
4679
|
return [
|
|
4668
4680
|
{
|
|
@@ -4762,7 +4774,7 @@ function registerMarketTools() {
|
|
|
4762
4774
|
{
|
|
4763
4775
|
name: "market_get_candles",
|
|
4764
4776
|
module: "market",
|
|
4765
|
-
description: "Get candlestick (OHLCV) data for an instrument.
|
|
4777
|
+
description: "Get candlestick (OHLCV) data for an instrument. Automatically retrieves historical data (back to 2021) when requesting older time ranges. Use the `after` parameter to paginate back in time (the old `history` parameter has been removed). IMPORTANT: Before fetching with `after`/`before`, estimate the number of candles: time_range_ms / bar_interval_ms. If the estimate exceeds ~500 candles, inform the user of the estimated count and ask for confirmation before proceeding.",
|
|
4766
4778
|
isWrite: false,
|
|
4767
4779
|
inputSchema: {
|
|
4768
4780
|
type: "object",
|
|
@@ -4787,29 +4799,29 @@ function registerMarketTools() {
|
|
|
4787
4799
|
limit: {
|
|
4788
4800
|
type: "number",
|
|
4789
4801
|
description: "Max results (default 100)"
|
|
4790
|
-
},
|
|
4791
|
-
history: {
|
|
4792
|
-
type: "boolean",
|
|
4793
|
-
description: "true=older historical data beyond recent window"
|
|
4794
4802
|
}
|
|
4795
4803
|
},
|
|
4796
4804
|
required: ["instId"]
|
|
4797
4805
|
},
|
|
4798
4806
|
handler: async (rawArgs, context) => {
|
|
4799
4807
|
const args = asRecord(rawArgs);
|
|
4800
|
-
const
|
|
4801
|
-
const
|
|
4802
|
-
const
|
|
4803
|
-
|
|
4804
|
-
|
|
4805
|
-
|
|
4806
|
-
|
|
4807
|
-
|
|
4808
|
-
|
|
4809
|
-
|
|
4810
|
-
|
|
4811
|
-
|
|
4812
|
-
|
|
4808
|
+
const afterTs = readString(args, "after");
|
|
4809
|
+
const beforeTs = readString(args, "before");
|
|
4810
|
+
const query = compactObject({
|
|
4811
|
+
instId: requireString(args, "instId"),
|
|
4812
|
+
bar: readString(args, "bar"),
|
|
4813
|
+
after: afterTs,
|
|
4814
|
+
before: beforeTs,
|
|
4815
|
+
limit: readNumber(args, "limit")
|
|
4816
|
+
});
|
|
4817
|
+
const rateLimit = publicRateLimit("market_get_candles", 40);
|
|
4818
|
+
const hasTimestamp = afterTs !== void 0 || beforeTs !== void 0;
|
|
4819
|
+
const useHistory = afterTs !== void 0 && Number(afterTs) < Date.now() - TWO_DAYS_MS;
|
|
4820
|
+
const path4 = useHistory ? "/api/v5/market/history-candles" : "/api/v5/market/candles";
|
|
4821
|
+
const response = await context.client.publicGet(path4, query, rateLimit);
|
|
4822
|
+
if (!useHistory && hasTimestamp && Array.isArray(response.data) && response.data.length === 0) {
|
|
4823
|
+
return normalizeResponse(await context.client.publicGet("/api/v5/market/history-candles", query, rateLimit));
|
|
4824
|
+
}
|
|
4813
4825
|
return normalizeResponse(response);
|
|
4814
4826
|
}
|
|
4815
4827
|
},
|
|
@@ -5662,7 +5674,14 @@ function registerOptionTools() {
|
|
|
5662
5674
|
handler: async (rawArgs, context) => {
|
|
5663
5675
|
const args = asRecord(rawArgs);
|
|
5664
5676
|
const status = readString(args, "status") ?? "live";
|
|
5665
|
-
|
|
5677
|
+
let path4;
|
|
5678
|
+
if (status === "archive") {
|
|
5679
|
+
path4 = "/api/v5/trade/orders-history-archive";
|
|
5680
|
+
} else if (status === "history") {
|
|
5681
|
+
path4 = "/api/v5/trade/orders-history";
|
|
5682
|
+
} else {
|
|
5683
|
+
path4 = "/api/v5/trade/orders-pending";
|
|
5684
|
+
}
|
|
5666
5685
|
const response = await context.client.privateGet(
|
|
5667
5686
|
path4,
|
|
5668
5687
|
compactObject({
|
|
@@ -7070,7 +7089,7 @@ var _require = createRequire(import.meta.url);
|
|
|
7070
7089
|
var pkg = _require("../package.json");
|
|
7071
7090
|
var SERVER_NAME = "okx-trade-mcp";
|
|
7072
7091
|
var SERVER_VERSION = pkg.version;
|
|
7073
|
-
var GIT_HASH = true ? "
|
|
7092
|
+
var GIT_HASH = true ? "f9ea608" : "dev";
|
|
7074
7093
|
|
|
7075
7094
|
// src/server.ts
|
|
7076
7095
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|