@definitive-fi/mcp 1.0.0 → 1.1.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/README.md +5 -1
- package/dist/server.js +343 -12
- package/package.json +7 -5
package/README.md
CHANGED
|
@@ -22,6 +22,10 @@ Add the following to your MCP client configuration (e.g., Claude Desktop, Claude
|
|
|
22
22
|
}
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
+
## Documentation & API Keys
|
|
26
|
+
|
|
27
|
+
New to Definitive? Visit the [Definitive API documentation](https://ddp.definitive.fi/overview) to get started and obtain your API keys.
|
|
28
|
+
|
|
25
29
|
## Environment Variables
|
|
26
30
|
|
|
27
31
|
| Variable | Required | Description |
|
|
@@ -29,5 +33,5 @@ Add the following to your MCP client configuration (e.g., Claude Desktop, Claude
|
|
|
29
33
|
| `DEFINITIVE_API_KEY` | Yes | Your Definitive API key |
|
|
30
34
|
| `DEFINITIVE_API_SECRET` | Yes | Your Definitive API secret |
|
|
31
35
|
| `DEFINITIVE_API_KEY_TYPE` | Yes | Key type: `"portfolio"` or `"organization"` |
|
|
32
|
-
| `DEFINITIVE_BASE_URL` | No | API base URL
|
|
36
|
+
| `DEFINITIVE_BASE_URL` | No | API base URL |
|
|
33
37
|
| `DEFINITIVE_PORTFOLIO_ID` | No | Portfolio ID (required for organization keys when targeting a specific portfolio) |
|
package/dist/server.js
CHANGED
|
@@ -154,8 +154,8 @@ function registerReadTools(server, client, keyType, defaultPortfolioId) {
|
|
|
154
154
|
"VAULT_ACTION_BRIDGE_RECEIVE",
|
|
155
155
|
"VAULT_ACTION_SWAP"
|
|
156
156
|
])).optional().describe("Filter by transfer action types"),
|
|
157
|
-
start_timestamp: z.string().optional().describe("Start of time range (ISO 8601 string)"),
|
|
158
|
-
end_timestamp: z.string().optional().describe("End of time range (ISO 8601 string)"),
|
|
157
|
+
start_timestamp: z.string().datetime().optional().describe("Start of time range (ISO 8601 string, e.g. 2025-01-01T00:00:00Z)"),
|
|
158
|
+
end_timestamp: z.string().datetime().optional().describe("End of time range (ISO 8601 string, e.g. 2025-01-01T00:00:00Z)"),
|
|
159
159
|
portfolio_id: portfolioIdParam
|
|
160
160
|
}, async ({
|
|
161
161
|
limit,
|
|
@@ -231,8 +231,8 @@ function registerReadTools(server, client, keyType, defaultPortfolioId) {
|
|
|
231
231
|
});
|
|
232
232
|
server.tool("get_fees", "Get fee summary for a portfolio over a time period. Organization API keys only.", {
|
|
233
233
|
portfolio_id: zUUID.describe("Portfolio UUID to get fees for"),
|
|
234
|
-
start_timestamp: z.string().optional().describe("Start of time range (ISO 8601 string)"),
|
|
235
|
-
end_timestamp: z.string().optional().describe("End of time range (ISO 8601 string)")
|
|
234
|
+
start_timestamp: z.string().datetime().optional().describe("Start of time range (ISO 8601 string, e.g. 2025-01-01T00:00:00Z)"),
|
|
235
|
+
end_timestamp: z.string().datetime().optional().describe("End of time range (ISO 8601 string, e.g. 2025-01-01T00:00:00Z)")
|
|
236
236
|
}, async ({ portfolio_id, start_timestamp, end_timestamp }) => {
|
|
237
237
|
const params = {};
|
|
238
238
|
if (start_timestamp)
|
|
@@ -246,20 +246,351 @@ function registerReadTools(server, client, keyType, defaultPortfolioId) {
|
|
|
246
246
|
|
|
247
247
|
|
|
248
248
|
import { z as z2 } from "zod";
|
|
249
|
-
var
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
249
|
+
var zUUID2 = z2.string().uuid();
|
|
250
|
+
var portfolioIdParam2 = zUUID2.optional().describe("Portfolio UUID (required for organization keys without a default)");
|
|
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([
|
|
267
|
+
"market",
|
|
268
|
+
"limit",
|
|
269
|
+
"twap",
|
|
270
|
+
"stop",
|
|
271
|
+
"stop-loss",
|
|
272
|
+
"take-profit"
|
|
273
|
+
]);
|
|
274
|
+
var jsonResult2 = (result) => ({
|
|
275
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
276
|
+
});
|
|
277
|
+
function registerWriteTools(server, client, keyType, defaultPortfolioId) {
|
|
278
|
+
const resolve = (suffix, portfolioId) => resolvePortfolioRoute(keyType, suffix, portfolioId, defaultPortfolioId);
|
|
279
|
+
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
|
+
type: OrderTypeEnum.describe("Order type"),
|
|
281
|
+
chain: ChainEnum2.describe("Blockchain network name"),
|
|
282
|
+
target_asset: z2.string().min(1).describe("Target asset contract address"),
|
|
283
|
+
contra_asset: z2.string().min(1).describe("Contra (quote) asset contract address"),
|
|
284
|
+
qty: z2.string().min(1).describe("Order quantity as a decimal string"),
|
|
285
|
+
order_side: OrderSideEnum.describe("Buy or sell"),
|
|
286
|
+
limit_price: z2.string().optional().describe("Limit price (for limit orders)"),
|
|
287
|
+
limit_is_notional: z2.boolean().optional().describe("Whether limit price is in notional terms"),
|
|
288
|
+
trigger_price: z2.string().optional().describe("Trigger price (for stop/stop-loss/take-profit orders)"),
|
|
289
|
+
trigger_is_notional: z2.boolean().optional().describe("Whether trigger price is in notional terms"),
|
|
290
|
+
duration_seconds: z2.number().optional().describe("TWAP duration in seconds"),
|
|
291
|
+
target_twap_buckets: z2.number().optional().describe("Number of TWAP buckets"),
|
|
292
|
+
trigger_type: z2.enum(["upper", "lower"]).optional().describe("Trigger type for stop-buy orders only (upper or lower price bound)"),
|
|
293
|
+
slippage_tolerance: z2.string().optional().describe("Slippage tolerance as a decimal string (e.g. '1.0' for 1%)"),
|
|
294
|
+
max_price_impact: z2.string().optional().describe("Max price impact as a decimal string (e.g. '1.0' for 1%)"),
|
|
295
|
+
portfolio_id: portfolioIdParam2
|
|
296
|
+
}, { readOnlyHint: true }, async ({
|
|
297
|
+
type,
|
|
298
|
+
chain,
|
|
299
|
+
target_asset,
|
|
300
|
+
contra_asset,
|
|
301
|
+
qty,
|
|
302
|
+
order_side,
|
|
303
|
+
limit_price,
|
|
304
|
+
limit_is_notional,
|
|
305
|
+
trigger_price,
|
|
306
|
+
trigger_is_notional,
|
|
307
|
+
duration_seconds,
|
|
308
|
+
target_twap_buckets,
|
|
309
|
+
trigger_type,
|
|
310
|
+
slippage_tolerance,
|
|
311
|
+
max_price_impact,
|
|
312
|
+
portfolio_id
|
|
313
|
+
}) => {
|
|
314
|
+
const path = resolve("trade/quote", portfolio_id);
|
|
315
|
+
const body = {
|
|
316
|
+
type,
|
|
317
|
+
chain,
|
|
318
|
+
targetAsset: target_asset,
|
|
319
|
+
contraAsset: contra_asset,
|
|
320
|
+
qty,
|
|
321
|
+
orderSide: order_side
|
|
322
|
+
};
|
|
323
|
+
if (limit_price !== undefined) {
|
|
324
|
+
body.limit = {
|
|
325
|
+
price: limit_price,
|
|
326
|
+
isNotional: limit_is_notional ?? false
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
if (trigger_price !== undefined) {
|
|
330
|
+
body.trigger = {
|
|
331
|
+
price: trigger_price,
|
|
332
|
+
isNotional: trigger_is_notional ?? false
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
if (duration_seconds !== undefined)
|
|
336
|
+
body.durationSeconds = duration_seconds;
|
|
337
|
+
if (target_twap_buckets !== undefined)
|
|
338
|
+
body.targetTWAPBuckets = target_twap_buckets;
|
|
339
|
+
if (trigger_type !== undefined)
|
|
340
|
+
body.triggerType = trigger_type;
|
|
341
|
+
if (slippage_tolerance !== undefined)
|
|
342
|
+
body.slippageTolerance = slippage_tolerance;
|
|
343
|
+
if (max_price_impact !== undefined)
|
|
344
|
+
body.maxPriceImpact = max_price_impact;
|
|
345
|
+
const result = await client.request("POST", path, undefined, body);
|
|
346
|
+
return jsonResult2(result);
|
|
347
|
+
});
|
|
348
|
+
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: z2.string().min(1).describe("Target asset contract address"),
|
|
350
|
+
contra_asset: z2.string().min(1).describe("Contra (quote) asset contract address"),
|
|
351
|
+
chain: ChainEnum2.describe("Blockchain network name"),
|
|
352
|
+
qty: z2.string().min(1).describe("Order quantity as a decimal string"),
|
|
353
|
+
order_side: OrderSideEnum.describe("Buy or sell"),
|
|
354
|
+
portfolio_id: portfolioIdParam2
|
|
355
|
+
}, { readOnlyHint: true }, async ({ target_asset, contra_asset, chain, qty, order_side, portfolio_id }) => {
|
|
356
|
+
const path = resolve("quicktrade/quote", portfolio_id);
|
|
357
|
+
const body = {
|
|
358
|
+
type: "market",
|
|
359
|
+
chain,
|
|
360
|
+
targetAsset: target_asset,
|
|
361
|
+
contraAsset: contra_asset,
|
|
362
|
+
qty,
|
|
363
|
+
orderSide: order_side
|
|
364
|
+
};
|
|
365
|
+
const result = await client.request("POST", path, undefined, body);
|
|
366
|
+
return jsonResult2(result);
|
|
367
|
+
});
|
|
368
|
+
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: z2.string().min(1).describe("Source asset contract address"),
|
|
370
|
+
from_chain: ChainEnum2.describe("Source blockchain network"),
|
|
371
|
+
to_asset_address: z2.string().min(1).describe("Destination asset contract address"),
|
|
372
|
+
to_chain: ChainEnum2.describe("Destination blockchain network"),
|
|
373
|
+
from_amount: z2.string().min(1).describe("Amount to bridge as a decimal string"),
|
|
374
|
+
portfolio_id: portfolioIdParam2
|
|
375
|
+
}, { readOnlyHint: true }, async ({
|
|
376
|
+
from_asset_address,
|
|
377
|
+
from_chain,
|
|
378
|
+
to_asset_address,
|
|
379
|
+
to_chain,
|
|
380
|
+
from_amount,
|
|
381
|
+
portfolio_id
|
|
382
|
+
}) => {
|
|
383
|
+
const path = resolve("bridge/quote", portfolio_id);
|
|
384
|
+
const body = {
|
|
385
|
+
fromAssetAddress: from_asset_address,
|
|
386
|
+
fromChain: from_chain,
|
|
387
|
+
toAssetAddress: to_asset_address,
|
|
388
|
+
toChain: to_chain,
|
|
389
|
+
fromAmount: from_amount
|
|
390
|
+
};
|
|
391
|
+
const result = await client.request("POST", path, undefined, body);
|
|
392
|
+
return jsonResult2(result);
|
|
393
|
+
});
|
|
394
|
+
server.tool("cancel_trade", "Cancel a pending trade order. This prevents the order from executing.", {
|
|
395
|
+
order_id: zUUID2.describe("The order UUID to cancel"),
|
|
396
|
+
portfolio_id: portfolioIdParam2
|
|
397
|
+
}, {
|
|
398
|
+
readOnlyHint: false,
|
|
399
|
+
destructiveHint: false,
|
|
400
|
+
idempotentHint: true
|
|
401
|
+
}, async ({ order_id, portfolio_id }) => {
|
|
402
|
+
const path = resolve(`trade/${order_id}`, portfolio_id);
|
|
403
|
+
const result = await client.request("DELETE", path);
|
|
404
|
+
return jsonResult2(result);
|
|
405
|
+
});
|
|
406
|
+
server.tool("cancel_quicktrade", "Cancel a pending QuickTrade order. This prevents the order from executing.", {
|
|
407
|
+
order_id: zUUID2.describe("The order UUID to cancel"),
|
|
408
|
+
portfolio_id: portfolioIdParam2
|
|
409
|
+
}, {
|
|
410
|
+
readOnlyHint: false,
|
|
411
|
+
destructiveHint: false,
|
|
412
|
+
idempotentHint: true
|
|
413
|
+
}, async ({ order_id, portfolio_id }) => {
|
|
414
|
+
const path = resolve(`quicktrade/${order_id}`, portfolio_id);
|
|
415
|
+
const result = await client.request("DELETE", path);
|
|
416
|
+
return jsonResult2(result);
|
|
417
|
+
});
|
|
418
|
+
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: zUUID2.describe("Quote UUID from get_trade_quote response (found in quote.quote.id)"),
|
|
420
|
+
type: OrderTypeEnum.describe("Order type"),
|
|
421
|
+
chain: ChainEnum2.describe("Blockchain network name"),
|
|
422
|
+
target_asset: z2.string().min(1).describe("Target asset contract address"),
|
|
423
|
+
contra_asset: z2.string().min(1).describe("Contra (quote) asset contract address"),
|
|
424
|
+
qty: z2.string().min(1).describe("Order quantity as a decimal string"),
|
|
425
|
+
order_side: OrderSideEnum.describe("Buy or sell"),
|
|
426
|
+
limit_price: z2.string().optional().describe("Limit price (for limit orders)"),
|
|
427
|
+
limit_is_notional: z2.boolean().optional().describe("Whether limit price is in notional terms"),
|
|
428
|
+
trigger_price: z2.string().optional().describe("Trigger price (for stop/stop-loss/take-profit orders)"),
|
|
429
|
+
trigger_is_notional: z2.boolean().optional().describe("Whether trigger price is in notional terms"),
|
|
430
|
+
duration_seconds: z2.number().optional().describe("TWAP duration in seconds"),
|
|
431
|
+
target_twap_buckets: z2.number().optional().describe("Number of TWAP buckets"),
|
|
432
|
+
trigger_type: z2.enum(["upper", "lower"]).optional().describe("Trigger type for stop-buy orders only"),
|
|
433
|
+
slippage_tolerance: z2.string().optional().describe("Slippage tolerance as a decimal string (e.g. '1.0' for 1%)"),
|
|
434
|
+
max_price_impact: z2.string().optional().describe("Max price impact as a decimal string (e.g. '1.0' for 1%)"),
|
|
435
|
+
portfolio_id: portfolioIdParam2
|
|
436
|
+
}, {
|
|
437
|
+
readOnlyHint: false,
|
|
438
|
+
destructiveHint: true,
|
|
439
|
+
idempotentHint: false
|
|
440
|
+
}, async ({
|
|
441
|
+
quote_id,
|
|
442
|
+
type,
|
|
443
|
+
chain,
|
|
444
|
+
target_asset,
|
|
445
|
+
contra_asset,
|
|
446
|
+
qty,
|
|
447
|
+
order_side,
|
|
448
|
+
limit_price,
|
|
449
|
+
limit_is_notional,
|
|
450
|
+
trigger_price,
|
|
451
|
+
trigger_is_notional,
|
|
452
|
+
duration_seconds,
|
|
453
|
+
target_twap_buckets,
|
|
454
|
+
trigger_type,
|
|
455
|
+
slippage_tolerance,
|
|
456
|
+
max_price_impact,
|
|
457
|
+
portfolio_id
|
|
458
|
+
}) => {
|
|
459
|
+
const path = resolve("trade", portfolio_id);
|
|
460
|
+
const externalOrderRequest = {
|
|
461
|
+
type,
|
|
462
|
+
chain,
|
|
463
|
+
targetAsset: target_asset,
|
|
464
|
+
contraAsset: contra_asset,
|
|
465
|
+
qty,
|
|
466
|
+
orderSide: order_side
|
|
467
|
+
};
|
|
468
|
+
if (limit_price !== undefined)
|
|
469
|
+
externalOrderRequest.limit = { price: limit_price, isNotional: limit_is_notional ?? false };
|
|
470
|
+
if (trigger_price !== undefined)
|
|
471
|
+
externalOrderRequest.trigger = { price: trigger_price, isNotional: trigger_is_notional ?? false };
|
|
472
|
+
if (duration_seconds !== undefined)
|
|
473
|
+
externalOrderRequest.durationSeconds = duration_seconds;
|
|
474
|
+
if (target_twap_buckets !== undefined)
|
|
475
|
+
externalOrderRequest.targetTWAPBuckets = target_twap_buckets;
|
|
476
|
+
if (trigger_type !== undefined)
|
|
477
|
+
externalOrderRequest.triggerType = trigger_type;
|
|
478
|
+
if (slippage_tolerance !== undefined)
|
|
479
|
+
externalOrderRequest.slippageTolerance = slippage_tolerance;
|
|
480
|
+
if (max_price_impact !== undefined)
|
|
481
|
+
externalOrderRequest.maxPriceImpact = max_price_impact;
|
|
482
|
+
const result = await client.request("POST", path, undefined, {
|
|
483
|
+
quoteId: quote_id,
|
|
484
|
+
externalOrderRequest
|
|
485
|
+
});
|
|
486
|
+
return jsonResult2(result);
|
|
487
|
+
});
|
|
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. Always call get_quicktrade_quote first and confirm the details with the user before executing.", {
|
|
489
|
+
target_asset: z2.string().min(1).describe("Target asset contract address"),
|
|
490
|
+
contra_asset: z2.string().min(1).describe("Contra (quote) asset contract address"),
|
|
491
|
+
chain: ChainEnum2.describe("Blockchain network name"),
|
|
492
|
+
qty: z2.string().min(1).describe("Order quantity as a decimal string"),
|
|
493
|
+
order_side: OrderSideEnum.describe("Buy or sell"),
|
|
494
|
+
slippage_tolerance: z2.string().optional().describe("Slippage tolerance as a decimal string (e.g. '0.01' for 1%)"),
|
|
495
|
+
display_asset_price: z2.string().optional().describe("Target asset notional price for display validation"),
|
|
496
|
+
seconds_to_expire: z2.number().int().positive().optional().describe("Order expiry time in seconds"),
|
|
497
|
+
portfolio_id: portfolioIdParam2
|
|
498
|
+
}, {
|
|
499
|
+
readOnlyHint: false,
|
|
500
|
+
destructiveHint: true,
|
|
501
|
+
idempotentHint: false
|
|
502
|
+
}, async ({
|
|
503
|
+
target_asset,
|
|
504
|
+
contra_asset,
|
|
505
|
+
chain,
|
|
506
|
+
qty,
|
|
507
|
+
order_side,
|
|
508
|
+
slippage_tolerance,
|
|
509
|
+
display_asset_price,
|
|
510
|
+
seconds_to_expire,
|
|
511
|
+
portfolio_id
|
|
512
|
+
}) => {
|
|
513
|
+
const path = resolve("quicktrade", portfolio_id);
|
|
514
|
+
const body = {
|
|
515
|
+
type: "market",
|
|
516
|
+
chain,
|
|
517
|
+
targetAsset: target_asset,
|
|
518
|
+
contraAsset: contra_asset,
|
|
519
|
+
qty,
|
|
520
|
+
orderSide: order_side
|
|
521
|
+
};
|
|
522
|
+
if (slippage_tolerance !== undefined)
|
|
523
|
+
body.slippageTolerance = slippage_tolerance;
|
|
524
|
+
if (display_asset_price !== undefined)
|
|
525
|
+
body.displayAssetPrice = display_asset_price;
|
|
526
|
+
if (seconds_to_expire !== undefined)
|
|
527
|
+
body.secondsToExpire = seconds_to_expire;
|
|
528
|
+
const result = await client.request("POST", path, undefined, body);
|
|
529
|
+
return jsonResult2(result);
|
|
530
|
+
});
|
|
531
|
+
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: ChainEnum2.describe("Source blockchain network"),
|
|
533
|
+
to_chain: ChainEnum2.describe("Destination blockchain network"),
|
|
534
|
+
from_asset_address: z2.string().min(1).describe("Source asset contract address"),
|
|
535
|
+
to_asset_address: z2.string().min(1).describe("Destination asset contract address"),
|
|
536
|
+
from_amount: z2.string().min(1).describe("Amount to bridge as a decimal string"),
|
|
537
|
+
route_id: z2.string().min(1).describe("Route ID from bridge_quote response"),
|
|
538
|
+
portfolio_id: portfolioIdParam2
|
|
539
|
+
}, {
|
|
540
|
+
readOnlyHint: false,
|
|
541
|
+
destructiveHint: true,
|
|
542
|
+
idempotentHint: false
|
|
543
|
+
}, async ({
|
|
544
|
+
from_chain,
|
|
545
|
+
to_chain,
|
|
546
|
+
from_asset_address,
|
|
547
|
+
to_asset_address,
|
|
548
|
+
from_amount,
|
|
549
|
+
route_id,
|
|
550
|
+
portfolio_id
|
|
551
|
+
}) => {
|
|
552
|
+
const path = resolve("bridge", portfolio_id);
|
|
553
|
+
const body = {
|
|
554
|
+
fromChain: from_chain,
|
|
555
|
+
toChain: to_chain,
|
|
556
|
+
fromAssetAddress: from_asset_address,
|
|
557
|
+
toAssetAddress: to_asset_address,
|
|
558
|
+
fromAmount: from_amount,
|
|
559
|
+
routeId: route_id
|
|
560
|
+
};
|
|
561
|
+
const result = await client.request("POST", path, undefined, body);
|
|
562
|
+
return jsonResult2(result);
|
|
563
|
+
});
|
|
564
|
+
if (keyType !== "organization")
|
|
565
|
+
return;
|
|
566
|
+
server.tool("create_portfolio", "Create a new portfolio in the organization. Organization API keys only.", {
|
|
567
|
+
portfolio_name: z2.string().min(1).describe("Name for the new portfolio")
|
|
568
|
+
}, {
|
|
569
|
+
readOnlyHint: false,
|
|
570
|
+
destructiveHint: false
|
|
571
|
+
}, async ({ portfolio_name }) => {
|
|
572
|
+
const result = await client.request("POST", "/v2/organization/create-portfolio", undefined, { portfolioName: portfolio_name });
|
|
573
|
+
return jsonResult2(result);
|
|
574
|
+
});
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
|
|
578
|
+
import { z as z3 } from "zod";
|
|
579
|
+
var McpEnvSchema = z3.object({
|
|
580
|
+
DEFINITIVE_API_KEY: z3.string().startsWith("dpka_"),
|
|
581
|
+
DEFINITIVE_API_SECRET: z3.string().startsWith("dpks_"),
|
|
582
|
+
DEFINITIVE_BASE_URL: z3.string().url().default("https://ddp.definitive.fi"),
|
|
583
|
+
DEFINITIVE_API_KEY_TYPE: z3.enum(["portfolio", "organization"]),
|
|
584
|
+
DEFINITIVE_PORTFOLIO_ID: z3.string().optional()
|
|
255
585
|
});
|
|
256
586
|
var env = McpEnvSchema.parse(process.env);
|
|
257
587
|
var client = createClient(env.DEFINITIVE_BASE_URL, env.DEFINITIVE_API_KEY, env.DEFINITIVE_API_SECRET);
|
|
258
588
|
var server = new McpServer({
|
|
259
589
|
name: "Definitive",
|
|
260
|
-
version: "1.
|
|
261
|
-
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
|
|
590
|
+
version: "1.1.0",
|
|
591
|
+
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."
|
|
262
592
|
});
|
|
263
593
|
registerReadTools(server, client, env.DEFINITIVE_API_KEY_TYPE, env.DEFINITIVE_PORTFOLIO_ID);
|
|
594
|
+
registerWriteTools(server, client, env.DEFINITIVE_API_KEY_TYPE, env.DEFINITIVE_PORTFOLIO_ID);
|
|
264
595
|
var transport = new StdioServerTransport;
|
|
265
596
|
await server.connect(transport);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@definitive-fi/mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "MCP server for the Definitive on-chain trading platform",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": "dist/server.js",
|
|
@@ -8,13 +8,15 @@
|
|
|
8
8
|
"dist"
|
|
9
9
|
],
|
|
10
10
|
"scripts": {
|
|
11
|
-
"build": "bun run build.ts"
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
"node": ">=18"
|
|
11
|
+
"build": "bun run build.ts",
|
|
12
|
+
"dev": "bun run --hot src/server.ts",
|
|
13
|
+
"start": "bun run src/server.ts"
|
|
15
14
|
},
|
|
16
15
|
"dependencies": {
|
|
17
16
|
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
18
17
|
"zod": "^3.25.0"
|
|
18
|
+
},
|
|
19
|
+
"engines": {
|
|
20
|
+
"node": ">=18"
|
|
19
21
|
}
|
|
20
22
|
}
|