@tongateway/mcp 0.2.0 → 0.3.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 +130 -0
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -228,5 +228,135 @@ server.tool('list_pending_requests', 'List all pending transfer requests waiting
228
228
  };
229
229
  }
230
230
  });
231
+ server.tool('get_wallet_info', 'Get the connected wallet address, TON balance, and account status.', {}, async () => {
232
+ if (!TOKEN) {
233
+ return { content: [{ type: 'text', text: 'No token configured. Use request_auth first.' }], isError: true };
234
+ }
235
+ try {
236
+ const result = await apiCall('/v1/wallet/balance');
237
+ const balanceTon = (BigInt(result.balance) / 1000000000n).toString();
238
+ const balanceFrac = (BigInt(result.balance) % 1000000000n).toString().padStart(9, '0').replace(/0+$/, '') || '0';
239
+ return {
240
+ content: [{
241
+ type: 'text',
242
+ text: [
243
+ `Address: ${result.address}`,
244
+ `Balance: ${balanceTon}.${balanceFrac} TON (${result.balance} nanoTON)`,
245
+ `Status: ${result.status}`,
246
+ ].join('\n'),
247
+ }],
248
+ };
249
+ }
250
+ catch (e) {
251
+ return { content: [{ type: 'text', text: `Error: ${e.message}` }], isError: true };
252
+ }
253
+ });
254
+ server.tool('get_jetton_balances', 'Get all jetton (token) balances in the connected wallet. Shows USDT, NOT, DOGS, and other tokens.', {}, async () => {
255
+ if (!TOKEN) {
256
+ return { content: [{ type: 'text', text: 'No token configured. Use request_auth first.' }], isError: true };
257
+ }
258
+ try {
259
+ const result = await apiCall('/v1/wallet/jettons');
260
+ if (!result.balances?.length) {
261
+ return { content: [{ type: 'text', text: 'No jettons found in this wallet.' }] };
262
+ }
263
+ const lines = result.balances.map((b) => {
264
+ const decimals = b.decimals ?? 9;
265
+ const raw = BigInt(b.balance);
266
+ const divisor = BigInt(10 ** decimals);
267
+ const whole = (raw / divisor).toString();
268
+ const frac = (raw % divisor).toString().padStart(decimals, '0').replace(/0+$/, '') || '0';
269
+ return `- ${b.symbol ?? b.name ?? 'Unknown'}: ${whole}.${frac} (${b.address})`;
270
+ });
271
+ return {
272
+ content: [{ type: 'text', text: `Jetton balances:\n${lines.join('\n')}` }],
273
+ };
274
+ }
275
+ catch (e) {
276
+ return { content: [{ type: 'text', text: `Error: ${e.message}` }], isError: true };
277
+ }
278
+ });
279
+ server.tool('get_transactions', 'Get recent transaction history for the connected wallet.', {
280
+ limit: z.number().optional().describe('Number of transactions to return (default 10)'),
281
+ }, async ({ limit }) => {
282
+ if (!TOKEN) {
283
+ return { content: [{ type: 'text', text: 'No token configured. Use request_auth first.' }], isError: true };
284
+ }
285
+ try {
286
+ const result = await apiCall(`/v1/wallet/transactions?limit=${limit ?? 10}`);
287
+ const events = result.events ?? [];
288
+ if (!events.length) {
289
+ return { content: [{ type: 'text', text: 'No recent transactions.' }] };
290
+ }
291
+ const lines = events.map((e) => {
292
+ const time = new Date(e.timestamp * 1000).toISOString();
293
+ const actions = (e.actions ?? []).map((a) => a.type).join(', ');
294
+ return `- ${time}: ${actions || 'unknown'} ${e.is_scam ? '[SCAM]' : ''}`;
295
+ });
296
+ return {
297
+ content: [{ type: 'text', text: `Recent transactions:\n${lines.join('\n')}` }],
298
+ };
299
+ }
300
+ catch (e) {
301
+ return { content: [{ type: 'text', text: `Error: ${e.message}` }], isError: true };
302
+ }
303
+ });
304
+ server.tool('get_nft_items', 'List NFTs owned by the connected wallet.', {}, async () => {
305
+ if (!TOKEN) {
306
+ return { content: [{ type: 'text', text: 'No token configured. Use request_auth first.' }], isError: true };
307
+ }
308
+ try {
309
+ const result = await apiCall('/v1/wallet/nfts');
310
+ const nfts = result.nfts ?? [];
311
+ if (!nfts.length) {
312
+ return { content: [{ type: 'text', text: 'No NFTs found in this wallet.' }] };
313
+ }
314
+ const lines = nfts.map((n) => `- ${n.name ?? 'Unnamed'} ${n.collection ? `(${n.collection})` : ''} — ${n.address}`);
315
+ return {
316
+ content: [{ type: 'text', text: `NFTs (${nfts.length}):\n${lines.join('\n')}` }],
317
+ };
318
+ }
319
+ catch (e) {
320
+ return { content: [{ type: 'text', text: `Error: ${e.message}` }], isError: true };
321
+ }
322
+ });
323
+ server.tool('resolve_name', 'Resolve a .ton domain name to a wallet address. Use this when the user says "send to alice.ton" instead of a raw address.', {
324
+ domain: z.string().describe('The .ton domain name to resolve (e.g. "alice.ton")'),
325
+ }, async ({ domain }) => {
326
+ try {
327
+ const result = await fetch(`${API_URL}/v1/dns/${encodeURIComponent(domain)}/resolve`);
328
+ const data = await result.json();
329
+ if (!result.ok)
330
+ throw new Error(data.error ?? 'Failed');
331
+ if (!data.address) {
332
+ return { content: [{ type: 'text', text: `Domain "${domain}" not found or has no wallet address.` }] };
333
+ }
334
+ return {
335
+ content: [{ type: 'text', text: `${domain} → ${data.address}` }],
336
+ };
337
+ }
338
+ catch (e) {
339
+ return { content: [{ type: 'text', text: `Error: ${e.message}` }], isError: true };
340
+ }
341
+ });
342
+ server.tool('get_ton_price', 'Get the current price of TON in USD and other currencies.', {
343
+ currencies: z.string().optional().describe('Comma-separated currencies (default "USD")'),
344
+ }, async ({ currencies }) => {
345
+ try {
346
+ const curr = currencies || 'USD';
347
+ const result = await fetch(`${API_URL}/v1/market/price?tokens=TON&currencies=${curr}`);
348
+ const data = await result.json();
349
+ if (!result.ok)
350
+ throw new Error(data.error ?? 'Failed');
351
+ const tonRates = data.rates?.TON?.prices ?? {};
352
+ const lines = Object.entries(tonRates).map(([c, p]) => `1 TON = ${p} ${c}`);
353
+ return {
354
+ content: [{ type: 'text', text: lines.length ? lines.join('\n') : 'Price data unavailable.' }],
355
+ };
356
+ }
357
+ catch (e) {
358
+ return { content: [{ type: 'text', text: `Error: ${e.message}` }], isError: true };
359
+ }
360
+ });
231
361
  const transport = new StdioServerTransport();
232
362
  await server.connect(transport);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tongateway/mcp",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "MCP server for Agent Gateway — lets AI agents request TON blockchain transfers",
5
5
  "license": "MIT",
6
6
  "repository": {