@definitive-fi/mcp 1.1.0 → 1.1.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/server.js +120 -124
- package/package.json +10 -1
package/dist/server.js
CHANGED
|
@@ -115,17 +115,21 @@ var ChainEnum = z.enum([
|
|
|
115
115
|
"solana",
|
|
116
116
|
"hyperevm",
|
|
117
117
|
"plasma",
|
|
118
|
-
"monad"
|
|
118
|
+
"monad",
|
|
119
|
+
"robinhood"
|
|
119
120
|
]);
|
|
120
121
|
var jsonResult = (result) => ({
|
|
121
122
|
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
122
123
|
});
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
import { z as z2 } from "zod";
|
|
123
127
|
function registerReadTools(server, client, keyType, defaultPortfolioId) {
|
|
124
128
|
const resolve = (suffix, portfolioId) => resolvePortfolioRoute(keyType, suffix, portfolioId, defaultPortfolioId);
|
|
125
129
|
server.tool("list_positions", "List current token holdings in the portfolio with balances, USD values, and P&L.", {
|
|
126
|
-
limit:
|
|
127
|
-
cursor:
|
|
128
|
-
include_dust_balances:
|
|
130
|
+
limit: z2.number().min(1).max(100).default(20).describe("Max positions to return (1-100)"),
|
|
131
|
+
cursor: z2.string().optional().describe("Pagination cursor from previous response's nextCursor field"),
|
|
132
|
+
include_dust_balances: z2.boolean().default(false).describe("Include positions worth less than $1"),
|
|
129
133
|
portfolio_id: portfolioIdParam
|
|
130
134
|
}, async ({ limit, cursor, include_dust_balances, portfolio_id }) => {
|
|
131
135
|
const path = resolve("positions", portfolio_id);
|
|
@@ -145,17 +149,17 @@ function registerReadTools(server, client, keyType, defaultPortfolioId) {
|
|
|
145
149
|
return jsonResult(result);
|
|
146
150
|
});
|
|
147
151
|
server.tool("list_transfers", "List historical transfers (deposits, withdrawals, swaps, bridge transactions) for the portfolio.", {
|
|
148
|
-
limit:
|
|
149
|
-
cursor:
|
|
150
|
-
action_types:
|
|
152
|
+
limit: z2.number().min(1).max(100).default(20).describe("Max transfers to return (1-100)"),
|
|
153
|
+
cursor: z2.string().optional().describe("Pagination cursor from previous response's nextCursor field"),
|
|
154
|
+
action_types: z2.array(z2.enum([
|
|
151
155
|
"VAULT_ACTION_DEPOSIT",
|
|
152
156
|
"VAULT_ACTION_WITHDRAW",
|
|
153
157
|
"VAULT_ACTION_BRIDGE_SEND",
|
|
154
158
|
"VAULT_ACTION_BRIDGE_RECEIVE",
|
|
155
159
|
"VAULT_ACTION_SWAP"
|
|
156
160
|
])).optional().describe("Filter by transfer action types"),
|
|
157
|
-
start_timestamp:
|
|
158
|
-
end_timestamp:
|
|
161
|
+
start_timestamp: z2.string().datetime().optional().describe("Start of time range (ISO 8601 string, e.g. 2025-01-01T00:00:00Z)"),
|
|
162
|
+
end_timestamp: z2.string().datetime().optional().describe("End of time range (ISO 8601 string, e.g. 2025-01-01T00:00:00Z)"),
|
|
159
163
|
portfolio_id: portfolioIdParam
|
|
160
164
|
}, async ({
|
|
161
165
|
limit,
|
|
@@ -180,7 +184,7 @@ function registerReadTools(server, client, keyType, defaultPortfolioId) {
|
|
|
180
184
|
});
|
|
181
185
|
server.tool("get_deposit_address", "Get a deposit address for a specific blockchain. Creates a vault if one doesn't exist for that chain.", {
|
|
182
186
|
chain: ChainEnum.describe("Blockchain network name"),
|
|
183
|
-
wallet_address:
|
|
187
|
+
wallet_address: z2.string().min(1).describe("User's wallet address on this chain — ask the user if not provided"),
|
|
184
188
|
portfolio_id: portfolioIdParam
|
|
185
189
|
}, async ({ chain, wallet_address, portfolio_id }) => {
|
|
186
190
|
const path = resolve(`address/${chain}`, portfolio_id);
|
|
@@ -189,9 +193,9 @@ function registerReadTools(server, client, keyType, defaultPortfolioId) {
|
|
|
189
193
|
return jsonResult(result);
|
|
190
194
|
});
|
|
191
195
|
server.tool("list_orders", "List trade orders with optional status filtering. Returns order details including fill status and pricing.", {
|
|
192
|
-
limit:
|
|
193
|
-
cursor:
|
|
194
|
-
status:
|
|
196
|
+
limit: z2.number().min(1).max(100).default(20).describe("Max orders to return (1-100)"),
|
|
197
|
+
cursor: z2.string().optional().describe("Pagination cursor from previous response's nextCursor field"),
|
|
198
|
+
status: z2.enum([
|
|
195
199
|
"ORDER_STATUS_PENDING",
|
|
196
200
|
"ORDER_STATUS_ACCEPTED",
|
|
197
201
|
"ORDER_STATUS_PARTIALLY_FILLED",
|
|
@@ -220,8 +224,8 @@ function registerReadTools(server, client, keyType, defaultPortfolioId) {
|
|
|
220
224
|
if (keyType !== "organization")
|
|
221
225
|
return;
|
|
222
226
|
server.tool("list_portfolios", "List all portfolios in the organization. Organization API keys only.", {
|
|
223
|
-
limit:
|
|
224
|
-
cursor:
|
|
227
|
+
limit: z2.number().min(1).max(100).default(10).describe("Max portfolios to return (1-100)"),
|
|
228
|
+
cursor: z2.string().optional().describe("Pagination cursor from previous response's nextCursor field")
|
|
225
229
|
}, async ({ limit, cursor }) => {
|
|
226
230
|
const params = { limit: String(limit) };
|
|
227
231
|
if (cursor)
|
|
@@ -231,8 +235,8 @@ function registerReadTools(server, client, keyType, defaultPortfolioId) {
|
|
|
231
235
|
});
|
|
232
236
|
server.tool("get_fees", "Get fee summary for a portfolio over a time period. Organization API keys only.", {
|
|
233
237
|
portfolio_id: zUUID.describe("Portfolio UUID to get fees for"),
|
|
234
|
-
start_timestamp:
|
|
235
|
-
end_timestamp:
|
|
238
|
+
start_timestamp: z2.string().datetime().optional().describe("Start of time range (ISO 8601 string, e.g. 2025-01-01T00:00:00Z)"),
|
|
239
|
+
end_timestamp: z2.string().datetime().optional().describe("End of time range (ISO 8601 string, e.g. 2025-01-01T00:00:00Z)")
|
|
236
240
|
}, async ({ portfolio_id, start_timestamp, end_timestamp }) => {
|
|
237
241
|
const params = {};
|
|
238
242
|
if (start_timestamp)
|
|
@@ -245,25 +249,9 @@ function registerReadTools(server, client, keyType, defaultPortfolioId) {
|
|
|
245
249
|
}
|
|
246
250
|
|
|
247
251
|
|
|
248
|
-
import { z as
|
|
249
|
-
var
|
|
250
|
-
var
|
|
251
|
-
var ChainEnum2 = z2.enum([
|
|
252
|
-
"arbitrum",
|
|
253
|
-
"avalanche",
|
|
254
|
-
"base",
|
|
255
|
-
"blast",
|
|
256
|
-
"bsc",
|
|
257
|
-
"ethereum",
|
|
258
|
-
"optimism",
|
|
259
|
-
"polygon",
|
|
260
|
-
"solana",
|
|
261
|
-
"hyperevm",
|
|
262
|
-
"plasma",
|
|
263
|
-
"monad"
|
|
264
|
-
]);
|
|
265
|
-
var OrderSideEnum = z2.enum(["buy", "sell"]);
|
|
266
|
-
var OrderTypeEnum = z2.enum([
|
|
252
|
+
import { z as z3 } from "zod";
|
|
253
|
+
var OrderSideEnum = z3.enum(["buy", "sell"]);
|
|
254
|
+
var OrderTypeEnum = z3.enum([
|
|
267
255
|
"market",
|
|
268
256
|
"limit",
|
|
269
257
|
"twap",
|
|
@@ -271,28 +259,25 @@ var OrderTypeEnum = z2.enum([
|
|
|
271
259
|
"stop-loss",
|
|
272
260
|
"take-profit"
|
|
273
261
|
]);
|
|
274
|
-
var jsonResult2 = (result) => ({
|
|
275
|
-
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
276
|
-
});
|
|
277
262
|
function registerWriteTools(server, client, keyType, defaultPortfolioId) {
|
|
278
263
|
const resolve = (suffix, portfolioId) => resolvePortfolioRoute(keyType, suffix, portfolioId, defaultPortfolioId);
|
|
279
264
|
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.", {
|
|
280
265
|
type: OrderTypeEnum.describe("Order type"),
|
|
281
|
-
chain:
|
|
282
|
-
target_asset:
|
|
283
|
-
contra_asset:
|
|
284
|
-
qty:
|
|
266
|
+
chain: ChainEnum.describe("Blockchain network name"),
|
|
267
|
+
target_asset: z3.string().min(1).describe("Target asset contract address"),
|
|
268
|
+
contra_asset: z3.string().min(1).describe("Contra (quote) asset contract address"),
|
|
269
|
+
qty: z3.string().min(1).describe("Order quantity as a decimal string"),
|
|
285
270
|
order_side: OrderSideEnum.describe("Buy or sell"),
|
|
286
|
-
limit_price:
|
|
287
|
-
limit_is_notional:
|
|
288
|
-
trigger_price:
|
|
289
|
-
trigger_is_notional:
|
|
290
|
-
duration_seconds:
|
|
291
|
-
target_twap_buckets:
|
|
292
|
-
trigger_type:
|
|
293
|
-
slippage_tolerance:
|
|
294
|
-
max_price_impact:
|
|
295
|
-
portfolio_id:
|
|
271
|
+
limit_price: z3.string().optional().describe("Limit price (for limit orders)"),
|
|
272
|
+
limit_is_notional: z3.boolean().optional().describe("Whether limit price is in notional terms"),
|
|
273
|
+
trigger_price: z3.string().optional().describe("Trigger price (for stop/stop-loss/take-profit orders)"),
|
|
274
|
+
trigger_is_notional: z3.boolean().optional().describe("Whether trigger price is in notional terms"),
|
|
275
|
+
duration_seconds: z3.number().optional().describe("TWAP duration in seconds"),
|
|
276
|
+
target_twap_buckets: z3.number().optional().describe("Number of TWAP buckets"),
|
|
277
|
+
trigger_type: z3.enum(["upper", "lower"]).optional().describe("Trigger type for stop-buy orders only (upper or lower price bound)"),
|
|
278
|
+
slippage_tolerance: z3.string().optional().describe("Slippage tolerance as a decimal string (e.g. '0.01' for 1%)"),
|
|
279
|
+
max_price_impact: z3.string().optional().describe("Max price impact as a decimal string (e.g. '0.01' for 1%)"),
|
|
280
|
+
portfolio_id: portfolioIdParam
|
|
296
281
|
}, { readOnlyHint: true }, async ({
|
|
297
282
|
type,
|
|
298
283
|
chain,
|
|
@@ -343,16 +328,23 @@ function registerWriteTools(server, client, keyType, defaultPortfolioId) {
|
|
|
343
328
|
if (max_price_impact !== undefined)
|
|
344
329
|
body.maxPriceImpact = max_price_impact;
|
|
345
330
|
const result = await client.request("POST", path, undefined, body);
|
|
346
|
-
return
|
|
331
|
+
return jsonResult(result);
|
|
347
332
|
});
|
|
348
333
|
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.", {
|
|
349
|
-
target_asset:
|
|
350
|
-
contra_asset:
|
|
351
|
-
chain:
|
|
352
|
-
qty:
|
|
334
|
+
target_asset: z3.string().min(1).describe("Target asset contract address"),
|
|
335
|
+
contra_asset: z3.string().min(1).describe("Contra (quote) asset contract address"),
|
|
336
|
+
chain: ChainEnum.describe("Blockchain network name"),
|
|
337
|
+
qty: z3.string().min(1).describe("Order quantity as a decimal string"),
|
|
353
338
|
order_side: OrderSideEnum.describe("Buy or sell"),
|
|
354
|
-
portfolio_id:
|
|
355
|
-
}, { readOnlyHint: true }, async ({
|
|
339
|
+
portfolio_id: portfolioIdParam
|
|
340
|
+
}, { readOnlyHint: true }, async ({
|
|
341
|
+
target_asset,
|
|
342
|
+
contra_asset,
|
|
343
|
+
chain,
|
|
344
|
+
qty,
|
|
345
|
+
order_side,
|
|
346
|
+
portfolio_id
|
|
347
|
+
}) => {
|
|
356
348
|
const path = resolve("quicktrade/quote", portfolio_id);
|
|
357
349
|
const body = {
|
|
358
350
|
type: "market",
|
|
@@ -363,15 +355,15 @@ function registerWriteTools(server, client, keyType, defaultPortfolioId) {
|
|
|
363
355
|
orderSide: order_side
|
|
364
356
|
};
|
|
365
357
|
const result = await client.request("POST", path, undefined, body);
|
|
366
|
-
return
|
|
358
|
+
return jsonResult(result);
|
|
367
359
|
});
|
|
368
360
|
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.", {
|
|
369
|
-
from_asset_address:
|
|
370
|
-
from_chain:
|
|
371
|
-
to_asset_address:
|
|
372
|
-
to_chain:
|
|
373
|
-
from_amount:
|
|
374
|
-
portfolio_id:
|
|
361
|
+
from_asset_address: z3.string().min(1).describe("Source asset contract address"),
|
|
362
|
+
from_chain: ChainEnum.describe("Source blockchain network"),
|
|
363
|
+
to_asset_address: z3.string().min(1).describe("Destination asset contract address"),
|
|
364
|
+
to_chain: ChainEnum.describe("Destination blockchain network"),
|
|
365
|
+
from_amount: z3.string().min(1).describe("Amount to bridge as a decimal string"),
|
|
366
|
+
portfolio_id: portfolioIdParam
|
|
375
367
|
}, { readOnlyHint: true }, async ({
|
|
376
368
|
from_asset_address,
|
|
377
369
|
from_chain,
|
|
@@ -389,50 +381,48 @@ function registerWriteTools(server, client, keyType, defaultPortfolioId) {
|
|
|
389
381
|
fromAmount: from_amount
|
|
390
382
|
};
|
|
391
383
|
const result = await client.request("POST", path, undefined, body);
|
|
392
|
-
return
|
|
384
|
+
return jsonResult(result);
|
|
393
385
|
});
|
|
394
386
|
server.tool("cancel_trade", "Cancel a pending trade order. This prevents the order from executing.", {
|
|
395
|
-
order_id:
|
|
396
|
-
portfolio_id:
|
|
387
|
+
order_id: zUUID.describe("The order UUID to cancel"),
|
|
388
|
+
portfolio_id: portfolioIdParam
|
|
397
389
|
}, {
|
|
398
390
|
readOnlyHint: false,
|
|
399
|
-
destructiveHint: false
|
|
400
|
-
idempotentHint: true
|
|
391
|
+
destructiveHint: false
|
|
401
392
|
}, async ({ order_id, portfolio_id }) => {
|
|
402
393
|
const path = resolve(`trade/${order_id}`, portfolio_id);
|
|
403
394
|
const result = await client.request("DELETE", path);
|
|
404
|
-
return
|
|
395
|
+
return jsonResult(result);
|
|
405
396
|
});
|
|
406
397
|
server.tool("cancel_quicktrade", "Cancel a pending QuickTrade order. This prevents the order from executing.", {
|
|
407
|
-
order_id:
|
|
408
|
-
portfolio_id:
|
|
398
|
+
order_id: zUUID.describe("The order UUID to cancel"),
|
|
399
|
+
portfolio_id: portfolioIdParam
|
|
409
400
|
}, {
|
|
410
401
|
readOnlyHint: false,
|
|
411
|
-
destructiveHint: false
|
|
412
|
-
idempotentHint: true
|
|
402
|
+
destructiveHint: false
|
|
413
403
|
}, async ({ order_id, portfolio_id }) => {
|
|
414
404
|
const path = resolve(`quicktrade/${order_id}`, portfolio_id);
|
|
415
405
|
const result = await client.request("DELETE", path);
|
|
416
|
-
return
|
|
406
|
+
return jsonResult(result);
|
|
417
407
|
});
|
|
418
408
|
server.tool("submit_trade", "Submit a trade order using a quote from get_trade_quote. This is irreversible — all order types (market, limit, stop, TWAP) may execute immediately. Always show the user the quote details and get confirmation before calling this tool. Pass the same parameters you used for get_trade_quote plus the quote_id.", {
|
|
419
|
-
quote_id:
|
|
409
|
+
quote_id: zUUID.describe("Quote UUID from get_trade_quote response (found in quote.quote.id)"),
|
|
420
410
|
type: OrderTypeEnum.describe("Order type"),
|
|
421
|
-
chain:
|
|
422
|
-
target_asset:
|
|
423
|
-
contra_asset:
|
|
424
|
-
qty:
|
|
411
|
+
chain: ChainEnum.describe("Blockchain network name"),
|
|
412
|
+
target_asset: z3.string().min(1).describe("Target asset contract address"),
|
|
413
|
+
contra_asset: z3.string().min(1).describe("Contra (quote) asset contract address"),
|
|
414
|
+
qty: z3.string().min(1).describe("Order quantity as a decimal string"),
|
|
425
415
|
order_side: OrderSideEnum.describe("Buy or sell"),
|
|
426
|
-
limit_price:
|
|
427
|
-
limit_is_notional:
|
|
428
|
-
trigger_price:
|
|
429
|
-
trigger_is_notional:
|
|
430
|
-
duration_seconds:
|
|
431
|
-
target_twap_buckets:
|
|
432
|
-
trigger_type:
|
|
433
|
-
slippage_tolerance:
|
|
434
|
-
max_price_impact:
|
|
435
|
-
portfolio_id:
|
|
416
|
+
limit_price: z3.string().optional().describe("Limit price (for limit orders)"),
|
|
417
|
+
limit_is_notional: z3.boolean().optional().describe("Whether limit price is in notional terms"),
|
|
418
|
+
trigger_price: z3.string().optional().describe("Trigger price (for stop/stop-loss/take-profit orders)"),
|
|
419
|
+
trigger_is_notional: z3.boolean().optional().describe("Whether trigger price is in notional terms"),
|
|
420
|
+
duration_seconds: z3.number().optional().describe("TWAP duration in seconds"),
|
|
421
|
+
target_twap_buckets: z3.number().optional().describe("Number of TWAP buckets"),
|
|
422
|
+
trigger_type: z3.enum(["upper", "lower"]).optional().describe("Trigger type for stop-buy orders only"),
|
|
423
|
+
slippage_tolerance: z3.string().optional().describe("Slippage tolerance as a decimal string (e.g. '0.01' for 1%)"),
|
|
424
|
+
max_price_impact: z3.string().optional().describe("Max price impact as a decimal string (e.g. '0.01' for 1%)"),
|
|
425
|
+
portfolio_id: portfolioIdParam
|
|
436
426
|
}, {
|
|
437
427
|
readOnlyHint: false,
|
|
438
428
|
destructiveHint: true,
|
|
@@ -466,9 +456,15 @@ function registerWriteTools(server, client, keyType, defaultPortfolioId) {
|
|
|
466
456
|
orderSide: order_side
|
|
467
457
|
};
|
|
468
458
|
if (limit_price !== undefined)
|
|
469
|
-
externalOrderRequest.limit = {
|
|
459
|
+
externalOrderRequest.limit = {
|
|
460
|
+
price: limit_price,
|
|
461
|
+
isNotional: limit_is_notional ?? false
|
|
462
|
+
};
|
|
470
463
|
if (trigger_price !== undefined)
|
|
471
|
-
externalOrderRequest.trigger = {
|
|
464
|
+
externalOrderRequest.trigger = {
|
|
465
|
+
price: trigger_price,
|
|
466
|
+
isNotional: trigger_is_notional ?? false
|
|
467
|
+
};
|
|
472
468
|
if (duration_seconds !== undefined)
|
|
473
469
|
externalOrderRequest.durationSeconds = duration_seconds;
|
|
474
470
|
if (target_twap_buckets !== undefined)
|
|
@@ -483,18 +479,18 @@ function registerWriteTools(server, client, keyType, defaultPortfolioId) {
|
|
|
483
479
|
quoteId: quote_id,
|
|
484
480
|
externalOrderRequest
|
|
485
481
|
});
|
|
486
|
-
return
|
|
482
|
+
return jsonResult(result);
|
|
487
483
|
});
|
|
488
|
-
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.
|
|
489
|
-
target_asset:
|
|
490
|
-
contra_asset:
|
|
491
|
-
chain:
|
|
492
|
-
qty:
|
|
484
|
+
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.", {
|
|
485
|
+
target_asset: z3.string().min(1).describe("Target asset contract address"),
|
|
486
|
+
contra_asset: z3.string().min(1).describe("Contra (quote) asset contract address"),
|
|
487
|
+
chain: ChainEnum.describe("Blockchain network name"),
|
|
488
|
+
qty: z3.string().min(1).describe("Order quantity as a decimal string"),
|
|
493
489
|
order_side: OrderSideEnum.describe("Buy or sell"),
|
|
494
|
-
slippage_tolerance:
|
|
495
|
-
display_asset_price:
|
|
496
|
-
seconds_to_expire:
|
|
497
|
-
portfolio_id:
|
|
490
|
+
slippage_tolerance: z3.string().optional().describe("Slippage tolerance as a decimal string (e.g. '0.01' for 1%)"),
|
|
491
|
+
display_asset_price: z3.string().optional().describe("Target asset notional price for display validation"),
|
|
492
|
+
seconds_to_expire: z3.number().int().positive().optional().describe("Order expiry time in seconds"),
|
|
493
|
+
portfolio_id: portfolioIdParam
|
|
498
494
|
}, {
|
|
499
495
|
readOnlyHint: false,
|
|
500
496
|
destructiveHint: true,
|
|
@@ -526,16 +522,16 @@ function registerWriteTools(server, client, keyType, defaultPortfolioId) {
|
|
|
526
522
|
if (seconds_to_expire !== undefined)
|
|
527
523
|
body.secondsToExpire = seconds_to_expire;
|
|
528
524
|
const result = await client.request("POST", path, undefined, body);
|
|
529
|
-
return
|
|
525
|
+
return jsonResult(result);
|
|
530
526
|
});
|
|
531
527
|
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.", {
|
|
532
|
-
from_chain:
|
|
533
|
-
to_chain:
|
|
534
|
-
from_asset_address:
|
|
535
|
-
to_asset_address:
|
|
536
|
-
from_amount:
|
|
537
|
-
route_id:
|
|
538
|
-
portfolio_id:
|
|
528
|
+
from_chain: ChainEnum.describe("Source blockchain network"),
|
|
529
|
+
to_chain: ChainEnum.describe("Destination blockchain network"),
|
|
530
|
+
from_asset_address: z3.string().min(1).describe("Source asset contract address"),
|
|
531
|
+
to_asset_address: z3.string().min(1).describe("Destination asset contract address"),
|
|
532
|
+
from_amount: z3.string().min(1).describe("Amount to bridge as a decimal string"),
|
|
533
|
+
route_id: z3.string().min(1).describe("Route ID from bridge_quote response"),
|
|
534
|
+
portfolio_id: portfolioIdParam
|
|
539
535
|
}, {
|
|
540
536
|
readOnlyHint: false,
|
|
541
537
|
destructiveHint: true,
|
|
@@ -559,35 +555,35 @@ function registerWriteTools(server, client, keyType, defaultPortfolioId) {
|
|
|
559
555
|
routeId: route_id
|
|
560
556
|
};
|
|
561
557
|
const result = await client.request("POST", path, undefined, body);
|
|
562
|
-
return
|
|
558
|
+
return jsonResult(result);
|
|
563
559
|
});
|
|
564
560
|
if (keyType !== "organization")
|
|
565
561
|
return;
|
|
566
562
|
server.tool("create_portfolio", "Create a new portfolio in the organization. Organization API keys only.", {
|
|
567
|
-
portfolio_name:
|
|
563
|
+
portfolio_name: z3.string().min(1).describe("Name for the new portfolio")
|
|
568
564
|
}, {
|
|
569
565
|
readOnlyHint: false,
|
|
570
566
|
destructiveHint: false
|
|
571
567
|
}, async ({ portfolio_name }) => {
|
|
572
568
|
const result = await client.request("POST", "/v2/organization/create-portfolio", undefined, { portfolioName: portfolio_name });
|
|
573
|
-
return
|
|
569
|
+
return jsonResult(result);
|
|
574
570
|
});
|
|
575
571
|
}
|
|
576
572
|
|
|
577
573
|
|
|
578
|
-
import { z as
|
|
579
|
-
var McpEnvSchema =
|
|
580
|
-
DEFINITIVE_API_KEY:
|
|
581
|
-
DEFINITIVE_API_SECRET:
|
|
582
|
-
DEFINITIVE_BASE_URL:
|
|
583
|
-
DEFINITIVE_API_KEY_TYPE:
|
|
584
|
-
DEFINITIVE_PORTFOLIO_ID:
|
|
574
|
+
import { z as z4 } from "zod";
|
|
575
|
+
var McpEnvSchema = z4.object({
|
|
576
|
+
DEFINITIVE_API_KEY: z4.string().startsWith("dpka_"),
|
|
577
|
+
DEFINITIVE_API_SECRET: z4.string().startsWith("dpks_"),
|
|
578
|
+
DEFINITIVE_BASE_URL: z4.string().url().default("https://ddp.definitive.fi"),
|
|
579
|
+
DEFINITIVE_API_KEY_TYPE: z4.enum(["portfolio", "organization"]),
|
|
580
|
+
DEFINITIVE_PORTFOLIO_ID: z4.string().optional()
|
|
585
581
|
});
|
|
586
582
|
var env = McpEnvSchema.parse(process.env);
|
|
587
583
|
var client = createClient(env.DEFINITIVE_BASE_URL, env.DEFINITIVE_API_KEY, env.DEFINITIVE_API_SECRET);
|
|
588
584
|
var server = new McpServer({
|
|
589
585
|
name: "Definitive",
|
|
590
|
-
version: "1.1.
|
|
586
|
+
version: "1.1.2",
|
|
591
587
|
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."
|
|
592
588
|
});
|
|
593
589
|
registerReadTools(server, client, env.DEFINITIVE_API_KEY_TYPE, env.DEFINITIVE_PORTFOLIO_ID);
|
package/package.json
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@definitive-fi/mcp",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"description": "MCP server for the Definitive on-chain trading platform",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"mcp",
|
|
7
|
+
"definitive",
|
|
8
|
+
"trading",
|
|
9
|
+
"defi",
|
|
10
|
+
"crypto",
|
|
11
|
+
"blockchain",
|
|
12
|
+
"onchain"
|
|
13
|
+
],
|
|
5
14
|
"type": "module",
|
|
6
15
|
"bin": "dist/server.js",
|
|
7
16
|
"files": [
|