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