@t402/mcp 2.4.0 → 2.6.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/bin/t402-mcp.js +19 -3
- package/dist/cjs/index.d.ts +4 -3
- package/dist/cjs/index.js +1054 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/server/index.d.ts +51 -1
- package/dist/cjs/server/index.js +1036 -1
- package/dist/cjs/server/index.js.map +1 -1
- package/dist/cjs/{types-CWK2p9_n.d.ts → ton-bridge-BN3RKhNy.d.ts} +93 -1
- package/dist/cjs/tools/index.d.ts +620 -3
- package/dist/cjs/tools/index.js +945 -2
- package/dist/cjs/tools/index.js.map +1 -1
- package/dist/esm/{chunk-U2V6MOSU.mjs → chunk-3FGPOVUZ.mjs} +202 -4
- package/dist/esm/chunk-3FGPOVUZ.mjs.map +1 -0
- package/dist/esm/{chunk-5IVOABVF.mjs → chunk-RDQ7AMR4.mjs} +912 -2
- package/dist/esm/chunk-RDQ7AMR4.mjs.map +1 -0
- package/dist/esm/index.d.mts +4 -3
- package/dist/esm/index.mjs +20 -2
- package/dist/esm/server/index.d.mts +51 -1
- package/dist/esm/server/index.mjs +2 -2
- package/dist/esm/{types-CWK2p9_n.d.mts → ton-bridge-BN3RKhNy.d.mts} +93 -1
- package/dist/esm/tools/index.d.mts +620 -3
- package/dist/esm/tools/index.mjs +69 -3
- package/package.json +26 -16
- package/dist/esm/chunk-5IVOABVF.mjs.map +0 -1
- package/dist/esm/chunk-U2V6MOSU.mjs.map +0 -1
package/dist/cjs/server/index.js
CHANGED
|
@@ -1151,6 +1151,771 @@ function formatBridgeResult(result) {
|
|
|
1151
1151
|
].join("\n");
|
|
1152
1152
|
}
|
|
1153
1153
|
|
|
1154
|
+
// src/tools/wdkGetWallet.ts
|
|
1155
|
+
var import_zod7 = require("zod");
|
|
1156
|
+
var wdkGetWalletInputSchema = import_zod7.z.object({});
|
|
1157
|
+
async function executeWdkGetWallet(_input, wdk) {
|
|
1158
|
+
const signer = await wdk.getSigner("ethereum");
|
|
1159
|
+
const chains6 = wdk.getConfiguredChains();
|
|
1160
|
+
return {
|
|
1161
|
+
evmAddress: signer.address,
|
|
1162
|
+
chains: chains6.length > 0 ? chains6 : ["ethereum"]
|
|
1163
|
+
};
|
|
1164
|
+
}
|
|
1165
|
+
function executeWdkGetWalletDemo() {
|
|
1166
|
+
return {
|
|
1167
|
+
evmAddress: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
|
|
1168
|
+
chains: ["ethereum", "arbitrum", "base", "optimism"]
|
|
1169
|
+
};
|
|
1170
|
+
}
|
|
1171
|
+
function formatWdkWalletResult(info) {
|
|
1172
|
+
const lines = [
|
|
1173
|
+
"## WDK Wallet Info",
|
|
1174
|
+
"",
|
|
1175
|
+
`**EVM Address:** \`${info.evmAddress}\``,
|
|
1176
|
+
"",
|
|
1177
|
+
"### Supported Chains",
|
|
1178
|
+
...info.chains.map((c) => `- ${c}`)
|
|
1179
|
+
];
|
|
1180
|
+
return lines.join("\n");
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
// src/tools/wdkGetBalances.ts
|
|
1184
|
+
var import_zod8 = require("zod");
|
|
1185
|
+
var import_viem6 = require("viem");
|
|
1186
|
+
var wdkGetBalancesInputSchema = import_zod8.z.object({
|
|
1187
|
+
chains: import_zod8.z.array(import_zod8.z.string()).optional().describe("Optional list of chains to check. If not provided, checks all configured chains.")
|
|
1188
|
+
});
|
|
1189
|
+
function findTokenFormatted(tokens, symbol) {
|
|
1190
|
+
return tokens.find((t) => t.symbol === symbol)?.formatted ?? "0";
|
|
1191
|
+
}
|
|
1192
|
+
async function executeWdkGetBalances(input, wdk) {
|
|
1193
|
+
const balances = await wdk.getAggregatedBalances();
|
|
1194
|
+
const chains6 = balances.chains.filter((c) => !input.chains || input.chains.includes(c.chain)).map((c) => ({
|
|
1195
|
+
chain: c.chain,
|
|
1196
|
+
usdt0: findTokenFormatted(c.tokens, "USDT0"),
|
|
1197
|
+
usdc: findTokenFormatted(c.tokens, "USDC"),
|
|
1198
|
+
native: (0, import_viem6.formatUnits)(c.native, 18)
|
|
1199
|
+
}));
|
|
1200
|
+
return {
|
|
1201
|
+
chains: chains6,
|
|
1202
|
+
totalUsdt0: (0, import_viem6.formatUnits)(balances.totalUsdt0, 6),
|
|
1203
|
+
totalUsdc: (0, import_viem6.formatUnits)(balances.totalUsdc, 6)
|
|
1204
|
+
};
|
|
1205
|
+
}
|
|
1206
|
+
function executeWdkGetBalancesDemo() {
|
|
1207
|
+
return {
|
|
1208
|
+
chains: [
|
|
1209
|
+
{ chain: "ethereum", usdt0: "100.00", usdc: "250.00", native: "0.5" },
|
|
1210
|
+
{ chain: "arbitrum", usdt0: "500.00", usdc: "0", native: "0.01" },
|
|
1211
|
+
{ chain: "base", usdt0: "200.00", usdc: "100.00", native: "0.02" }
|
|
1212
|
+
],
|
|
1213
|
+
totalUsdt0: "800.00",
|
|
1214
|
+
totalUsdc: "350.00"
|
|
1215
|
+
};
|
|
1216
|
+
}
|
|
1217
|
+
function formatWdkBalancesResult(result) {
|
|
1218
|
+
const lines = [
|
|
1219
|
+
"## WDK Multi-Chain Balances",
|
|
1220
|
+
"",
|
|
1221
|
+
`**Total USDT0:** ${result.totalUsdt0}`,
|
|
1222
|
+
`**Total USDC:** ${result.totalUsdc}`,
|
|
1223
|
+
"",
|
|
1224
|
+
"### Per-Chain Breakdown",
|
|
1225
|
+
""
|
|
1226
|
+
];
|
|
1227
|
+
for (const chain of result.chains) {
|
|
1228
|
+
lines.push(`**${chain.chain}**`);
|
|
1229
|
+
lines.push(`- USDT0: ${chain.usdt0}`);
|
|
1230
|
+
lines.push(`- USDC: ${chain.usdc}`);
|
|
1231
|
+
lines.push(`- Native: ${chain.native}`);
|
|
1232
|
+
lines.push("");
|
|
1233
|
+
}
|
|
1234
|
+
return lines.join("\n");
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
// src/tools/wdkTransfer.ts
|
|
1238
|
+
var import_zod9 = require("zod");
|
|
1239
|
+
var wdkTransferInputSchema = import_zod9.z.object({
|
|
1240
|
+
to: import_zod9.z.string().describe("Recipient address"),
|
|
1241
|
+
amount: import_zod9.z.string().regex(/^\d+(\.\d+)?$/).describe("Amount to send (e.g., '10.50')"),
|
|
1242
|
+
token: import_zod9.z.enum(["USDC", "USDT", "USDT0"]).describe("Token to transfer"),
|
|
1243
|
+
chain: import_zod9.z.string().describe('Chain to execute transfer on (e.g., "ethereum", "arbitrum")')
|
|
1244
|
+
});
|
|
1245
|
+
async function executeWdkTransfer(input, wdk) {
|
|
1246
|
+
const signer = await wdk.getSigner(input.chain);
|
|
1247
|
+
const result = await signer.sendTransaction({
|
|
1248
|
+
to: input.to
|
|
1249
|
+
});
|
|
1250
|
+
const txHash = result.hash;
|
|
1251
|
+
const explorerUrl = getExplorerTxUrl(input.chain, txHash);
|
|
1252
|
+
return {
|
|
1253
|
+
txHash,
|
|
1254
|
+
amount: input.amount,
|
|
1255
|
+
token: input.token,
|
|
1256
|
+
chain: input.chain,
|
|
1257
|
+
to: input.to,
|
|
1258
|
+
explorerUrl
|
|
1259
|
+
};
|
|
1260
|
+
}
|
|
1261
|
+
function executeWdkTransferDemo(input) {
|
|
1262
|
+
const demoTxHash = "0xdemo" + Math.random().toString(16).slice(2, 10);
|
|
1263
|
+
return {
|
|
1264
|
+
txHash: demoTxHash,
|
|
1265
|
+
amount: input.amount,
|
|
1266
|
+
token: input.token,
|
|
1267
|
+
chain: input.chain,
|
|
1268
|
+
to: input.to,
|
|
1269
|
+
explorerUrl: `https://etherscan.io/tx/${demoTxHash}`
|
|
1270
|
+
};
|
|
1271
|
+
}
|
|
1272
|
+
function formatWdkTransferResult(result) {
|
|
1273
|
+
return [
|
|
1274
|
+
"## WDK Transfer Complete",
|
|
1275
|
+
"",
|
|
1276
|
+
`**Amount:** ${result.amount} ${result.token}`,
|
|
1277
|
+
`**Chain:** ${result.chain}`,
|
|
1278
|
+
`**To:** \`${result.to}\``,
|
|
1279
|
+
`**Tx Hash:** \`${result.txHash}\``,
|
|
1280
|
+
`**Explorer:** [View Transaction](${result.explorerUrl})`
|
|
1281
|
+
].join("\n");
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
// src/tools/wdkSwap.ts
|
|
1285
|
+
var import_zod10 = require("zod");
|
|
1286
|
+
var import_viem7 = require("viem");
|
|
1287
|
+
var wdkSwapInputSchema = import_zod10.z.object({
|
|
1288
|
+
fromToken: import_zod10.z.string().describe('Token to swap from (e.g., "ETH", "USDC")'),
|
|
1289
|
+
toToken: import_zod10.z.string().describe('Token to swap to (e.g., "USDT0", "USDC")'),
|
|
1290
|
+
amount: import_zod10.z.string().regex(/^\d+(\.\d+)?$/).describe("Amount to swap (e.g., '1.0')"),
|
|
1291
|
+
chain: import_zod10.z.string().describe('Chain to execute swap on (e.g., "ethereum", "arbitrum")')
|
|
1292
|
+
});
|
|
1293
|
+
async function executeWdkSwap(input, wdk) {
|
|
1294
|
+
const decimals = ["USDC", "USDT", "USDT0"].includes(input.fromToken.toUpperCase()) ? 6 : 18;
|
|
1295
|
+
const amountBigInt = (0, import_viem7.parseUnits)(input.amount, decimals);
|
|
1296
|
+
const quote = await wdk.getSwapQuote(input.chain, input.fromToken, amountBigInt);
|
|
1297
|
+
const result = await wdk.swapAndPay({
|
|
1298
|
+
chain: input.chain,
|
|
1299
|
+
fromToken: input.fromToken,
|
|
1300
|
+
amount: amountBigInt
|
|
1301
|
+
});
|
|
1302
|
+
const outputDecimals = ["USDC", "USDT", "USDT0"].includes(input.toToken.toUpperCase()) ? 6 : 18;
|
|
1303
|
+
const toAmount = (0, import_viem7.formatUnits)(result?.outputAmount ?? quote.outputAmount, outputDecimals);
|
|
1304
|
+
return {
|
|
1305
|
+
fromAmount: input.amount,
|
|
1306
|
+
fromToken: input.fromToken,
|
|
1307
|
+
toAmount,
|
|
1308
|
+
toToken: input.toToken,
|
|
1309
|
+
chain: input.chain,
|
|
1310
|
+
txHash: result?.txHash
|
|
1311
|
+
};
|
|
1312
|
+
}
|
|
1313
|
+
function executeWdkSwapDemo(input) {
|
|
1314
|
+
const inputAmount = parseFloat(input.amount);
|
|
1315
|
+
const outputAmount = (inputAmount * 0.997).toFixed(6);
|
|
1316
|
+
return {
|
|
1317
|
+
fromAmount: input.amount,
|
|
1318
|
+
fromToken: input.fromToken,
|
|
1319
|
+
toAmount: outputAmount,
|
|
1320
|
+
toToken: input.toToken,
|
|
1321
|
+
chain: input.chain,
|
|
1322
|
+
txHash: "0xdemo" + Math.random().toString(16).slice(2, 10)
|
|
1323
|
+
};
|
|
1324
|
+
}
|
|
1325
|
+
function formatWdkSwapResult(result) {
|
|
1326
|
+
const lines = [
|
|
1327
|
+
"## WDK Swap Result",
|
|
1328
|
+
"",
|
|
1329
|
+
`**From:** ${result.fromAmount} ${result.fromToken}`,
|
|
1330
|
+
`**To:** ${result.toAmount} ${result.toToken}`,
|
|
1331
|
+
`**Chain:** ${result.chain}`
|
|
1332
|
+
];
|
|
1333
|
+
if (result.txHash) {
|
|
1334
|
+
lines.push(`**Tx Hash:** \`${result.txHash}\``);
|
|
1335
|
+
}
|
|
1336
|
+
return lines.join("\n");
|
|
1337
|
+
}
|
|
1338
|
+
|
|
1339
|
+
// src/tools/autoPay.ts
|
|
1340
|
+
var import_zod11 = require("zod");
|
|
1341
|
+
var import_wdk_protocol = require("@t402/wdk-protocol");
|
|
1342
|
+
var autoPayInputSchema = import_zod11.z.object({
|
|
1343
|
+
url: import_zod11.z.string().url().describe("URL to fetch (may return 402 Payment Required)"),
|
|
1344
|
+
maxAmount: import_zod11.z.string().regex(/^\d+(\.\d+)?$/).optional().describe('Maximum amount willing to pay (e.g., "10.00"). If not set, pays any amount.'),
|
|
1345
|
+
preferredChain: import_zod11.z.string().optional().describe(
|
|
1346
|
+
'Preferred chain for payment (e.g., "arbitrum"). If not specified, uses first available.'
|
|
1347
|
+
)
|
|
1348
|
+
});
|
|
1349
|
+
async function executeAutoPay(input, wdk) {
|
|
1350
|
+
const chains6 = input.preferredChain ? [input.preferredChain] : ["ethereum", "arbitrum", "base"];
|
|
1351
|
+
const protocol = await import_wdk_protocol.T402Protocol.create(wdk, { chains: chains6 });
|
|
1352
|
+
const { response, receipt } = await protocol.fetch(input.url);
|
|
1353
|
+
if (receipt && input.maxAmount) {
|
|
1354
|
+
const paidAmount = parseFloat(receipt.amount) / 1e6;
|
|
1355
|
+
const maxAmount = parseFloat(input.maxAmount);
|
|
1356
|
+
if (paidAmount > maxAmount) {
|
|
1357
|
+
return {
|
|
1358
|
+
success: false,
|
|
1359
|
+
statusCode: 402,
|
|
1360
|
+
body: "",
|
|
1361
|
+
error: `Payment amount (${paidAmount}) exceeds max allowed (${maxAmount})`
|
|
1362
|
+
};
|
|
1363
|
+
}
|
|
1364
|
+
}
|
|
1365
|
+
const contentType = response.headers.get("content-type") ?? void 0;
|
|
1366
|
+
let body = "";
|
|
1367
|
+
try {
|
|
1368
|
+
body = await response.text();
|
|
1369
|
+
if (body.length > 1e4) {
|
|
1370
|
+
body = body.slice(0, 1e4) + "\n... (truncated)";
|
|
1371
|
+
}
|
|
1372
|
+
} catch {
|
|
1373
|
+
body = "[Could not read response body]";
|
|
1374
|
+
}
|
|
1375
|
+
return {
|
|
1376
|
+
success: response.ok,
|
|
1377
|
+
statusCode: response.status,
|
|
1378
|
+
body,
|
|
1379
|
+
contentType,
|
|
1380
|
+
payment: receipt ? {
|
|
1381
|
+
network: receipt.network,
|
|
1382
|
+
scheme: receipt.scheme,
|
|
1383
|
+
amount: receipt.amount,
|
|
1384
|
+
payTo: receipt.payTo
|
|
1385
|
+
} : void 0
|
|
1386
|
+
};
|
|
1387
|
+
}
|
|
1388
|
+
function executeAutoPayDemo(input) {
|
|
1389
|
+
return {
|
|
1390
|
+
success: true,
|
|
1391
|
+
statusCode: 200,
|
|
1392
|
+
body: `[Demo] Premium content from ${input.url}
|
|
1393
|
+
|
|
1394
|
+
This is simulated content that would be returned after payment.`,
|
|
1395
|
+
contentType: "text/plain",
|
|
1396
|
+
payment: {
|
|
1397
|
+
network: "eip155:42161",
|
|
1398
|
+
scheme: "exact",
|
|
1399
|
+
amount: "1000000",
|
|
1400
|
+
payTo: "0xC88f67e776f16DcFBf42e6bDda1B82604448899B"
|
|
1401
|
+
}
|
|
1402
|
+
};
|
|
1403
|
+
}
|
|
1404
|
+
function formatAutoPayResult(result) {
|
|
1405
|
+
const lines = ["## AutoPay Result", ""];
|
|
1406
|
+
if (result.success) {
|
|
1407
|
+
lines.push(`**Status:** Success (${result.statusCode})`);
|
|
1408
|
+
} else {
|
|
1409
|
+
lines.push(`**Status:** Failed (${result.statusCode})`);
|
|
1410
|
+
}
|
|
1411
|
+
if (result.payment) {
|
|
1412
|
+
lines.push("");
|
|
1413
|
+
lines.push("### Payment Details");
|
|
1414
|
+
lines.push(`- **Network:** ${result.payment.network}`);
|
|
1415
|
+
lines.push(`- **Scheme:** ${result.payment.scheme}`);
|
|
1416
|
+
lines.push(`- **Amount:** ${result.payment.amount}`);
|
|
1417
|
+
lines.push(`- **Pay To:** \`${result.payment.payTo}\``);
|
|
1418
|
+
}
|
|
1419
|
+
if (result.error) {
|
|
1420
|
+
lines.push("");
|
|
1421
|
+
lines.push(`**Error:** ${result.error}`);
|
|
1422
|
+
}
|
|
1423
|
+
if (result.body) {
|
|
1424
|
+
lines.push("");
|
|
1425
|
+
lines.push("### Response Content");
|
|
1426
|
+
if (result.contentType) {
|
|
1427
|
+
lines.push(`_Content-Type: ${result.contentType}_`);
|
|
1428
|
+
}
|
|
1429
|
+
lines.push("");
|
|
1430
|
+
lines.push("```");
|
|
1431
|
+
lines.push(result.body);
|
|
1432
|
+
lines.push("```");
|
|
1433
|
+
}
|
|
1434
|
+
return lines.join("\n");
|
|
1435
|
+
}
|
|
1436
|
+
|
|
1437
|
+
// src/tools/ton-bridge.ts
|
|
1438
|
+
var TON_BRIDGE_TOOLS = {
|
|
1439
|
+
"ton/getBalance": {
|
|
1440
|
+
name: "ton/getBalance",
|
|
1441
|
+
description: "Get TON and Jetton balances for a wallet address on the TON blockchain.",
|
|
1442
|
+
inputSchema: {
|
|
1443
|
+
type: "object",
|
|
1444
|
+
properties: {
|
|
1445
|
+
address: {
|
|
1446
|
+
type: "string",
|
|
1447
|
+
description: "TON wallet address (friendly or raw format)"
|
|
1448
|
+
}
|
|
1449
|
+
},
|
|
1450
|
+
required: ["address"]
|
|
1451
|
+
}
|
|
1452
|
+
},
|
|
1453
|
+
"ton/transfer": {
|
|
1454
|
+
name: "ton/transfer",
|
|
1455
|
+
description: "Send TON to a recipient address on the TON blockchain.",
|
|
1456
|
+
inputSchema: {
|
|
1457
|
+
type: "object",
|
|
1458
|
+
properties: {
|
|
1459
|
+
to: {
|
|
1460
|
+
type: "string",
|
|
1461
|
+
description: "Recipient TON address"
|
|
1462
|
+
},
|
|
1463
|
+
amount: {
|
|
1464
|
+
type: "string",
|
|
1465
|
+
description: 'Amount of TON to send (e.g., "1.5")'
|
|
1466
|
+
},
|
|
1467
|
+
memo: {
|
|
1468
|
+
type: "string",
|
|
1469
|
+
description: "Optional memo/comment for the transfer"
|
|
1470
|
+
}
|
|
1471
|
+
},
|
|
1472
|
+
required: ["to", "amount"]
|
|
1473
|
+
}
|
|
1474
|
+
},
|
|
1475
|
+
"ton/getJettonBalance": {
|
|
1476
|
+
name: "ton/getJettonBalance",
|
|
1477
|
+
description: "Get the balance of a specific Jetton (TON token) for a wallet address.",
|
|
1478
|
+
inputSchema: {
|
|
1479
|
+
type: "object",
|
|
1480
|
+
properties: {
|
|
1481
|
+
address: {
|
|
1482
|
+
type: "string",
|
|
1483
|
+
description: "TON wallet address"
|
|
1484
|
+
},
|
|
1485
|
+
jettonMaster: {
|
|
1486
|
+
type: "string",
|
|
1487
|
+
description: "Jetton master contract address"
|
|
1488
|
+
}
|
|
1489
|
+
},
|
|
1490
|
+
required: ["address", "jettonMaster"]
|
|
1491
|
+
}
|
|
1492
|
+
},
|
|
1493
|
+
"ton/swapJettons": {
|
|
1494
|
+
name: "ton/swapJettons",
|
|
1495
|
+
description: "Swap Jettons (TON tokens) using DEX aggregation on the TON network. Returns a raw transaction JSON to be sent via sendTransaction.",
|
|
1496
|
+
inputSchema: {
|
|
1497
|
+
type: "object",
|
|
1498
|
+
properties: {
|
|
1499
|
+
from: {
|
|
1500
|
+
type: "string",
|
|
1501
|
+
description: 'Source Jetton master address (or "TON" for native TON)'
|
|
1502
|
+
},
|
|
1503
|
+
to: {
|
|
1504
|
+
type: "string",
|
|
1505
|
+
description: 'Destination Jetton master address (or "TON" for native TON)'
|
|
1506
|
+
},
|
|
1507
|
+
amount: {
|
|
1508
|
+
type: "string",
|
|
1509
|
+
description: 'Amount to swap in human-readable format (e.g., "1.5")'
|
|
1510
|
+
},
|
|
1511
|
+
slippage: {
|
|
1512
|
+
type: "string",
|
|
1513
|
+
description: 'Slippage tolerance (e.g., "0.5" for 0.5%)'
|
|
1514
|
+
}
|
|
1515
|
+
},
|
|
1516
|
+
required: ["from", "to", "amount"]
|
|
1517
|
+
}
|
|
1518
|
+
},
|
|
1519
|
+
"ton/getTransactionStatus": {
|
|
1520
|
+
name: "ton/getTransactionStatus",
|
|
1521
|
+
description: "Check the status and details of a TON transaction by its hash.",
|
|
1522
|
+
inputSchema: {
|
|
1523
|
+
type: "object",
|
|
1524
|
+
properties: {
|
|
1525
|
+
txHash: {
|
|
1526
|
+
type: "string",
|
|
1527
|
+
description: "Transaction hash (BOC hash or message hash)"
|
|
1528
|
+
}
|
|
1529
|
+
},
|
|
1530
|
+
required: ["txHash"]
|
|
1531
|
+
}
|
|
1532
|
+
}
|
|
1533
|
+
};
|
|
1534
|
+
async function executeTonBridgeTool(toolName, args, config) {
|
|
1535
|
+
if (config.demoMode) {
|
|
1536
|
+
return executeTonBridgeToolDemo(toolName, args);
|
|
1537
|
+
}
|
|
1538
|
+
if (config.tonMcpEndpoint) {
|
|
1539
|
+
return proxyToTonMcp(toolName, args, config.tonMcpEndpoint);
|
|
1540
|
+
}
|
|
1541
|
+
if (config.tonApiKey) {
|
|
1542
|
+
return executeTonBridgeToolDirect(toolName, args, config.tonApiKey);
|
|
1543
|
+
}
|
|
1544
|
+
return {
|
|
1545
|
+
content: [
|
|
1546
|
+
{
|
|
1547
|
+
type: "text",
|
|
1548
|
+
text: `Error: TON MCP bridge not configured. Set tonMcpEndpoint or tonApiKey.`
|
|
1549
|
+
}
|
|
1550
|
+
],
|
|
1551
|
+
isError: true
|
|
1552
|
+
};
|
|
1553
|
+
}
|
|
1554
|
+
function executeTonBridgeToolDemo(toolName, args) {
|
|
1555
|
+
const responses = {
|
|
1556
|
+
"ton/getBalance": `[DEMO] TON Balance for ${args.address ?? "unknown"}:
|
|
1557
|
+
- TON: 5.25
|
|
1558
|
+
- USDT0: 100.00`,
|
|
1559
|
+
"ton/transfer": `[DEMO] Transfer sent:
|
|
1560
|
+
- To: ${args.to ?? "unknown"}
|
|
1561
|
+
- Amount: ${args.amount ?? "0"} TON
|
|
1562
|
+
- TX: demo-ton-tx-hash-${Date.now().toString(36)}`,
|
|
1563
|
+
"ton/getJettonBalance": `[DEMO] Jetton Balance:
|
|
1564
|
+
- Address: ${args.address ?? "unknown"}
|
|
1565
|
+
- Jetton: ${args.jettonMaster ?? "unknown"}
|
|
1566
|
+
- Balance: 50.00`,
|
|
1567
|
+
"ton/swapJettons": `[DEMO] Swap quote received:
|
|
1568
|
+
- From: ${args.from ?? "unknown"}
|
|
1569
|
+
- To: ${args.to ?? "unknown"}
|
|
1570
|
+
- Amount: ${args.amount ?? "0"}
|
|
1571
|
+
- Transaction: {"validUntil":${Math.floor(Date.now() / 1e3) + 300},"messages":[{"address":"EQDemo...","amount":"${args.amount ?? "0"}","payload":"base64..."}]}`,
|
|
1572
|
+
"ton/getTransactionStatus": `[DEMO] Transaction Status:
|
|
1573
|
+
- Hash: ${args.txHash ?? "unknown"}
|
|
1574
|
+
- Status: Confirmed
|
|
1575
|
+
- Block: 12345678`
|
|
1576
|
+
};
|
|
1577
|
+
return {
|
|
1578
|
+
content: [
|
|
1579
|
+
{
|
|
1580
|
+
type: "text",
|
|
1581
|
+
text: responses[toolName] ?? `[DEMO] Unknown TON tool: ${toolName}`
|
|
1582
|
+
}
|
|
1583
|
+
]
|
|
1584
|
+
};
|
|
1585
|
+
}
|
|
1586
|
+
async function proxyToTonMcp(toolName, args, endpoint) {
|
|
1587
|
+
try {
|
|
1588
|
+
const response = await fetch(endpoint, {
|
|
1589
|
+
method: "POST",
|
|
1590
|
+
headers: { "Content-Type": "application/json" },
|
|
1591
|
+
body: JSON.stringify({
|
|
1592
|
+
jsonrpc: "2.0",
|
|
1593
|
+
id: 1,
|
|
1594
|
+
method: "tools/call",
|
|
1595
|
+
params: { name: toolName, arguments: args }
|
|
1596
|
+
})
|
|
1597
|
+
});
|
|
1598
|
+
if (!response.ok) {
|
|
1599
|
+
throw new Error(`TON MCP server returned ${response.status}`);
|
|
1600
|
+
}
|
|
1601
|
+
const result = await response.json();
|
|
1602
|
+
if (result.error) {
|
|
1603
|
+
throw new Error(result.error.message);
|
|
1604
|
+
}
|
|
1605
|
+
return result.result ?? { content: [{ type: "text", text: "No result" }] };
|
|
1606
|
+
} catch (error) {
|
|
1607
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1608
|
+
return {
|
|
1609
|
+
content: [{ type: "text", text: `Error proxying to @ton/mcp: ${message}` }],
|
|
1610
|
+
isError: true
|
|
1611
|
+
};
|
|
1612
|
+
}
|
|
1613
|
+
}
|
|
1614
|
+
async function executeTonBridgeToolDirect(toolName, args, apiKey) {
|
|
1615
|
+
const baseUrl = "https://toncenter.com/api/v2";
|
|
1616
|
+
try {
|
|
1617
|
+
switch (toolName) {
|
|
1618
|
+
case "ton/getBalance": {
|
|
1619
|
+
const response = await fetch(
|
|
1620
|
+
`${baseUrl}/getAddressBalance?address=${encodeURIComponent(String(args.address))}&api_key=${apiKey}`
|
|
1621
|
+
);
|
|
1622
|
+
const data = await response.json();
|
|
1623
|
+
const balanceNano = BigInt(data.result);
|
|
1624
|
+
const balanceTon = Number(balanceNano) / 1e9;
|
|
1625
|
+
return {
|
|
1626
|
+
content: [{ type: "text", text: `TON Balance: ${balanceTon.toFixed(4)} TON` }]
|
|
1627
|
+
};
|
|
1628
|
+
}
|
|
1629
|
+
case "ton/getTransactionStatus": {
|
|
1630
|
+
const response = await fetch(
|
|
1631
|
+
`${baseUrl}/getTransactions?hash=${encodeURIComponent(String(args.txHash))}&limit=1&api_key=${apiKey}`
|
|
1632
|
+
);
|
|
1633
|
+
const data = await response.json();
|
|
1634
|
+
if (data.result.length === 0) {
|
|
1635
|
+
return {
|
|
1636
|
+
content: [{ type: "text", text: "Transaction not found" }]
|
|
1637
|
+
};
|
|
1638
|
+
}
|
|
1639
|
+
return {
|
|
1640
|
+
content: [
|
|
1641
|
+
{
|
|
1642
|
+
type: "text",
|
|
1643
|
+
text: `Transaction found:
|
|
1644
|
+
${JSON.stringify(data.result[0], null, 2)}`
|
|
1645
|
+
}
|
|
1646
|
+
]
|
|
1647
|
+
};
|
|
1648
|
+
}
|
|
1649
|
+
default:
|
|
1650
|
+
return {
|
|
1651
|
+
content: [
|
|
1652
|
+
{
|
|
1653
|
+
type: "text",
|
|
1654
|
+
text: `Direct execution of ${toolName} is not supported. Configure tonMcpEndpoint to proxy to @ton/mcp.`
|
|
1655
|
+
}
|
|
1656
|
+
],
|
|
1657
|
+
isError: true
|
|
1658
|
+
};
|
|
1659
|
+
}
|
|
1660
|
+
} catch (error) {
|
|
1661
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1662
|
+
return {
|
|
1663
|
+
content: [{ type: "text", text: `Error executing TON API call: ${message}` }],
|
|
1664
|
+
isError: true
|
|
1665
|
+
};
|
|
1666
|
+
}
|
|
1667
|
+
}
|
|
1668
|
+
|
|
1669
|
+
// src/tools/unified.ts
|
|
1670
|
+
var import_zod12 = require("zod");
|
|
1671
|
+
var import_wdk_protocol2 = require("@t402/wdk-protocol");
|
|
1672
|
+
var smartPayInputSchema = import_zod12.z.object({
|
|
1673
|
+
url: import_zod12.z.string().url().describe("URL of the 402-protected resource"),
|
|
1674
|
+
maxBridgeFee: import_zod12.z.string().regex(/^\d+(\.\d+)?$/).optional().describe("Maximum acceptable bridge fee in native token (optional)"),
|
|
1675
|
+
preferredNetwork: import_zod12.z.string().optional().describe("Preferred network for payment (optional)")
|
|
1676
|
+
});
|
|
1677
|
+
var paymentPlanInputSchema = import_zod12.z.object({
|
|
1678
|
+
paymentRequired: import_zod12.z.object({
|
|
1679
|
+
scheme: import_zod12.z.string().optional(),
|
|
1680
|
+
network: import_zod12.z.string().optional(),
|
|
1681
|
+
maxAmountRequired: import_zod12.z.string().optional(),
|
|
1682
|
+
resource: import_zod12.z.string().optional(),
|
|
1683
|
+
description: import_zod12.z.string().optional(),
|
|
1684
|
+
payTo: import_zod12.z.string().optional(),
|
|
1685
|
+
maxDeadline: import_zod12.z.number().optional()
|
|
1686
|
+
}).passthrough().describe("The 402 PaymentRequired response")
|
|
1687
|
+
});
|
|
1688
|
+
var UNIFIED_TOOL_DEFINITIONS = {
|
|
1689
|
+
"t402/smartPay": {
|
|
1690
|
+
name: "t402/smartPay",
|
|
1691
|
+
description: "Intelligent payment that automatically checks balance, bridges if needed, and pays. Handles the entire payment flow for 402-protected resources.",
|
|
1692
|
+
inputSchema: {
|
|
1693
|
+
type: "object",
|
|
1694
|
+
properties: {
|
|
1695
|
+
url: { type: "string", description: "URL of the 402-protected resource" },
|
|
1696
|
+
maxBridgeFee: {
|
|
1697
|
+
type: "string",
|
|
1698
|
+
description: "Maximum acceptable bridge fee in native token (optional)"
|
|
1699
|
+
},
|
|
1700
|
+
preferredNetwork: {
|
|
1701
|
+
type: "string",
|
|
1702
|
+
description: "Preferred network for payment (optional)"
|
|
1703
|
+
}
|
|
1704
|
+
},
|
|
1705
|
+
required: ["url"]
|
|
1706
|
+
}
|
|
1707
|
+
},
|
|
1708
|
+
"t402/paymentPlan": {
|
|
1709
|
+
name: "t402/paymentPlan",
|
|
1710
|
+
description: "Analyze a 402 response and create an optimal payment plan considering balances across all chains. Returns recommended network, bridge requirements, and balance overview.",
|
|
1711
|
+
inputSchema: {
|
|
1712
|
+
type: "object",
|
|
1713
|
+
properties: {
|
|
1714
|
+
paymentRequired: {
|
|
1715
|
+
type: "object",
|
|
1716
|
+
description: "The 402 PaymentRequired response"
|
|
1717
|
+
}
|
|
1718
|
+
},
|
|
1719
|
+
required: ["paymentRequired"]
|
|
1720
|
+
}
|
|
1721
|
+
}
|
|
1722
|
+
};
|
|
1723
|
+
async function executeSmartPay(input, wdk) {
|
|
1724
|
+
const steps = [];
|
|
1725
|
+
const chains6 = input.preferredNetwork ? [input.preferredNetwork] : ["ethereum", "arbitrum", "base"];
|
|
1726
|
+
steps.push({
|
|
1727
|
+
action: "check_balance",
|
|
1728
|
+
status: "success",
|
|
1729
|
+
detail: `Checking balances on ${chains6.join(", ")}`
|
|
1730
|
+
});
|
|
1731
|
+
const protocol = await import_wdk_protocol2.T402Protocol.create(wdk, { chains: chains6 });
|
|
1732
|
+
steps.push({
|
|
1733
|
+
action: "fetch",
|
|
1734
|
+
status: "success",
|
|
1735
|
+
detail: `Fetching ${input.url}`
|
|
1736
|
+
});
|
|
1737
|
+
const { response, receipt } = await protocol.fetch(input.url);
|
|
1738
|
+
if (receipt) {
|
|
1739
|
+
steps.push({
|
|
1740
|
+
action: "pay",
|
|
1741
|
+
status: "success",
|
|
1742
|
+
detail: `Payment made: ${receipt.amount} on ${receipt.network}`
|
|
1743
|
+
});
|
|
1744
|
+
}
|
|
1745
|
+
const contentType = response.headers.get("content-type") ?? void 0;
|
|
1746
|
+
let body = "";
|
|
1747
|
+
try {
|
|
1748
|
+
body = await response.text();
|
|
1749
|
+
if (body.length > 1e4) {
|
|
1750
|
+
body = body.slice(0, 1e4) + "\n... (truncated)";
|
|
1751
|
+
}
|
|
1752
|
+
} catch {
|
|
1753
|
+
body = "[Could not read response body]";
|
|
1754
|
+
}
|
|
1755
|
+
return {
|
|
1756
|
+
success: response.ok,
|
|
1757
|
+
statusCode: response.status,
|
|
1758
|
+
body,
|
|
1759
|
+
contentType,
|
|
1760
|
+
steps,
|
|
1761
|
+
payment: receipt ? {
|
|
1762
|
+
network: receipt.network,
|
|
1763
|
+
scheme: receipt.scheme,
|
|
1764
|
+
amount: receipt.amount,
|
|
1765
|
+
payTo: receipt.payTo
|
|
1766
|
+
} : void 0
|
|
1767
|
+
};
|
|
1768
|
+
}
|
|
1769
|
+
function executeSmartPayDemo(input) {
|
|
1770
|
+
const network = input.preferredNetwork ?? "arbitrum";
|
|
1771
|
+
return {
|
|
1772
|
+
success: true,
|
|
1773
|
+
statusCode: 200,
|
|
1774
|
+
body: `[Demo] Premium content from ${input.url}
|
|
1775
|
+
|
|
1776
|
+
This is simulated content returned after smart payment.`,
|
|
1777
|
+
contentType: "text/plain",
|
|
1778
|
+
steps: [
|
|
1779
|
+
{ action: "check_balance", status: "success", detail: `Checked balances on ${network}` },
|
|
1780
|
+
{ action: "check_price", status: "success", detail: "Resource costs 1.00 USDT0" },
|
|
1781
|
+
{ action: "pay", status: "success", detail: `Paid 1000000 USDT0 on eip155:42161` },
|
|
1782
|
+
{ action: "fetch", status: "success", detail: `Fetched ${input.url}` }
|
|
1783
|
+
],
|
|
1784
|
+
payment: {
|
|
1785
|
+
network: "eip155:42161",
|
|
1786
|
+
scheme: "exact",
|
|
1787
|
+
amount: "1000000",
|
|
1788
|
+
payTo: "0xC88f67e776f16DcFBf42e6bDda1B82604448899B"
|
|
1789
|
+
}
|
|
1790
|
+
};
|
|
1791
|
+
}
|
|
1792
|
+
async function executePaymentPlan(input, wdk) {
|
|
1793
|
+
const targetNetwork = input.paymentRequired.network;
|
|
1794
|
+
const requiredAmount = input.paymentRequired.maxAmountRequired;
|
|
1795
|
+
const aggregated = await wdk.getAggregatedBalances();
|
|
1796
|
+
const balances = aggregated.chains.map((chain) => {
|
|
1797
|
+
const usdt0 = chain.tokens.find((t) => t.symbol === "USDT0");
|
|
1798
|
+
const usdc = chain.tokens.find((t) => t.symbol === "USDC");
|
|
1799
|
+
return {
|
|
1800
|
+
chain: chain.chain,
|
|
1801
|
+
usdt0: usdt0?.formatted ?? "0",
|
|
1802
|
+
usdc: usdc?.formatted ?? "0"
|
|
1803
|
+
};
|
|
1804
|
+
});
|
|
1805
|
+
const requiredBigint = requiredAmount ? BigInt(requiredAmount) : 0n;
|
|
1806
|
+
const bestChain = await wdk.findBestChainForPayment(requiredBigint);
|
|
1807
|
+
if (bestChain) {
|
|
1808
|
+
const needsBridge = targetNetwork ? !bestChain.chain.includes(targetNetwork) : false;
|
|
1809
|
+
return {
|
|
1810
|
+
viable: true,
|
|
1811
|
+
recommendedNetwork: bestChain.chain,
|
|
1812
|
+
availableBalance: bestChain.balance.toString(),
|
|
1813
|
+
bridgeRequired: needsBridge,
|
|
1814
|
+
bridgeDetails: needsBridge ? {
|
|
1815
|
+
fromChain: bestChain.chain,
|
|
1816
|
+
toChain: targetNetwork ?? bestChain.chain,
|
|
1817
|
+
amount: requiredAmount ?? "0",
|
|
1818
|
+
estimatedFee: "0.001"
|
|
1819
|
+
} : void 0,
|
|
1820
|
+
balances
|
|
1821
|
+
};
|
|
1822
|
+
}
|
|
1823
|
+
return {
|
|
1824
|
+
viable: false,
|
|
1825
|
+
bridgeRequired: false,
|
|
1826
|
+
balances,
|
|
1827
|
+
reason: "Insufficient balance across all chains"
|
|
1828
|
+
};
|
|
1829
|
+
}
|
|
1830
|
+
function executePaymentPlanDemo(_input) {
|
|
1831
|
+
return {
|
|
1832
|
+
viable: true,
|
|
1833
|
+
recommendedNetwork: "arbitrum",
|
|
1834
|
+
availableBalance: "500000000",
|
|
1835
|
+
bridgeRequired: false,
|
|
1836
|
+
balances: [
|
|
1837
|
+
{ chain: "ethereum", usdt0: "100.00", usdc: "250.00" },
|
|
1838
|
+
{ chain: "arbitrum", usdt0: "500.00", usdc: "0" },
|
|
1839
|
+
{ chain: "base", usdt0: "50.00", usdc: "100.00" }
|
|
1840
|
+
]
|
|
1841
|
+
};
|
|
1842
|
+
}
|
|
1843
|
+
function formatSmartPayResult(result) {
|
|
1844
|
+
const lines = ["## SmartPay Result", ""];
|
|
1845
|
+
if (result.success) {
|
|
1846
|
+
lines.push(`**Status:** Success (${result.statusCode})`);
|
|
1847
|
+
} else {
|
|
1848
|
+
lines.push(`**Status:** Failed (${result.statusCode})`);
|
|
1849
|
+
}
|
|
1850
|
+
if (result.steps.length > 0) {
|
|
1851
|
+
lines.push("");
|
|
1852
|
+
lines.push("### Steps");
|
|
1853
|
+
for (const step of result.steps) {
|
|
1854
|
+
const icon = step.status === "success" ? "[OK]" : step.status === "skipped" ? "[SKIP]" : "[FAIL]";
|
|
1855
|
+
lines.push(`- ${icon} **${step.action}**: ${step.detail}`);
|
|
1856
|
+
}
|
|
1857
|
+
}
|
|
1858
|
+
if (result.payment) {
|
|
1859
|
+
lines.push("");
|
|
1860
|
+
lines.push("### Payment Details");
|
|
1861
|
+
lines.push(`- **Network:** ${result.payment.network}`);
|
|
1862
|
+
lines.push(`- **Scheme:** ${result.payment.scheme}`);
|
|
1863
|
+
lines.push(`- **Amount:** ${result.payment.amount}`);
|
|
1864
|
+
lines.push(`- **Pay To:** \`${result.payment.payTo}\``);
|
|
1865
|
+
}
|
|
1866
|
+
if (result.error) {
|
|
1867
|
+
lines.push("");
|
|
1868
|
+
lines.push(`**Error:** ${result.error}`);
|
|
1869
|
+
}
|
|
1870
|
+
if (result.body) {
|
|
1871
|
+
lines.push("");
|
|
1872
|
+
lines.push("### Response Content");
|
|
1873
|
+
if (result.contentType) {
|
|
1874
|
+
lines.push(`_Content-Type: ${result.contentType}_`);
|
|
1875
|
+
}
|
|
1876
|
+
lines.push("");
|
|
1877
|
+
lines.push("```");
|
|
1878
|
+
lines.push(result.body);
|
|
1879
|
+
lines.push("```");
|
|
1880
|
+
}
|
|
1881
|
+
return lines.join("\n");
|
|
1882
|
+
}
|
|
1883
|
+
function formatPaymentPlanResult(result) {
|
|
1884
|
+
const lines = ["## Payment Plan", ""];
|
|
1885
|
+
if (result.viable) {
|
|
1886
|
+
lines.push(`**Viable:** Yes`);
|
|
1887
|
+
if (result.recommendedNetwork) {
|
|
1888
|
+
lines.push(`**Recommended Network:** ${result.recommendedNetwork}`);
|
|
1889
|
+
}
|
|
1890
|
+
if (result.availableBalance) {
|
|
1891
|
+
lines.push(`**Available Balance:** ${result.availableBalance}`);
|
|
1892
|
+
}
|
|
1893
|
+
} else {
|
|
1894
|
+
lines.push(`**Viable:** No`);
|
|
1895
|
+
if (result.reason) {
|
|
1896
|
+
lines.push(`**Reason:** ${result.reason}`);
|
|
1897
|
+
}
|
|
1898
|
+
}
|
|
1899
|
+
if (result.bridgeRequired && result.bridgeDetails) {
|
|
1900
|
+
lines.push("");
|
|
1901
|
+
lines.push("### Bridge Required");
|
|
1902
|
+
lines.push(`- **From:** ${result.bridgeDetails.fromChain}`);
|
|
1903
|
+
lines.push(`- **To:** ${result.bridgeDetails.toChain}`);
|
|
1904
|
+
lines.push(`- **Amount:** ${result.bridgeDetails.amount}`);
|
|
1905
|
+
lines.push(`- **Estimated Fee:** ${result.bridgeDetails.estimatedFee}`);
|
|
1906
|
+
}
|
|
1907
|
+
if (result.balances.length > 0) {
|
|
1908
|
+
lines.push("");
|
|
1909
|
+
lines.push("### Chain Balances");
|
|
1910
|
+
lines.push("| Chain | USDT0 | USDC |");
|
|
1911
|
+
lines.push("|-------|-------|------|");
|
|
1912
|
+
for (const b of result.balances) {
|
|
1913
|
+
lines.push(`| ${b.chain} | ${b.usdt0} | ${b.usdc} |`);
|
|
1914
|
+
}
|
|
1915
|
+
}
|
|
1916
|
+
return lines.join("\n");
|
|
1917
|
+
}
|
|
1918
|
+
|
|
1154
1919
|
// src/tools/index.ts
|
|
1155
1920
|
var TOOL_DEFINITIONS = {
|
|
1156
1921
|
"t402/getBalance": {
|
|
@@ -1351,12 +2116,119 @@ var TOOL_DEFINITIONS = {
|
|
|
1351
2116
|
}
|
|
1352
2117
|
}
|
|
1353
2118
|
};
|
|
2119
|
+
var WDK_TOOL_DEFINITIONS = {
|
|
2120
|
+
"wdk/getWallet": {
|
|
2121
|
+
name: "wdk/getWallet",
|
|
2122
|
+
description: "Get wallet information from the configured WDK wallet. Returns EVM address and supported chains. No parameters needed.",
|
|
2123
|
+
inputSchema: {
|
|
2124
|
+
type: "object",
|
|
2125
|
+
properties: {},
|
|
2126
|
+
required: []
|
|
2127
|
+
}
|
|
2128
|
+
},
|
|
2129
|
+
"wdk/getBalances": {
|
|
2130
|
+
name: "wdk/getBalances",
|
|
2131
|
+
description: "Get multi-chain token balances from the WDK wallet. Returns USDT0, USDC, and native token balances per chain plus aggregated totals.",
|
|
2132
|
+
inputSchema: {
|
|
2133
|
+
type: "object",
|
|
2134
|
+
properties: {
|
|
2135
|
+
chains: {
|
|
2136
|
+
type: "array",
|
|
2137
|
+
items: { type: "string" },
|
|
2138
|
+
description: 'Optional list of chains to check (e.g., ["ethereum", "arbitrum"]). If not provided, checks all configured chains.'
|
|
2139
|
+
}
|
|
2140
|
+
},
|
|
2141
|
+
required: []
|
|
2142
|
+
}
|
|
2143
|
+
},
|
|
2144
|
+
"wdk/transfer": {
|
|
2145
|
+
name: "wdk/transfer",
|
|
2146
|
+
description: "Send stablecoins (USDC, USDT, USDT0) from the WDK wallet to a recipient address on a specific chain.",
|
|
2147
|
+
inputSchema: {
|
|
2148
|
+
type: "object",
|
|
2149
|
+
properties: {
|
|
2150
|
+
to: {
|
|
2151
|
+
type: "string",
|
|
2152
|
+
description: "Recipient address"
|
|
2153
|
+
},
|
|
2154
|
+
amount: {
|
|
2155
|
+
type: "string",
|
|
2156
|
+
pattern: "^\\d+(\\.\\d+)?$",
|
|
2157
|
+
description: "Amount to send (e.g., '10.50')"
|
|
2158
|
+
},
|
|
2159
|
+
token: {
|
|
2160
|
+
type: "string",
|
|
2161
|
+
enum: ["USDC", "USDT", "USDT0"],
|
|
2162
|
+
description: "Token to transfer"
|
|
2163
|
+
},
|
|
2164
|
+
chain: {
|
|
2165
|
+
type: "string",
|
|
2166
|
+
description: 'Chain to execute transfer on (e.g., "ethereum", "arbitrum")'
|
|
2167
|
+
}
|
|
2168
|
+
},
|
|
2169
|
+
required: ["to", "amount", "token", "chain"]
|
|
2170
|
+
}
|
|
2171
|
+
},
|
|
2172
|
+
"wdk/swap": {
|
|
2173
|
+
name: "wdk/swap",
|
|
2174
|
+
description: "Swap tokens using the WDK Velora protocol. Supports swapping between stablecoins and native tokens.",
|
|
2175
|
+
inputSchema: {
|
|
2176
|
+
type: "object",
|
|
2177
|
+
properties: {
|
|
2178
|
+
fromToken: {
|
|
2179
|
+
type: "string",
|
|
2180
|
+
description: 'Token to swap from (e.g., "ETH", "USDC")'
|
|
2181
|
+
},
|
|
2182
|
+
toToken: {
|
|
2183
|
+
type: "string",
|
|
2184
|
+
description: 'Token to swap to (e.g., "USDT0", "USDC")'
|
|
2185
|
+
},
|
|
2186
|
+
amount: {
|
|
2187
|
+
type: "string",
|
|
2188
|
+
pattern: "^\\d+(\\.\\d+)?$",
|
|
2189
|
+
description: "Amount to swap (e.g., '1.0')"
|
|
2190
|
+
},
|
|
2191
|
+
chain: {
|
|
2192
|
+
type: "string",
|
|
2193
|
+
description: 'Chain to execute swap on (e.g., "ethereum", "arbitrum")'
|
|
2194
|
+
}
|
|
2195
|
+
},
|
|
2196
|
+
required: ["fromToken", "toToken", "amount", "chain"]
|
|
2197
|
+
}
|
|
2198
|
+
},
|
|
2199
|
+
"t402/autoPay": {
|
|
2200
|
+
name: "t402/autoPay",
|
|
2201
|
+
description: "Smart payment orchestrator. Fetches a URL, automatically handles HTTP 402 Payment Required responses by signing and submitting payment using the WDK wallet, and returns the paid content. The killer tool for AI agents.",
|
|
2202
|
+
inputSchema: {
|
|
2203
|
+
type: "object",
|
|
2204
|
+
properties: {
|
|
2205
|
+
url: {
|
|
2206
|
+
type: "string",
|
|
2207
|
+
description: "URL to fetch (may return 402 Payment Required)"
|
|
2208
|
+
},
|
|
2209
|
+
maxAmount: {
|
|
2210
|
+
type: "string",
|
|
2211
|
+
pattern: "^\\d+(\\.\\d+)?$",
|
|
2212
|
+
description: 'Maximum amount willing to pay (e.g., "10.00"). If not set, pays any amount.'
|
|
2213
|
+
},
|
|
2214
|
+
preferredChain: {
|
|
2215
|
+
type: "string",
|
|
2216
|
+
description: 'Preferred chain for payment (e.g., "arbitrum"). If not specified, uses first available.'
|
|
2217
|
+
}
|
|
2218
|
+
},
|
|
2219
|
+
required: ["url"]
|
|
2220
|
+
}
|
|
2221
|
+
}
|
|
2222
|
+
};
|
|
1354
2223
|
|
|
1355
2224
|
// src/server/t402Server.ts
|
|
1356
2225
|
var T402McpServer = class {
|
|
1357
2226
|
constructor(config = {}) {
|
|
1358
2227
|
__publicField(this, "server");
|
|
1359
2228
|
__publicField(this, "config");
|
|
2229
|
+
__publicField(this, "wdk", null);
|
|
2230
|
+
/** TON MCP bridge configuration */
|
|
2231
|
+
__publicField(this, "tonBridgeConfig", null);
|
|
1360
2232
|
this.config = config;
|
|
1361
2233
|
this.server = new import_server.Server(
|
|
1362
2234
|
{
|
|
@@ -1371,13 +2243,55 @@ var T402McpServer = class {
|
|
|
1371
2243
|
);
|
|
1372
2244
|
this.setupHandlers();
|
|
1373
2245
|
}
|
|
2246
|
+
/**
|
|
2247
|
+
* Initialize the WDK instance from seed phrase
|
|
2248
|
+
*/
|
|
2249
|
+
async initWdk() {
|
|
2250
|
+
if (!this.config.seedPhrase) return;
|
|
2251
|
+
try {
|
|
2252
|
+
const { T402WDK } = await import("@t402/wdk");
|
|
2253
|
+
const rpcUrls = {};
|
|
2254
|
+
if (this.config.rpcUrls) {
|
|
2255
|
+
for (const [network, url] of Object.entries(this.config.rpcUrls)) {
|
|
2256
|
+
if (url) rpcUrls[network] = url;
|
|
2257
|
+
}
|
|
2258
|
+
}
|
|
2259
|
+
this.wdk = new T402WDK(this.config.seedPhrase, rpcUrls);
|
|
2260
|
+
} catch {
|
|
2261
|
+
console.error("Warning: Failed to initialize WDK. WDK tools will not be available.");
|
|
2262
|
+
}
|
|
2263
|
+
}
|
|
2264
|
+
/**
|
|
2265
|
+
* Register TON bridge tools
|
|
2266
|
+
*
|
|
2267
|
+
* Enables AI agents to use @ton/mcp tools through the t402 MCP server.
|
|
2268
|
+
*/
|
|
2269
|
+
registerTonBridge(config) {
|
|
2270
|
+
this.tonBridgeConfig = config;
|
|
2271
|
+
}
|
|
2272
|
+
/**
|
|
2273
|
+
* Get all tool definitions (base + WDK if configured + unified if enabled + TON bridge if registered)
|
|
2274
|
+
*/
|
|
2275
|
+
getToolDefinitions() {
|
|
2276
|
+
const tools = { ...TOOL_DEFINITIONS };
|
|
2277
|
+
if (this.wdk || this.config.demoMode) {
|
|
2278
|
+
Object.assign(tools, WDK_TOOL_DEFINITIONS);
|
|
2279
|
+
}
|
|
2280
|
+
if (this.config.unifiedMode && (this.wdk || this.config.demoMode)) {
|
|
2281
|
+
Object.assign(tools, UNIFIED_TOOL_DEFINITIONS);
|
|
2282
|
+
}
|
|
2283
|
+
if (this.tonBridgeConfig) {
|
|
2284
|
+
Object.assign(tools, TON_BRIDGE_TOOLS);
|
|
2285
|
+
}
|
|
2286
|
+
return tools;
|
|
2287
|
+
}
|
|
1374
2288
|
/**
|
|
1375
2289
|
* Set up MCP request handlers
|
|
1376
2290
|
*/
|
|
1377
2291
|
setupHandlers() {
|
|
1378
2292
|
this.server.setRequestHandler(import_types.ListToolsRequestSchema, async () => {
|
|
1379
2293
|
return {
|
|
1380
|
-
tools: Object.values(
|
|
2294
|
+
tools: Object.values(this.getToolDefinitions())
|
|
1381
2295
|
};
|
|
1382
2296
|
});
|
|
1383
2297
|
this.server.setRequestHandler(import_types.CallToolRequestSchema, async (request) => {
|
|
@@ -1396,6 +2310,29 @@ var T402McpServer = class {
|
|
|
1396
2310
|
return await this.handleGetBridgeFee(args);
|
|
1397
2311
|
case "t402/bridge":
|
|
1398
2312
|
return await this.handleBridge(args);
|
|
2313
|
+
// WDK tools
|
|
2314
|
+
case "wdk/getWallet":
|
|
2315
|
+
return await this.handleWdkGetWallet(args);
|
|
2316
|
+
case "wdk/getBalances":
|
|
2317
|
+
return await this.handleWdkGetBalances(args);
|
|
2318
|
+
case "wdk/transfer":
|
|
2319
|
+
return await this.handleWdkTransfer(args);
|
|
2320
|
+
case "wdk/swap":
|
|
2321
|
+
return await this.handleWdkSwap(args);
|
|
2322
|
+
case "t402/autoPay":
|
|
2323
|
+
return await this.handleAutoPay(args);
|
|
2324
|
+
// Unified tools
|
|
2325
|
+
case "t402/smartPay":
|
|
2326
|
+
return await this.handleSmartPay(args);
|
|
2327
|
+
case "t402/paymentPlan":
|
|
2328
|
+
return await this.handlePaymentPlan(args);
|
|
2329
|
+
// TON bridge tools
|
|
2330
|
+
case "ton/getBalance":
|
|
2331
|
+
case "ton/transfer":
|
|
2332
|
+
case "ton/getJettonBalance":
|
|
2333
|
+
case "ton/swapJettons":
|
|
2334
|
+
case "ton/getTransactionStatus":
|
|
2335
|
+
return await this.handleTonBridgeTool(name, args);
|
|
1399
2336
|
default:
|
|
1400
2337
|
throw new Error(`Unknown tool: ${name}`);
|
|
1401
2338
|
}
|
|
@@ -1542,10 +2479,93 @@ var T402McpServer = class {
|
|
|
1542
2479
|
]
|
|
1543
2480
|
};
|
|
1544
2481
|
}
|
|
2482
|
+
// ---- WDK Tool Handlers ----
|
|
2483
|
+
/**
|
|
2484
|
+
* Handle wdk/getWallet
|
|
2485
|
+
*/
|
|
2486
|
+
async handleWdkGetWallet(args) {
|
|
2487
|
+
wdkGetWalletInputSchema.parse(args);
|
|
2488
|
+
const result = this.config.demoMode || !this.wdk ? executeWdkGetWalletDemo() : await executeWdkGetWallet({}, this.wdk);
|
|
2489
|
+
return {
|
|
2490
|
+
content: [{ type: "text", text: formatWdkWalletResult(result) }]
|
|
2491
|
+
};
|
|
2492
|
+
}
|
|
2493
|
+
/**
|
|
2494
|
+
* Handle wdk/getBalances
|
|
2495
|
+
*/
|
|
2496
|
+
async handleWdkGetBalances(args) {
|
|
2497
|
+
const input = wdkGetBalancesInputSchema.parse(args);
|
|
2498
|
+
const result = this.config.demoMode || !this.wdk ? executeWdkGetBalancesDemo() : await executeWdkGetBalances(input, this.wdk);
|
|
2499
|
+
return {
|
|
2500
|
+
content: [{ type: "text", text: formatWdkBalancesResult(result) }]
|
|
2501
|
+
};
|
|
2502
|
+
}
|
|
2503
|
+
/**
|
|
2504
|
+
* Handle wdk/transfer
|
|
2505
|
+
*/
|
|
2506
|
+
async handleWdkTransfer(args) {
|
|
2507
|
+
const input = wdkTransferInputSchema.parse(args);
|
|
2508
|
+
const result = this.config.demoMode || !this.wdk ? executeWdkTransferDemo(input) : await executeWdkTransfer(input, this.wdk);
|
|
2509
|
+
return {
|
|
2510
|
+
content: [{ type: "text", text: formatWdkTransferResult(result) }]
|
|
2511
|
+
};
|
|
2512
|
+
}
|
|
2513
|
+
/**
|
|
2514
|
+
* Handle wdk/swap
|
|
2515
|
+
*/
|
|
2516
|
+
async handleWdkSwap(args) {
|
|
2517
|
+
const input = wdkSwapInputSchema.parse(args);
|
|
2518
|
+
const result = this.config.demoMode || !this.wdk ? executeWdkSwapDemo(input) : await executeWdkSwap(input, this.wdk);
|
|
2519
|
+
return {
|
|
2520
|
+
content: [{ type: "text", text: formatWdkSwapResult(result) }]
|
|
2521
|
+
};
|
|
2522
|
+
}
|
|
2523
|
+
/**
|
|
2524
|
+
* Handle t402/autoPay
|
|
2525
|
+
*/
|
|
2526
|
+
async handleAutoPay(args) {
|
|
2527
|
+
const input = autoPayInputSchema.parse(args);
|
|
2528
|
+
const result = this.config.demoMode || !this.wdk ? executeAutoPayDemo(input) : await executeAutoPay(input, this.wdk);
|
|
2529
|
+
return {
|
|
2530
|
+
content: [{ type: "text", text: formatAutoPayResult(result) }]
|
|
2531
|
+
};
|
|
2532
|
+
}
|
|
2533
|
+
// ---- Unified Tool Handlers ----
|
|
2534
|
+
/**
|
|
2535
|
+
* Handle t402/smartPay
|
|
2536
|
+
*/
|
|
2537
|
+
async handleSmartPay(args) {
|
|
2538
|
+
const input = smartPayInputSchema.parse(args);
|
|
2539
|
+
const result = this.config.demoMode || !this.wdk ? executeSmartPayDemo(input) : await executeSmartPay(input, this.wdk);
|
|
2540
|
+
return {
|
|
2541
|
+
content: [{ type: "text", text: formatSmartPayResult(result) }]
|
|
2542
|
+
};
|
|
2543
|
+
}
|
|
2544
|
+
/**
|
|
2545
|
+
* Handle t402/paymentPlan
|
|
2546
|
+
*/
|
|
2547
|
+
async handlePaymentPlan(args) {
|
|
2548
|
+
const input = paymentPlanInputSchema.parse(args);
|
|
2549
|
+
const result = this.config.demoMode || !this.wdk ? executePaymentPlanDemo(input) : await executePaymentPlan(input, this.wdk);
|
|
2550
|
+
return {
|
|
2551
|
+
content: [{ type: "text", text: formatPaymentPlanResult(result) }]
|
|
2552
|
+
};
|
|
2553
|
+
}
|
|
2554
|
+
// ---- TON Bridge Tool Handler ----
|
|
2555
|
+
/**
|
|
2556
|
+
* Handle TON bridge tool calls
|
|
2557
|
+
*/
|
|
2558
|
+
async handleTonBridgeTool(name, args) {
|
|
2559
|
+
if (!this.tonBridgeConfig) {
|
|
2560
|
+
throw new Error("TON bridge not configured. Call registerTonBridge() to enable TON tools.");
|
|
2561
|
+
}
|
|
2562
|
+
return executeTonBridgeTool(name, args ?? {}, this.tonBridgeConfig);
|
|
2563
|
+
}
|
|
1545
2564
|
/**
|
|
1546
2565
|
* Start the server using stdio transport
|
|
1547
2566
|
*/
|
|
1548
2567
|
async run() {
|
|
2568
|
+
await this.initWdk();
|
|
1549
2569
|
const transport = new import_stdio.StdioServerTransport();
|
|
1550
2570
|
await this.server.connect(transport);
|
|
1551
2571
|
console.error("t402 MCP Server running on stdio");
|
|
@@ -1568,6 +2588,15 @@ function loadConfigFromEnv() {
|
|
|
1568
2588
|
if (process.env.T402_PAYMASTER_URL) {
|
|
1569
2589
|
config.paymasterUrl = process.env.T402_PAYMASTER_URL;
|
|
1570
2590
|
}
|
|
2591
|
+
if (process.env.T402_WDK_SEED_PHRASE) {
|
|
2592
|
+
config.seedPhrase = process.env.T402_WDK_SEED_PHRASE;
|
|
2593
|
+
}
|
|
2594
|
+
if (process.env.T402_WDK_CHAINS) {
|
|
2595
|
+
config.wdkChains = process.env.T402_WDK_CHAINS.split(",").map((c) => c.trim());
|
|
2596
|
+
}
|
|
2597
|
+
if (process.env.T402_UNIFIED_MODE === "true") {
|
|
2598
|
+
config.unifiedMode = true;
|
|
2599
|
+
}
|
|
1571
2600
|
const rpcUrls = {};
|
|
1572
2601
|
const networks = [
|
|
1573
2602
|
"ethereum",
|
|
@@ -1589,6 +2618,12 @@ function loadConfigFromEnv() {
|
|
|
1589
2618
|
if (Object.keys(rpcUrls).length > 0) {
|
|
1590
2619
|
config.rpcUrls = rpcUrls;
|
|
1591
2620
|
}
|
|
2621
|
+
if (process.env.T402_TON_MCP_ENDPOINT) {
|
|
2622
|
+
config.tonMcpEndpoint = process.env.T402_TON_MCP_ENDPOINT;
|
|
2623
|
+
}
|
|
2624
|
+
if (process.env.T402_TON_API_KEY) {
|
|
2625
|
+
config.tonApiKey = process.env.T402_TON_API_KEY;
|
|
2626
|
+
}
|
|
1592
2627
|
return config;
|
|
1593
2628
|
}
|
|
1594
2629
|
// Annotate the CommonJS export names for ESM import in node:
|