@tongateway/mcp 0.20.0 → 0.21.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/index.js +49 -25
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -321,7 +321,7 @@ server.tool('transfer.pending', 'List all transfer requests waiting for wallet o
321
321
  }
322
322
  });
323
323
  server.tool('transfer.batch', 'Send multiple TON transfers in a SINGLE wallet approval. Up to 4 transfers per batch (v4 wallet). All transfers appear as one transaction to sign. Use for batch payments, multi-recipient sends, or multiple DEX orders at once.', {
324
- transfers: z.string().describe('JSON array of transfers: [{"to":"addr","amountNano":"1000000000","comment":"optional text"},...]'),
324
+ transfers: z.string().describe('JSON array of transfers: [{"to":"addr","amountNano":"1000000000","comment":"optional text","payload":"base64 BOC"},...]. Use payload for custom BOC (e.g. DEX close order), comment for text messages. payload takes precedence over comment.'),
325
325
  }, { title: 'Batch Transfer', readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true }, async ({ transfers: transfersJson }) => {
326
326
  if (!TOKEN) {
327
327
  return { content: [{ type: 'text', text: 'No token configured. Use auth.request first.' }], isError: true };
@@ -332,11 +332,14 @@ server.tool('transfer.batch', 'Send multiple TON transfers in a SINGLE wallet ap
332
332
  throw new Error('No transfers provided');
333
333
  if (transfers.length > 4)
334
334
  throw new Error('Max 4 transfers per batch (v4 wallet). Use agent_wallet.batch_transfer for more.');
335
- // Encode comments as payloads
335
+ // Encode comments as payloads (payload field takes precedence)
336
336
  const processed = [];
337
337
  for (const t of transfers) {
338
338
  const entry = { to: t.to, amountNano: t.amountNano };
339
- if (t.comment) {
339
+ if (t.payload) {
340
+ entry.payload = t.payload;
341
+ }
342
+ else if (t.comment) {
340
343
  const { beginCell } = await import('@ton/core');
341
344
  const commentCell = beginCell().storeUint(0, 32).storeStringTail(t.comment).endCell();
342
345
  entry.payload = commentCell.toBoc().toString('base64');
@@ -359,7 +362,7 @@ server.tool('transfer.batch', 'Send multiple TON transfers in a SINGLE wallet ap
359
362
  `Total: ${totalTon} TON`,
360
363
  `Request ID: ${result.id}`,
361
364
  '',
362
- ...transfers.map((t, i) => ` ${i + 1}. ${t.amountNano} nanoTON → ${t.to.slice(0, 16)}...${t.comment ? ` "${t.comment}"` : ''}`),
365
+ ...transfers.map((t, i) => ` ${i + 1}. ${t.amountNano} nanoTON → ${t.to.slice(0, 16)}...${t.payload ? ' [payload]' : t.comment ? ` "${t.comment}"` : ''}`),
363
366
  '',
364
367
  'Approve in your wallet app — one signature for all transfers.',
365
368
  ].join('\n'),
@@ -500,35 +503,56 @@ server.tool('lookup.price', 'Get the current TON price in USD, EUR, or other cur
500
503
  return { content: [{ type: 'text', text: `Error: ${e.message}` }], isError: true };
501
504
  }
502
505
  });
503
- server.tool('dex.create_order', 'Place a limit order on the open4dev DEX order book. Both amount and price are human-readable the API converts to raw units automatically. The order requires wallet approval. Slippage (4% including fees) is applied automatically.', {
504
- fromToken: z.string().describe('Token to sell, e.g. "NOT", "TON", "USDT"'),
505
- toToken: z.string().describe('Token to buy, e.g. "TON", "NOT", "AGNT"'),
506
- amount: z.string().describe('Human-readable amount to sell, e.g. "10000" for 10,000 NOT or "5" for 5 USDT'),
507
- price: z.number().describe('Human-readable price: how many toToken per 1 fromToken. E.g. price=20 means "1 USDT = 20 AGNT". price=0.000289 means "1 NOT = 0.000289 TON".'),
508
- }, { title: 'Create DEX Order', readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true }, async ({ fromToken, toToken, amount, price }) => {
506
+ server.tool('dex.create_order', 'Place one or more limit orders on the open4dev DEX order book. For a single order, provide fromToken/toToken/amount/price directly. For multiple orders, provide an orders array. All orders are batched into one wallet transaction. Both amount and price are human-readable. Slippage (4% including fees) is applied automatically.', {
507
+ fromToken: z.string().optional().describe('Token to sell (single order), e.g. "NOT", "TON", "USDT"'),
508
+ toToken: z.string().optional().describe('Token to buy (single order), e.g. "TON", "NOT", "AGNT"'),
509
+ amount: z.string().optional().describe('Human-readable amount to sell (single order), e.g. "10000"'),
510
+ price: z.number().optional().describe('Human-readable price (single order): how many toToken per 1 fromToken'),
511
+ orders: z.array(z.object({
512
+ fromToken: z.string().describe('Token to sell'),
513
+ toToken: z.string().describe('Token to buy'),
514
+ amount: z.string().describe('Human-readable amount to sell'),
515
+ price: z.number().describe('Human-readable price: how many toToken per 1 fromToken'),
516
+ })).optional().describe('Array of orders for batch creation. If provided, flat params are ignored.'),
517
+ }, { title: 'Create DEX Order', readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true }, async ({ fromToken, toToken, amount, price, orders }) => {
509
518
  if (!TOKEN) {
510
519
  return { content: [{ type: 'text', text: 'No token configured. Use auth.request first.' }], isError: true };
511
520
  }
512
521
  try {
522
+ // Build request body: batch or single
523
+ let requestBody;
524
+ if (orders && orders.length > 0) {
525
+ requestBody = JSON.stringify({ orders });
526
+ }
527
+ else if (fromToken && toToken && amount && price) {
528
+ requestBody = JSON.stringify({ fromToken, toToken, amount, price });
529
+ }
530
+ else {
531
+ return { content: [{ type: 'text', text: 'Provide either orders array or fromToken/toToken/amount/price.' }], isError: true };
532
+ }
513
533
  const result = await apiCall('/v1/dex/order', {
514
534
  method: 'POST',
515
- body: JSON.stringify({ fromToken, toToken, amount, price }),
535
+ body: requestBody,
516
536
  });
537
+ // Format output
538
+ const orderList = result.orders || [result.swap];
539
+ const lines = [];
540
+ if (orderList.length === 1) {
541
+ const s = orderList[0];
542
+ lines.push(`Order placed on open4dev DEX!`, ``, `${s.fromToken} → ${s.toToken}`, `Amount: ${s.amount}`, `Price: ${s.price} ${s.toToken} per ${s.fromToken}`, `Slippage: ${s.slippage ?? 4}% (includes fees)`);
543
+ }
544
+ else {
545
+ lines.push(`${orderList.length} orders placed on open4dev DEX!`, ``);
546
+ for (let i = 0; i < orderList.length; i++) {
547
+ const s = orderList[i];
548
+ lines.push(`Order ${i + 1}: ${s.fromToken} → ${s.toToken} | Amount: ${s.amount} | Price: ${s.price}`);
549
+ }
550
+ lines.push(``);
551
+ lines.push(`Slippage: 4% (includes fees)`);
552
+ }
553
+ lines.push(`Request ID: ${result.id}`, ``, `Approve in your wallet app.`);
517
554
  return {
518
- content: [{
519
- type: 'text',
520
- text: [
521
- `Order placed on open4dev DEX!`,
522
- ``,
523
- `${fromToken} → ${toToken}`,
524
- `Amount: ${amount}`,
525
- `Price: ${price} ${toToken} per ${fromToken}`,
526
- `Slippage: ${result.swap?.slippage ?? 4}% (includes fees)`,
527
- `Request ID: ${result.id}`,
528
- ``,
529
- `Approve the order in your wallet app.`,
530
- ].join('\n'),
531
- }],
555
+ content: [{ type: 'text', text: lines.join('\n') }],
532
556
  };
533
557
  }
534
558
  catch (e) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tongateway/mcp",
3
- "version": "0.20.0",
3
+ "version": "0.21.0",
4
4
  "description": "TON blockchain gateway for AI agents — 16 MCP tools: wallet info, transfers, jettons, NFTs, DNS, prices, DEX orders, agent wallets",
5
5
  "homepage": "https://tongateway.ai",
6
6
  "license": "MIT",