@definitive-fi/mcp 1.1.1 → 1.2.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/dist/server.js +183 -72
- package/package.json +1 -1
package/dist/server.js
CHANGED
|
@@ -115,7 +115,9 @@ var ChainEnum = z.enum([
|
|
|
115
115
|
"solana",
|
|
116
116
|
"hyperevm",
|
|
117
117
|
"plasma",
|
|
118
|
-
"monad"
|
|
118
|
+
"monad",
|
|
119
|
+
"robinhood",
|
|
120
|
+
"ink"
|
|
119
121
|
]);
|
|
120
122
|
var jsonResult = (result) => ({
|
|
121
123
|
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
@@ -123,12 +125,122 @@ var jsonResult = (result) => ({
|
|
|
123
125
|
|
|
124
126
|
|
|
125
127
|
import { z as z2 } from "zod";
|
|
128
|
+
var perpsSymbolParam = z2.string().min(1).max(32).describe('Perps market symbol. Qualify with the subvenue when the base symbol is ambiguous, e.g. "native:BTC" (core exchange) — a bare symbol works only when exactly one market uses it');
|
|
129
|
+
var MIN_EPOCH_MS = 1600000000000;
|
|
130
|
+
var MAX_EPOCH_MS = 4102444800000;
|
|
131
|
+
var epochMsParam = () => z2.number().int().min(MIN_EPOCH_MS).max(MAX_EPOCH_MS);
|
|
132
|
+
var startTimeParam = epochMsParam().optional().describe("Range start in epoch milliseconds");
|
|
133
|
+
var decimalStringParam = z2.string().max(40).regex(/^\d+(\.\d+)?$/, "must be a non-negative decimal string").refine((value) => Number(value) > 0, "must be greater than zero");
|
|
134
|
+
function registerPerpsReadTools(server, client, keyType, defaultPortfolioId) {
|
|
135
|
+
const resolve = (suffix, portfolioId) => resolvePortfolioRoute(keyType, `perps/${suffix}`, portfolioId, defaultPortfolioId);
|
|
136
|
+
server.tool("perps_list_markets", "List all perps markets with live mark/mid/oracle prices, funding rate, open interest, and leverage caps. Use each row's marketId to address the market in other perps tools.", {
|
|
137
|
+
portfolio_id: portfolioIdParam
|
|
138
|
+
}, async ({ portfolio_id }) => {
|
|
139
|
+
const result = await client.request("GET", resolve("markets", portfolio_id));
|
|
140
|
+
return jsonResult(result);
|
|
141
|
+
});
|
|
142
|
+
server.tool("perps_get_orderbook", "Get the L2 orderbook snapshot for a perps market: bid/ask price levels with sizes and order counts.", {
|
|
143
|
+
symbol: perpsSymbolParam,
|
|
144
|
+
portfolio_id: portfolioIdParam
|
|
145
|
+
}, async ({ symbol, portfolio_id }) => {
|
|
146
|
+
const result = await client.request("GET", resolve(`markets/${symbol}/orderbook`, portfolio_id));
|
|
147
|
+
return jsonResult(result);
|
|
148
|
+
});
|
|
149
|
+
server.tool("perps_get_candles", "Get OHLCV candles for a perps market. Defaults to the last 24 hours when no range is given.", {
|
|
150
|
+
symbol: perpsSymbolParam,
|
|
151
|
+
interval: z2.enum(["1m", "5m", "15m", "1h", "4h", "1d"]).default("1h").describe("Candle interval"),
|
|
152
|
+
start_time: startTimeParam,
|
|
153
|
+
end_time: epochMsParam().optional().describe("Range end in epoch milliseconds"),
|
|
154
|
+
portfolio_id: portfolioIdParam
|
|
155
|
+
}, async ({ symbol, interval, start_time, end_time, portfolio_id }) => {
|
|
156
|
+
const end = end_time ?? Date.now();
|
|
157
|
+
const start = start_time ?? Math.max(MIN_EPOCH_MS, end - 24 * 60 * 60 * 1000);
|
|
158
|
+
if (start >= end) {
|
|
159
|
+
throw new Error("end_time must be greater than start_time");
|
|
160
|
+
}
|
|
161
|
+
const result = await client.request("GET", resolve(`markets/${symbol}/candles`, portfolio_id), {
|
|
162
|
+
interval,
|
|
163
|
+
startTime: String(start),
|
|
164
|
+
endTime: String(end)
|
|
165
|
+
});
|
|
166
|
+
return jsonResult(result);
|
|
167
|
+
});
|
|
168
|
+
server.tool("perps_get_quote", "Get a size-aware execution estimate for a perps market against the live orderbook (anonymous — does not account for positions or margin).", {
|
|
169
|
+
symbol: perpsSymbolParam,
|
|
170
|
+
side: z2.enum(["buy", "sell"]).describe("Order side"),
|
|
171
|
+
size: decimalStringParam.describe('Order size in the base asset, decimal string (e.g. "0.5")'),
|
|
172
|
+
portfolio_id: portfolioIdParam
|
|
173
|
+
}, async ({ symbol, side, size, portfolio_id }) => {
|
|
174
|
+
const result = await client.request("GET", resolve(`markets/${symbol}/quote`, portfolio_id), { side, size });
|
|
175
|
+
return jsonResult(result);
|
|
176
|
+
});
|
|
177
|
+
server.tool("perps_get_funding", "Get historical funding entries and the predicted next funding for a perps market.", {
|
|
178
|
+
symbol: perpsSymbolParam,
|
|
179
|
+
start_time: startTimeParam,
|
|
180
|
+
portfolio_id: portfolioIdParam
|
|
181
|
+
}, async ({ symbol, start_time, portfolio_id }) => {
|
|
182
|
+
const params = {};
|
|
183
|
+
if (start_time != null)
|
|
184
|
+
params.startTime = String(start_time);
|
|
185
|
+
const result = await client.request("GET", resolve(`markets/${symbol}/funding`, portfolio_id), params);
|
|
186
|
+
return jsonResult(result);
|
|
187
|
+
});
|
|
188
|
+
server.tool("perps_get_account", "Get the perps account state: equity, withdrawable balance, margin usage, and open positions with entry/mark/liquidation prices and PnL.", {
|
|
189
|
+
portfolio_id: portfolioIdParam
|
|
190
|
+
}, async ({ portfolio_id }) => {
|
|
191
|
+
const result = await client.request("GET", resolve("account", portfolio_id));
|
|
192
|
+
return jsonResult(result);
|
|
193
|
+
});
|
|
194
|
+
server.tool("perps_get_account_status", "Get perps onboarding status for the portfolio (NO_ACCOUNT → READY) and whether it can trade. Check this first if account tools return errors.", {
|
|
195
|
+
portfolio_id: portfolioIdParam
|
|
196
|
+
}, async ({ portfolio_id }) => {
|
|
197
|
+
const result = await client.request("GET", resolve("account/status", portfolio_id));
|
|
198
|
+
return jsonResult(result);
|
|
199
|
+
});
|
|
200
|
+
server.tool("perps_list_open_orders", "List perps orders currently resting on the venue, including trigger orders and position TP/SL.", {
|
|
201
|
+
portfolio_id: portfolioIdParam
|
|
202
|
+
}, async ({ portfolio_id }) => {
|
|
203
|
+
const result = await client.request("GET", resolve("orders/open", portfolio_id));
|
|
204
|
+
return jsonResult(result);
|
|
205
|
+
});
|
|
206
|
+
server.tool("perps_get_order_history", "List historical perps orders with their final status and average fill price.", {
|
|
207
|
+
portfolio_id: portfolioIdParam
|
|
208
|
+
}, async ({ portfolio_id }) => {
|
|
209
|
+
const result = await client.request("GET", resolve("orders/history", portfolio_id));
|
|
210
|
+
return jsonResult(result);
|
|
211
|
+
});
|
|
212
|
+
server.tool("perps_list_fills", "List perps trade fills with price, size, fee, closed PnL, and direction.", {
|
|
213
|
+
portfolio_id: portfolioIdParam
|
|
214
|
+
}, async ({ portfolio_id }) => {
|
|
215
|
+
const result = await client.request("GET", resolve("fills", portfolio_id));
|
|
216
|
+
return jsonResult(result);
|
|
217
|
+
});
|
|
218
|
+
server.tool("perps_list_funding_payments", "List funding payments paid (negative) or received (positive) on perps positions.", {
|
|
219
|
+
start_time: startTimeParam,
|
|
220
|
+
portfolio_id: portfolioIdParam
|
|
221
|
+
}, async ({ start_time, portfolio_id }) => {
|
|
222
|
+
const params = {};
|
|
223
|
+
if (start_time != null)
|
|
224
|
+
params.startTime = String(start_time);
|
|
225
|
+
const result = await client.request("GET", resolve("funding-payments", portfolio_id), params);
|
|
226
|
+
return jsonResult(result);
|
|
227
|
+
});
|
|
228
|
+
server.tool("perps_get_fees", "Get the portfolio's current perps taker/maker fee rates.", {
|
|
229
|
+
portfolio_id: portfolioIdParam
|
|
230
|
+
}, async ({ portfolio_id }) => {
|
|
231
|
+
const result = await client.request("GET", resolve("fees", portfolio_id));
|
|
232
|
+
return jsonResult(result);
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
import { z as z3 } from "zod";
|
|
126
238
|
function registerReadTools(server, client, keyType, defaultPortfolioId) {
|
|
127
239
|
const resolve = (suffix, portfolioId) => resolvePortfolioRoute(keyType, suffix, portfolioId, defaultPortfolioId);
|
|
128
240
|
server.tool("list_positions", "List current token holdings in the portfolio with balances, USD values, and P&L.", {
|
|
129
|
-
limit:
|
|
130
|
-
cursor:
|
|
131
|
-
include_dust_balances:
|
|
241
|
+
limit: z3.number().min(1).max(100).default(20).describe("Max positions to return (1-100)"),
|
|
242
|
+
cursor: z3.string().optional().describe("Pagination cursor from previous response's nextCursor field"),
|
|
243
|
+
include_dust_balances: z3.boolean().default(false).describe("Include positions worth less than $1"),
|
|
132
244
|
portfolio_id: portfolioIdParam
|
|
133
245
|
}, async ({ limit, cursor, include_dust_balances, portfolio_id }) => {
|
|
134
246
|
const path = resolve("positions", portfolio_id);
|
|
@@ -148,17 +260,17 @@ function registerReadTools(server, client, keyType, defaultPortfolioId) {
|
|
|
148
260
|
return jsonResult(result);
|
|
149
261
|
});
|
|
150
262
|
server.tool("list_transfers", "List historical transfers (deposits, withdrawals, swaps, bridge transactions) for the portfolio.", {
|
|
151
|
-
limit:
|
|
152
|
-
cursor:
|
|
153
|
-
action_types:
|
|
263
|
+
limit: z3.number().min(1).max(100).default(20).describe("Max transfers to return (1-100)"),
|
|
264
|
+
cursor: z3.string().optional().describe("Pagination cursor from previous response's nextCursor field"),
|
|
265
|
+
action_types: z3.array(z3.enum([
|
|
154
266
|
"VAULT_ACTION_DEPOSIT",
|
|
155
267
|
"VAULT_ACTION_WITHDRAW",
|
|
156
268
|
"VAULT_ACTION_BRIDGE_SEND",
|
|
157
269
|
"VAULT_ACTION_BRIDGE_RECEIVE",
|
|
158
270
|
"VAULT_ACTION_SWAP"
|
|
159
271
|
])).optional().describe("Filter by transfer action types"),
|
|
160
|
-
start_timestamp:
|
|
161
|
-
end_timestamp:
|
|
272
|
+
start_timestamp: z3.string().datetime().optional().describe("Start of time range (ISO 8601 string, e.g. 2025-01-01T00:00:00Z)"),
|
|
273
|
+
end_timestamp: z3.string().datetime().optional().describe("End of time range (ISO 8601 string, e.g. 2025-01-01T00:00:00Z)"),
|
|
162
274
|
portfolio_id: portfolioIdParam
|
|
163
275
|
}, async ({
|
|
164
276
|
limit,
|
|
@@ -183,7 +295,7 @@ function registerReadTools(server, client, keyType, defaultPortfolioId) {
|
|
|
183
295
|
});
|
|
184
296
|
server.tool("get_deposit_address", "Get a deposit address for a specific blockchain. Creates a vault if one doesn't exist for that chain.", {
|
|
185
297
|
chain: ChainEnum.describe("Blockchain network name"),
|
|
186
|
-
wallet_address:
|
|
298
|
+
wallet_address: z3.string().min(1).describe("User's wallet address on this chain — ask the user if not provided"),
|
|
187
299
|
portfolio_id: portfolioIdParam
|
|
188
300
|
}, async ({ chain, wallet_address, portfolio_id }) => {
|
|
189
301
|
const path = resolve(`address/${chain}`, portfolio_id);
|
|
@@ -192,9 +304,9 @@ function registerReadTools(server, client, keyType, defaultPortfolioId) {
|
|
|
192
304
|
return jsonResult(result);
|
|
193
305
|
});
|
|
194
306
|
server.tool("list_orders", "List trade orders with optional status filtering. Returns order details including fill status and pricing.", {
|
|
195
|
-
limit:
|
|
196
|
-
cursor:
|
|
197
|
-
status:
|
|
307
|
+
limit: z3.number().min(1).max(100).default(20).describe("Max orders to return (1-100)"),
|
|
308
|
+
cursor: z3.string().optional().describe("Pagination cursor from previous response's nextCursor field"),
|
|
309
|
+
status: z3.enum([
|
|
198
310
|
"ORDER_STATUS_PENDING",
|
|
199
311
|
"ORDER_STATUS_ACCEPTED",
|
|
200
312
|
"ORDER_STATUS_PARTIALLY_FILLED",
|
|
@@ -223,8 +335,8 @@ function registerReadTools(server, client, keyType, defaultPortfolioId) {
|
|
|
223
335
|
if (keyType !== "organization")
|
|
224
336
|
return;
|
|
225
337
|
server.tool("list_portfolios", "List all portfolios in the organization. Organization API keys only.", {
|
|
226
|
-
limit:
|
|
227
|
-
cursor:
|
|
338
|
+
limit: z3.number().min(1).max(100).default(10).describe("Max portfolios to return (1-100)"),
|
|
339
|
+
cursor: z3.string().optional().describe("Pagination cursor from previous response's nextCursor field")
|
|
228
340
|
}, async ({ limit, cursor }) => {
|
|
229
341
|
const params = { limit: String(limit) };
|
|
230
342
|
if (cursor)
|
|
@@ -234,8 +346,8 @@ function registerReadTools(server, client, keyType, defaultPortfolioId) {
|
|
|
234
346
|
});
|
|
235
347
|
server.tool("get_fees", "Get fee summary for a portfolio over a time period. Organization API keys only.", {
|
|
236
348
|
portfolio_id: zUUID.describe("Portfolio UUID to get fees for"),
|
|
237
|
-
start_timestamp:
|
|
238
|
-
end_timestamp:
|
|
349
|
+
start_timestamp: z3.string().datetime().optional().describe("Start of time range (ISO 8601 string, e.g. 2025-01-01T00:00:00Z)"),
|
|
350
|
+
end_timestamp: z3.string().datetime().optional().describe("End of time range (ISO 8601 string, e.g. 2025-01-01T00:00:00Z)")
|
|
239
351
|
}, async ({ portfolio_id, start_timestamp, end_timestamp }) => {
|
|
240
352
|
const params = {};
|
|
241
353
|
if (start_timestamp)
|
|
@@ -248,9 +360,9 @@ function registerReadTools(server, client, keyType, defaultPortfolioId) {
|
|
|
248
360
|
}
|
|
249
361
|
|
|
250
362
|
|
|
251
|
-
import { z as
|
|
252
|
-
var OrderSideEnum =
|
|
253
|
-
var OrderTypeEnum =
|
|
363
|
+
import { z as z4 } from "zod";
|
|
364
|
+
var OrderSideEnum = z4.enum(["buy", "sell"]);
|
|
365
|
+
var OrderTypeEnum = z4.enum([
|
|
254
366
|
"market",
|
|
255
367
|
"limit",
|
|
256
368
|
"twap",
|
|
@@ -263,19 +375,19 @@ function registerWriteTools(server, client, keyType, defaultPortfolioId) {
|
|
|
263
375
|
server.tool("get_trade_quote", "Get a price quote for a trade order. This is the DEFAULT tool for all trades — use this unless the user explicitly asks for a QuickTrade. Supports market, limit, TWAP, stop, stop-loss, and take-profit order types. This does not execute any trade. Use the returned quote ID with submit_trade to execute.", {
|
|
264
376
|
type: OrderTypeEnum.describe("Order type"),
|
|
265
377
|
chain: ChainEnum.describe("Blockchain network name"),
|
|
266
|
-
target_asset:
|
|
267
|
-
contra_asset:
|
|
268
|
-
qty:
|
|
378
|
+
target_asset: z4.string().min(1).describe("Target asset contract address"),
|
|
379
|
+
contra_asset: z4.string().min(1).describe("Contra (quote) asset contract address"),
|
|
380
|
+
qty: z4.string().min(1).describe("Order quantity as a decimal string"),
|
|
269
381
|
order_side: OrderSideEnum.describe("Buy or sell"),
|
|
270
|
-
limit_price:
|
|
271
|
-
limit_is_notional:
|
|
272
|
-
trigger_price:
|
|
273
|
-
trigger_is_notional:
|
|
274
|
-
duration_seconds:
|
|
275
|
-
target_twap_buckets:
|
|
276
|
-
trigger_type:
|
|
277
|
-
slippage_tolerance:
|
|
278
|
-
max_price_impact:
|
|
382
|
+
limit_price: z4.string().optional().describe("Limit price (for limit orders)"),
|
|
383
|
+
limit_is_notional: z4.boolean().optional().describe("Whether limit price is in notional terms"),
|
|
384
|
+
trigger_price: z4.string().optional().describe("Trigger price (for stop/stop-loss/take-profit orders)"),
|
|
385
|
+
trigger_is_notional: z4.boolean().optional().describe("Whether trigger price is in notional terms"),
|
|
386
|
+
duration_seconds: z4.number().optional().describe("TWAP duration in seconds"),
|
|
387
|
+
target_twap_buckets: z4.number().optional().describe("Number of TWAP buckets"),
|
|
388
|
+
trigger_type: z4.enum(["upper", "lower"]).optional().describe("Trigger type for stop-buy orders only (upper or lower price bound)"),
|
|
389
|
+
slippage_tolerance: z4.string().optional().describe("Slippage tolerance as a decimal string (e.g. '0.01' for 1%)"),
|
|
390
|
+
max_price_impact: z4.string().optional().describe("Max price impact as a decimal string (e.g. '0.01' for 1%)"),
|
|
279
391
|
portfolio_id: portfolioIdParam
|
|
280
392
|
}, { readOnlyHint: true }, async ({
|
|
281
393
|
type,
|
|
@@ -330,10 +442,10 @@ function registerWriteTools(server, client, keyType, defaultPortfolioId) {
|
|
|
330
442
|
return jsonResult(result);
|
|
331
443
|
});
|
|
332
444
|
server.tool("get_quicktrade_quote", "Get a price quote for a QuickTrade market swap. Only use when the user explicitly requests a QuickTrade. This does not execute any trade. Review the quote before executing with the quicktrade tool.", {
|
|
333
|
-
target_asset:
|
|
334
|
-
contra_asset:
|
|
445
|
+
target_asset: z4.string().min(1).describe("Target asset contract address"),
|
|
446
|
+
contra_asset: z4.string().min(1).describe("Contra (quote) asset contract address"),
|
|
335
447
|
chain: ChainEnum.describe("Blockchain network name"),
|
|
336
|
-
qty:
|
|
448
|
+
qty: z4.string().min(1).describe("Order quantity as a decimal string"),
|
|
337
449
|
order_side: OrderSideEnum.describe("Buy or sell"),
|
|
338
450
|
portfolio_id: portfolioIdParam
|
|
339
451
|
}, { readOnlyHint: true }, async ({
|
|
@@ -357,11 +469,11 @@ function registerWriteTools(server, client, keyType, defaultPortfolioId) {
|
|
|
357
469
|
return jsonResult(result);
|
|
358
470
|
});
|
|
359
471
|
server.tool("bridge_quote", "Get a quote for a cross-chain bridge transfer. This does not move any funds. Review the routes and select a route_id before executing with bridge_submit.", {
|
|
360
|
-
from_asset_address:
|
|
472
|
+
from_asset_address: z4.string().min(1).describe("Source asset contract address"),
|
|
361
473
|
from_chain: ChainEnum.describe("Source blockchain network"),
|
|
362
|
-
to_asset_address:
|
|
474
|
+
to_asset_address: z4.string().min(1).describe("Destination asset contract address"),
|
|
363
475
|
to_chain: ChainEnum.describe("Destination blockchain network"),
|
|
364
|
-
from_amount:
|
|
476
|
+
from_amount: z4.string().min(1).describe("Amount to bridge as a decimal string"),
|
|
365
477
|
portfolio_id: portfolioIdParam
|
|
366
478
|
}, { readOnlyHint: true }, async ({
|
|
367
479
|
from_asset_address,
|
|
@@ -408,19 +520,19 @@ function registerWriteTools(server, client, keyType, defaultPortfolioId) {
|
|
|
408
520
|
quote_id: zUUID.describe("Quote UUID from get_trade_quote response (found in quote.quote.id)"),
|
|
409
521
|
type: OrderTypeEnum.describe("Order type"),
|
|
410
522
|
chain: ChainEnum.describe("Blockchain network name"),
|
|
411
|
-
target_asset:
|
|
412
|
-
contra_asset:
|
|
413
|
-
qty:
|
|
523
|
+
target_asset: z4.string().min(1).describe("Target asset contract address"),
|
|
524
|
+
contra_asset: z4.string().min(1).describe("Contra (quote) asset contract address"),
|
|
525
|
+
qty: z4.string().min(1).describe("Order quantity as a decimal string"),
|
|
414
526
|
order_side: OrderSideEnum.describe("Buy or sell"),
|
|
415
|
-
limit_price:
|
|
416
|
-
limit_is_notional:
|
|
417
|
-
trigger_price:
|
|
418
|
-
trigger_is_notional:
|
|
419
|
-
duration_seconds:
|
|
420
|
-
target_twap_buckets:
|
|
421
|
-
trigger_type:
|
|
422
|
-
slippage_tolerance:
|
|
423
|
-
max_price_impact:
|
|
527
|
+
limit_price: z4.string().optional().describe("Limit price (for limit orders)"),
|
|
528
|
+
limit_is_notional: z4.boolean().optional().describe("Whether limit price is in notional terms"),
|
|
529
|
+
trigger_price: z4.string().optional().describe("Trigger price (for stop/stop-loss/take-profit orders)"),
|
|
530
|
+
trigger_is_notional: z4.boolean().optional().describe("Whether trigger price is in notional terms"),
|
|
531
|
+
duration_seconds: z4.number().optional().describe("TWAP duration in seconds"),
|
|
532
|
+
target_twap_buckets: z4.number().optional().describe("Number of TWAP buckets"),
|
|
533
|
+
trigger_type: z4.enum(["upper", "lower"]).optional().describe("Trigger type for stop-buy orders only"),
|
|
534
|
+
slippage_tolerance: z4.string().optional().describe("Slippage tolerance as a decimal string (e.g. '0.01' for 1%)"),
|
|
535
|
+
max_price_impact: z4.string().optional().describe("Max price impact as a decimal string (e.g. '0.01' for 1%)"),
|
|
424
536
|
portfolio_id: portfolioIdParam
|
|
425
537
|
}, {
|
|
426
538
|
readOnlyHint: false,
|
|
@@ -481,14 +593,14 @@ function registerWriteTools(server, client, keyType, defaultPortfolioId) {
|
|
|
481
593
|
return jsonResult(result);
|
|
482
594
|
});
|
|
483
595
|
server.tool("quicktrade", "Execute a QuickTrade market swap immediately. Only use when the user explicitly requests a QuickTrade. This is irreversible — funds move on-chain once submitted. Call get_quicktrade_quote first and confirm details with the user before executing, unless the user requests to skip the quote step.", {
|
|
484
|
-
target_asset:
|
|
485
|
-
contra_asset:
|
|
596
|
+
target_asset: z4.string().min(1).describe("Target asset contract address"),
|
|
597
|
+
contra_asset: z4.string().min(1).describe("Contra (quote) asset contract address"),
|
|
486
598
|
chain: ChainEnum.describe("Blockchain network name"),
|
|
487
|
-
qty:
|
|
599
|
+
qty: z4.string().min(1).describe("Order quantity as a decimal string"),
|
|
488
600
|
order_side: OrderSideEnum.describe("Buy or sell"),
|
|
489
|
-
slippage_tolerance:
|
|
490
|
-
display_asset_price:
|
|
491
|
-
seconds_to_expire:
|
|
601
|
+
slippage_tolerance: z4.string().optional().describe("Slippage tolerance as a decimal string (e.g. '0.01' for 1%)"),
|
|
602
|
+
display_asset_price: z4.string().optional().describe("Target asset notional price for display validation"),
|
|
603
|
+
seconds_to_expire: z4.number().int().positive().optional().describe("Order expiry time in seconds"),
|
|
492
604
|
portfolio_id: portfolioIdParam
|
|
493
605
|
}, {
|
|
494
606
|
readOnlyHint: false,
|
|
@@ -526,10 +638,10 @@ function registerWriteTools(server, client, keyType, defaultPortfolioId) {
|
|
|
526
638
|
server.tool("bridge_submit", "Execute a cross-chain bridge transfer. This is irreversible — funds are sent from the source chain to the destination chain. Always call bridge_quote first and confirm the details with the user before executing.", {
|
|
527
639
|
from_chain: ChainEnum.describe("Source blockchain network"),
|
|
528
640
|
to_chain: ChainEnum.describe("Destination blockchain network"),
|
|
529
|
-
from_asset_address:
|
|
530
|
-
to_asset_address:
|
|
531
|
-
from_amount:
|
|
532
|
-
route_id:
|
|
641
|
+
from_asset_address: z4.string().min(1).describe("Source asset contract address"),
|
|
642
|
+
to_asset_address: z4.string().min(1).describe("Destination asset contract address"),
|
|
643
|
+
from_amount: z4.string().min(1).describe("Amount to bridge as a decimal string"),
|
|
644
|
+
route_id: z4.string().min(1).describe("Route ID from bridge_quote response"),
|
|
533
645
|
portfolio_id: portfolioIdParam
|
|
534
646
|
}, {
|
|
535
647
|
readOnlyHint: false,
|
|
@@ -559,7 +671,7 @@ function registerWriteTools(server, client, keyType, defaultPortfolioId) {
|
|
|
559
671
|
if (keyType !== "organization")
|
|
560
672
|
return;
|
|
561
673
|
server.tool("create_portfolio", "Create a new portfolio in the organization. Organization API keys only.", {
|
|
562
|
-
portfolio_name:
|
|
674
|
+
portfolio_name: z4.string().min(1).describe("Name for the new portfolio")
|
|
563
675
|
}, {
|
|
564
676
|
readOnlyHint: false,
|
|
565
677
|
destructiveHint: false
|
|
@@ -570,22 +682,21 @@ function registerWriteTools(server, client, keyType, defaultPortfolioId) {
|
|
|
570
682
|
}
|
|
571
683
|
|
|
572
684
|
|
|
573
|
-
import { z as
|
|
574
|
-
var McpEnvSchema =
|
|
575
|
-
DEFINITIVE_API_KEY:
|
|
576
|
-
DEFINITIVE_API_SECRET:
|
|
577
|
-
DEFINITIVE_BASE_URL:
|
|
578
|
-
DEFINITIVE_API_KEY_TYPE:
|
|
579
|
-
DEFINITIVE_PORTFOLIO_ID:
|
|
685
|
+
import { z as z5 } from "zod";
|
|
686
|
+
var McpEnvSchema = z5.object({
|
|
687
|
+
DEFINITIVE_API_KEY: z5.string().startsWith("dpka_"),
|
|
688
|
+
DEFINITIVE_API_SECRET: z5.string().startsWith("dpks_"),
|
|
689
|
+
DEFINITIVE_BASE_URL: z5.string().url().default("https://ddp.definitive.fi"),
|
|
690
|
+
DEFINITIVE_API_KEY_TYPE: z5.enum(["portfolio", "organization"]),
|
|
691
|
+
DEFINITIVE_PORTFOLIO_ID: z5.string().optional()
|
|
580
692
|
});
|
|
581
693
|
var env = McpEnvSchema.parse(process.env);
|
|
582
694
|
var client = createClient(env.DEFINITIVE_BASE_URL, env.DEFINITIVE_API_KEY, env.DEFINITIVE_API_SECRET);
|
|
583
|
-
var server = new McpServer({
|
|
584
|
-
|
|
585
|
-
version: "1.1.1",
|
|
586
|
-
instructions: "MCP server for the Definitive on-chain trading platform. Provides unified tools for portfolio management, trading (market/limit/TWAP/stop orders), QuickTrade execution across multiple blockchains. Tools auto-route to the correct API based on the configured key type (portfolio or organization). For organization keys, pass portfolio_id to target a specific portfolio, or set DEFINITIVE_PORTFOLIO_ID as default. TRADING: Default to get_trade_quote + submit_trade for trades unless the user specifies QuickTrade."
|
|
695
|
+
var server = new McpServer({ name: "Definitive", version: "1.2.0" }, {
|
|
696
|
+
instructions: "MCP server for the Definitive on-chain trading platform. Provides unified tools for portfolio management, trading (market/limit/TWAP/stop orders), QuickTrade execution across multiple blockchains, and read-only perps (perpetual futures) market data and account state. Tools auto-route to the correct API based on the configured key type (portfolio or organization). For organization keys, pass portfolio_id to target a specific portfolio, or set DEFINITIVE_PORTFOLIO_ID as default. TRADING: Default to get_trade_quote + submit_trade for trades unless the user specifies QuickTrade."
|
|
587
697
|
});
|
|
588
698
|
registerReadTools(server, client, env.DEFINITIVE_API_KEY_TYPE, env.DEFINITIVE_PORTFOLIO_ID);
|
|
589
699
|
registerWriteTools(server, client, env.DEFINITIVE_API_KEY_TYPE, env.DEFINITIVE_PORTFOLIO_ID);
|
|
700
|
+
registerPerpsReadTools(server, client, env.DEFINITIVE_API_KEY_TYPE, env.DEFINITIVE_PORTFOLIO_ID);
|
|
590
701
|
var transport = new StdioServerTransport;
|
|
591
702
|
await server.connect(transport);
|