@definitive-fi/mcp 1.1.2 → 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.
Files changed (2) hide show
  1. package/dist/server.js +182 -72
  2. package/package.json +1 -1
package/dist/server.js CHANGED
@@ -116,7 +116,8 @@ var ChainEnum = z.enum([
116
116
  "hyperevm",
117
117
  "plasma",
118
118
  "monad",
119
- "robinhood"
119
+ "robinhood",
120
+ "ink"
120
121
  ]);
121
122
  var jsonResult = (result) => ({
122
123
  content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
@@ -124,12 +125,122 @@ var jsonResult = (result) => ({
124
125
 
125
126
 
126
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";
127
238
  function registerReadTools(server, client, keyType, defaultPortfolioId) {
128
239
  const resolve = (suffix, portfolioId) => resolvePortfolioRoute(keyType, suffix, portfolioId, defaultPortfolioId);
129
240
  server.tool("list_positions", "List current token holdings in the portfolio with balances, USD values, and P&L.", {
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"),
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"),
133
244
  portfolio_id: portfolioIdParam
134
245
  }, async ({ limit, cursor, include_dust_balances, portfolio_id }) => {
135
246
  const path = resolve("positions", portfolio_id);
@@ -149,17 +260,17 @@ function registerReadTools(server, client, keyType, defaultPortfolioId) {
149
260
  return jsonResult(result);
150
261
  });
151
262
  server.tool("list_transfers", "List historical transfers (deposits, withdrawals, swaps, bridge transactions) for the portfolio.", {
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([
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([
155
266
  "VAULT_ACTION_DEPOSIT",
156
267
  "VAULT_ACTION_WITHDRAW",
157
268
  "VAULT_ACTION_BRIDGE_SEND",
158
269
  "VAULT_ACTION_BRIDGE_RECEIVE",
159
270
  "VAULT_ACTION_SWAP"
160
271
  ])).optional().describe("Filter by transfer action types"),
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)"),
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)"),
163
274
  portfolio_id: portfolioIdParam
164
275
  }, async ({
165
276
  limit,
@@ -184,7 +295,7 @@ function registerReadTools(server, client, keyType, defaultPortfolioId) {
184
295
  });
185
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.", {
186
297
  chain: ChainEnum.describe("Blockchain network name"),
187
- wallet_address: z2.string().min(1).describe("User's wallet address on this chain — ask the user if not provided"),
298
+ wallet_address: z3.string().min(1).describe("User's wallet address on this chain — ask the user if not provided"),
188
299
  portfolio_id: portfolioIdParam
189
300
  }, async ({ chain, wallet_address, portfolio_id }) => {
190
301
  const path = resolve(`address/${chain}`, portfolio_id);
@@ -193,9 +304,9 @@ function registerReadTools(server, client, keyType, defaultPortfolioId) {
193
304
  return jsonResult(result);
194
305
  });
195
306
  server.tool("list_orders", "List trade orders with optional status filtering. Returns order details including fill status and pricing.", {
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([
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([
199
310
  "ORDER_STATUS_PENDING",
200
311
  "ORDER_STATUS_ACCEPTED",
201
312
  "ORDER_STATUS_PARTIALLY_FILLED",
@@ -224,8 +335,8 @@ function registerReadTools(server, client, keyType, defaultPortfolioId) {
224
335
  if (keyType !== "organization")
225
336
  return;
226
337
  server.tool("list_portfolios", "List all portfolios in the organization. Organization API keys only.", {
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")
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")
229
340
  }, async ({ limit, cursor }) => {
230
341
  const params = { limit: String(limit) };
231
342
  if (cursor)
@@ -235,8 +346,8 @@ function registerReadTools(server, client, keyType, defaultPortfolioId) {
235
346
  });
236
347
  server.tool("get_fees", "Get fee summary for a portfolio over a time period. Organization API keys only.", {
237
348
  portfolio_id: zUUID.describe("Portfolio UUID to get fees for"),
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)")
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)")
240
351
  }, async ({ portfolio_id, start_timestamp, end_timestamp }) => {
241
352
  const params = {};
242
353
  if (start_timestamp)
@@ -249,9 +360,9 @@ function registerReadTools(server, client, keyType, defaultPortfolioId) {
249
360
  }
250
361
 
251
362
 
252
- import { z as z3 } from "zod";
253
- var OrderSideEnum = z3.enum(["buy", "sell"]);
254
- var OrderTypeEnum = z3.enum([
363
+ import { z as z4 } from "zod";
364
+ var OrderSideEnum = z4.enum(["buy", "sell"]);
365
+ var OrderTypeEnum = z4.enum([
255
366
  "market",
256
367
  "limit",
257
368
  "twap",
@@ -264,19 +375,19 @@ function registerWriteTools(server, client, keyType, defaultPortfolioId) {
264
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.", {
265
376
  type: OrderTypeEnum.describe("Order type"),
266
377
  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"),
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"),
270
381
  order_side: OrderSideEnum.describe("Buy or sell"),
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%)"),
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%)"),
280
391
  portfolio_id: portfolioIdParam
281
392
  }, { readOnlyHint: true }, async ({
282
393
  type,
@@ -331,10 +442,10 @@ function registerWriteTools(server, client, keyType, defaultPortfolioId) {
331
442
  return jsonResult(result);
332
443
  });
333
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.", {
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"),
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"),
336
447
  chain: ChainEnum.describe("Blockchain network name"),
337
- qty: z3.string().min(1).describe("Order quantity as a decimal string"),
448
+ qty: z4.string().min(1).describe("Order quantity as a decimal string"),
338
449
  order_side: OrderSideEnum.describe("Buy or sell"),
339
450
  portfolio_id: portfolioIdParam
340
451
  }, { readOnlyHint: true }, async ({
@@ -358,11 +469,11 @@ function registerWriteTools(server, client, keyType, defaultPortfolioId) {
358
469
  return jsonResult(result);
359
470
  });
360
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.", {
361
- from_asset_address: z3.string().min(1).describe("Source asset contract address"),
472
+ from_asset_address: z4.string().min(1).describe("Source asset contract address"),
362
473
  from_chain: ChainEnum.describe("Source blockchain network"),
363
- to_asset_address: z3.string().min(1).describe("Destination asset contract address"),
474
+ to_asset_address: z4.string().min(1).describe("Destination asset contract address"),
364
475
  to_chain: ChainEnum.describe("Destination blockchain network"),
365
- from_amount: z3.string().min(1).describe("Amount to bridge as a decimal string"),
476
+ from_amount: z4.string().min(1).describe("Amount to bridge as a decimal string"),
366
477
  portfolio_id: portfolioIdParam
367
478
  }, { readOnlyHint: true }, async ({
368
479
  from_asset_address,
@@ -409,19 +520,19 @@ function registerWriteTools(server, client, keyType, defaultPortfolioId) {
409
520
  quote_id: zUUID.describe("Quote UUID from get_trade_quote response (found in quote.quote.id)"),
410
521
  type: OrderTypeEnum.describe("Order type"),
411
522
  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"),
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"),
415
526
  order_side: OrderSideEnum.describe("Buy or sell"),
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%)"),
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%)"),
425
536
  portfolio_id: portfolioIdParam
426
537
  }, {
427
538
  readOnlyHint: false,
@@ -482,14 +593,14 @@ function registerWriteTools(server, client, keyType, defaultPortfolioId) {
482
593
  return jsonResult(result);
483
594
  });
484
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.", {
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"),
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"),
487
598
  chain: ChainEnum.describe("Blockchain network name"),
488
- qty: z3.string().min(1).describe("Order quantity as a decimal string"),
599
+ qty: z4.string().min(1).describe("Order quantity as a decimal string"),
489
600
  order_side: OrderSideEnum.describe("Buy or sell"),
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"),
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"),
493
604
  portfolio_id: portfolioIdParam
494
605
  }, {
495
606
  readOnlyHint: false,
@@ -527,10 +638,10 @@ function registerWriteTools(server, client, keyType, defaultPortfolioId) {
527
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.", {
528
639
  from_chain: ChainEnum.describe("Source blockchain network"),
529
640
  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"),
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"),
534
645
  portfolio_id: portfolioIdParam
535
646
  }, {
536
647
  readOnlyHint: false,
@@ -560,7 +671,7 @@ function registerWriteTools(server, client, keyType, defaultPortfolioId) {
560
671
  if (keyType !== "organization")
561
672
  return;
562
673
  server.tool("create_portfolio", "Create a new portfolio in the organization. Organization API keys only.", {
563
- portfolio_name: z3.string().min(1).describe("Name for the new portfolio")
674
+ portfolio_name: z4.string().min(1).describe("Name for the new portfolio")
564
675
  }, {
565
676
  readOnlyHint: false,
566
677
  destructiveHint: false
@@ -571,22 +682,21 @@ function registerWriteTools(server, client, keyType, defaultPortfolioId) {
571
682
  }
572
683
 
573
684
 
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()
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()
581
692
  });
582
693
  var env = McpEnvSchema.parse(process.env);
583
694
  var client = createClient(env.DEFINITIVE_BASE_URL, env.DEFINITIVE_API_KEY, env.DEFINITIVE_API_SECRET);
584
- var server = new McpServer({
585
- name: "Definitive",
586
- version: "1.1.2",
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."
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."
588
697
  });
589
698
  registerReadTools(server, client, env.DEFINITIVE_API_KEY_TYPE, env.DEFINITIVE_PORTFOLIO_ID);
590
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);
591
701
  var transport = new StdioServerTransport;
592
702
  await server.connect(transport);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@definitive-fi/mcp",
3
- "version": "1.1.2",
3
+ "version": "1.2.0",
4
4
  "description": "MCP server for the Definitive on-chain trading platform",
5
5
  "keywords": [
6
6
  "mcp",