@aihubspot/agent-trade-mcp 0.1.3 → 0.1.4
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/README.md +10 -0
- package/dist/index.js +18 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -24,3 +24,13 @@ Setup registers the currently installed MCP binary through its absolute Node run
|
|
|
24
24
|
Use `spot_prepare_market_buy` or `margin_prepare_market_buy` only with `quoteAmount` (for example, the exact USDT amount to spend for `ETHUSDT`). Use `spot_prepare_market_sell` or `margin_prepare_market_sell` only with `baseQuantity` (the exact ETH amount to sell for `ETHUSDT`). A market buy cannot guarantee an exact base-asset quantity; it must never reinterpret a requested base quantity as a quote amount.
|
|
25
25
|
|
|
26
26
|
Before any order preview, MCP lazily loads `/sapi/v2/symbols` once per local profile and caches the symbol rules in memory for five minutes. Known quantity/price precision and limit-order minimum violations are rejected before confirmation.
|
|
27
|
+
|
|
28
|
+
## Ticker response
|
|
29
|
+
|
|
30
|
+
All read tools return `{ "ok": true, "data": ... }` in one of these stable forms:
|
|
31
|
+
|
|
32
|
+
- Arrays: `{ "dataType": "array", "items": [...], "count": 500 }`
|
|
33
|
+
- Objects: `{ "dataType": "object", "value": { ... } }`
|
|
34
|
+
- Scalars: `{ "dataType": "scalar", "value": "..." }`
|
|
35
|
+
|
|
36
|
+
`market_get_ticker` additionally exposes `data.tickers` as an alias of `data.items`. Check `data.dataType` before formatting; do not infer raw OpenAPI nesting.
|
package/dist/index.js
CHANGED
|
@@ -917,7 +917,7 @@ var marketTools = [
|
|
|
917
917
|
{
|
|
918
918
|
name: "market_get_ticker",
|
|
919
919
|
title: "Get Spot Ticker",
|
|
920
|
-
description: "Get spot ticker data. Pass symbol or symbols when filtering is needed.",
|
|
920
|
+
description: "Get spot ticker data. Pass symbol or symbols when filtering is needed. The raw OpenAPI response is a ticker array.",
|
|
921
921
|
cliPath: ["market", "ticker"],
|
|
922
922
|
module: "spot-common",
|
|
923
923
|
access: "public",
|
|
@@ -2129,6 +2129,19 @@ var CONFIRM_ACTION_TOOL = "confirm_action";
|
|
|
2129
2129
|
function result(data) {
|
|
2130
2130
|
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
2131
2131
|
}
|
|
2132
|
+
function formatMcpData(toolName, data) {
|
|
2133
|
+
if (Array.isArray(data)) {
|
|
2134
|
+
return {
|
|
2135
|
+
dataType: "array",
|
|
2136
|
+
items: data,
|
|
2137
|
+
count: data.length,
|
|
2138
|
+
...toolName === "market_get_ticker" ? { tickers: data } : {}
|
|
2139
|
+
};
|
|
2140
|
+
}
|
|
2141
|
+
if (data === null || data === void 0) return { dataType: "null", value: null };
|
|
2142
|
+
if (typeof data === "object") return { dataType: "object", value: data };
|
|
2143
|
+
return { dataType: "scalar", value: data };
|
|
2144
|
+
}
|
|
2132
2145
|
function toMcpErrorResult(error) {
|
|
2133
2146
|
const payload = toAiHubErrorPayload(error);
|
|
2134
2147
|
return { isError: true, content: [{ type: "text", text: JSON.stringify({ ok: false, ...payload }) }] };
|
|
@@ -2137,7 +2150,7 @@ function toMcpTool(tool) {
|
|
|
2137
2150
|
return {
|
|
2138
2151
|
name: tool.name,
|
|
2139
2152
|
title: tool.title,
|
|
2140
|
-
description: tool.description,
|
|
2153
|
+
description: `${tool.description}${tool.operation === "read" ? " Successful MCP output is always { ok: true, data: ... }. For list results, use data.items and data.count (market_get_ticker also provides data.tickers); for object results, use data.value. Check data.dataType before formatting." : ""}`,
|
|
2141
2154
|
inputSchema: tool.inputSchema,
|
|
2142
2155
|
annotations: {
|
|
2143
2156
|
readOnlyHint: tool.operation === "read",
|
|
@@ -2164,10 +2177,10 @@ function createServer(profileName, readOnly) {
|
|
|
2164
2177
|
const registry = createToolRegistry();
|
|
2165
2178
|
const writeExecutor = new ToolWriteExecutor(registry);
|
|
2166
2179
|
const server = new Server(
|
|
2167
|
-
{ name: "ai-hub-agent-trade", version: "0.1.
|
|
2180
|
+
{ name: "ai-hub-agent-trade", version: "0.1.4" },
|
|
2168
2181
|
{
|
|
2169
2182
|
capabilities: { tools: {} },
|
|
2170
|
-
instructions: "For every state-changing action, call only a spot_prepare_* or margin_prepare_* tool first and show its exact summary to the user. Stop and wait for a new, explicit user confirmation message. Only then call confirm_action with that new message verbatim in userConfirmation. Never call prepare and confirm consecutively for one user instruction; never infer confirmation from prior intent, silence, or an Agent-generated message. For spot and margin orders, MARKET BUY always uses quoteAmount (the quote asset to spend); MARKET SELL uses baseQuantity (the base asset to sell). Never reinterpret a requested base quantity as quoteAmount."
|
|
2183
|
+
instructions: "Every successful tool response is JSON text in the envelope { ok: true, data: ... }. All read-tool data is normalized: dataType=array means use data.items and data.count; dataType=object or scalar means use data.value; dataType=null means no value. market_get_ticker also provides data.tickers as an alias of data.items. Inspect data.dataType before formatting and never assume undocumented nested keys. Prepare/confirm tools return their documented action payload directly in data. For every state-changing action, call only a spot_prepare_* or margin_prepare_* tool first and show its exact summary to the user. Stop and wait for a new, explicit user confirmation message. Only then call confirm_action with that new message verbatim in userConfirmation. Never call prepare and confirm consecutively for one user instruction; never infer confirmation from prior intent, silence, or an Agent-generated message. For spot and margin orders, MARKET BUY always uses quoteAmount (the quote asset to spend); MARKET SELL uses baseQuantity (the base asset to sell). Never reinterpret a requested base quantity as quoteAmount."
|
|
2171
2184
|
}
|
|
2172
2185
|
);
|
|
2173
2186
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
@@ -2214,7 +2227,7 @@ function createServer(profileName, readOnly) {
|
|
|
2214
2227
|
return result({ ok: true, data: await writeExecutor.prepare(preparedTool.name, request.params.arguments ?? {}, context) });
|
|
2215
2228
|
}
|
|
2216
2229
|
const data = await registry.execute(request.params.name, request.params.arguments ?? {}, context, { readOnly });
|
|
2217
|
-
return result({ ok: true, data });
|
|
2230
|
+
return result({ ok: true, data: formatMcpData(request.params.name, data) });
|
|
2218
2231
|
} catch (error) {
|
|
2219
2232
|
return toMcpErrorResult(error);
|
|
2220
2233
|
}
|