@paydprotocol/mcp 0.1.0 → 0.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.
- package/README.md +3 -1
- package/dist/server.js +68 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -14,7 +14,9 @@ claude mcp add payd -- npx -y @paydprotocol/mcp # any MCP client: same command
|
|
|
14
14
|
|
|
15
15
|
Tools: `payd_list_tokens`, `payd_token_info`, `payd_holder_shares`,
|
|
16
16
|
`payd_launch_options`, and the prepare tools `payd_prepare_create_vault`,
|
|
17
|
-
`payd_prepare_launch`, `payd_prepare_bind`, `payd_prepare_claim
|
|
17
|
+
`payd_prepare_launch`, `payd_prepare_bind`, `payd_prepare_claim`, and for keepers
|
|
18
|
+
`payd_pending_work`, `payd_prepare_harvest`, `payd_prepare_buy_basket` — open
|
|
19
|
+
calls that pay their caller (gas back, or a bounty). Every prepare
|
|
18
20
|
tool simulates from `from` first and returns an error instead of calldata when
|
|
19
21
|
the simulation reverts.
|
|
20
22
|
|
package/dist/server.js
CHANGED
|
@@ -644,6 +644,7 @@ async function listTokens(c, o) {
|
|
|
644
644
|
}));
|
|
645
645
|
return { total: all.length, offset: o.offset, tokens: rows };
|
|
646
646
|
}
|
|
647
|
+
var pct2 = (bps) => bps === null ? null : `${bps / 100} %`;
|
|
647
648
|
var HOOK = ["not launched", "collecting", "redirect scheduled", "fees lost"];
|
|
648
649
|
async function tokenInfo(c, vault) {
|
|
649
650
|
const i = await createPayd({ vault: requireAddress("vault", vault), client: c }).info();
|
|
@@ -651,9 +652,13 @@ async function tokenInfo(c, vault) {
|
|
|
651
652
|
...i,
|
|
652
653
|
symbol: untrusted(i.symbol),
|
|
653
654
|
quote: i.quote === ZERO2 ? "native ETH" : i.quote,
|
|
655
|
+
// Spelled out: a model handed 873 next to totalFeeBps 1000 told holders
|
|
656
|
+
// "87.3 % of volume" (assistant eval, 2026-10-04). The real figure is 8.73 %.
|
|
657
|
+
holdersGetPercentOfVolume: pct2(i.rewardsOfVolumeBps),
|
|
658
|
+
creatorGetsPercentOfVolume: pct2(i.creatorOfVolumeBps),
|
|
654
659
|
hookStatus: i.hookStatus === null ? null : { code: i.hookStatus, meaning: HOOK[i.hookStatus] },
|
|
655
660
|
warning: i.hookStatus !== null && i.hookStatus !== 1 ? "Fees are not (or soon will not be) arriving at this launch. Say so; do not quote its percentages as current." : void 0,
|
|
656
|
-
note: "
|
|
661
|
+
note: "holdersGetPercentOfVolume is a share of TRADED VOLUME paid to holders as stock, not a yield; quote it as written, never recompute it from the bps fields. null means unread \u2014 hide it, never show 0."
|
|
657
662
|
};
|
|
658
663
|
}
|
|
659
664
|
async function holderShares(c, vault, holder) {
|
|
@@ -1357,7 +1362,8 @@ var registryAbi2 = parseAbi4([
|
|
|
1357
1362
|
"function listing(address stock) view returns (uint24 poolFee, address feed, bool allowed)",
|
|
1358
1363
|
"function quoteListing(address quote) view returns (uint24 poolFee, uint24 wethFee, uint256 minBuy, bool allowed)",
|
|
1359
1364
|
"function platformBps() view returns (uint256)",
|
|
1360
|
-
"function isVault(address vault) view returns (bool)"
|
|
1365
|
+
"function isVault(address vault) view returns (bool)",
|
|
1366
|
+
"function vaults() view returns (address[])"
|
|
1361
1367
|
]);
|
|
1362
1368
|
var vaultAbi2 = parseAbi4([
|
|
1363
1369
|
"function bind(address token)",
|
|
@@ -1365,6 +1371,10 @@ var vaultAbi2 = parseAbi4([
|
|
|
1365
1371
|
"function token() view returns (address)",
|
|
1366
1372
|
"function QUOTE() view returns (address)"
|
|
1367
1373
|
]);
|
|
1374
|
+
var cycleAbi = parseAbi4([
|
|
1375
|
+
"function harvest() returns (uint256 gross)",
|
|
1376
|
+
"function buyBasket(uint256[] minOuts) returns (uint256 legsBought)"
|
|
1377
|
+
]);
|
|
1368
1378
|
var claimAbi = parseAbi4([
|
|
1369
1379
|
"function claim(address[] stocks, uint256[] cumulative, bytes32[][] proofs) returns (uint256 delivered)"
|
|
1370
1380
|
]);
|
|
@@ -1485,10 +1495,49 @@ async function prepareClaim(c, i) {
|
|
|
1485
1495
|
notes: ["Proofs are valid for the CURRENT root only; a new one is published every epoch. Sign and send now, or prepare again."]
|
|
1486
1496
|
};
|
|
1487
1497
|
}
|
|
1498
|
+
async function registryVault(c, v) {
|
|
1499
|
+
const vault = requireAddress("vault", v);
|
|
1500
|
+
if (!await c.readContract({ address: REGISTRY, abi: registryAbi2, functionName: "isVault", args: [vault] })) {
|
|
1501
|
+
throw new Error(`${vault} is not a vault the Payd registry built`);
|
|
1502
|
+
}
|
|
1503
|
+
return vault;
|
|
1504
|
+
}
|
|
1505
|
+
var PAYS = "An ETH-quoted vault refunds the caller's gas; any other quote pays a bounty in its own currency. A wallet that refuses ETH gets its refund set aside: collect it with the vault's withdraw().";
|
|
1506
|
+
async function prepareHarvest(c, i) {
|
|
1507
|
+
const vault = await registryVault(c, i.vault);
|
|
1508
|
+
return {
|
|
1509
|
+
...await prepare(c, { from: requireAddress("from", i.from), to: vault, abi: cycleAbi, functionName: "harvest", args: [] }),
|
|
1510
|
+
notes: [PAYS]
|
|
1511
|
+
};
|
|
1512
|
+
}
|
|
1513
|
+
async function prepareBuyBasket(c, i) {
|
|
1514
|
+
const vault = await registryVault(c, i.vault);
|
|
1515
|
+
const legs = (await createPayd({ vault, client: c }).info()).basket.length;
|
|
1516
|
+
const minOuts = Array(legs).fill(0n);
|
|
1517
|
+
return {
|
|
1518
|
+
...await prepare(c, { from: requireAddress("from", i.from), to: vault, abi: cycleAbi, functionName: "buyBasket", args: [minOuts] }),
|
|
1519
|
+
notes: [PAYS, "minOuts are zeros: the vault's own oracle floor bounds every leg. Do not loosen it \u2014 you cannot."]
|
|
1520
|
+
};
|
|
1521
|
+
}
|
|
1522
|
+
async function pendingWork(c, i) {
|
|
1523
|
+
const vaults = i.vault ? [await registryVault(c, i.vault)] : await c.readContract({ address: REGISTRY, abi: registryAbi2, functionName: "vaults" });
|
|
1524
|
+
const status = (p) => p.then(() => "ready", (e) => e.message);
|
|
1525
|
+
const rows = await Promise.all(vaults.map(async (vault) => ({
|
|
1526
|
+
vault,
|
|
1527
|
+
harvest: await status(prepareHarvest(c, { vault, from: i.from })),
|
|
1528
|
+
buyBasket: await status(prepareBuyBasket(c, { vault, from: i.from }))
|
|
1529
|
+
})));
|
|
1530
|
+
const ready = rows.filter((r) => r.harvest === "ready" || r.buyBasket === "ready");
|
|
1531
|
+
return {
|
|
1532
|
+
ready,
|
|
1533
|
+
idle: rows.length - ready.length,
|
|
1534
|
+
note: '"ready" means it simulated from `from` just now; another caller may land first, and NothingToDo is then the normal answer. Harvest before buyBasket. distribute() is not offered here: it needs the push tree.'
|
|
1535
|
+
};
|
|
1536
|
+
}
|
|
1488
1537
|
|
|
1489
1538
|
// src/server.ts
|
|
1490
1539
|
var client = makeClient();
|
|
1491
|
-
var server = new McpServer({ name: "payd", version: "0.
|
|
1540
|
+
var server = new McpServer({ name: "payd", version: "0.2.0" });
|
|
1492
1541
|
var run = async (f) => {
|
|
1493
1542
|
try {
|
|
1494
1543
|
return { content: [{ type: "text", text: toJson(await f()) }] };
|
|
@@ -1562,4 +1611,20 @@ server.registerTool("payd_prepare_claim", {
|
|
|
1562
1611
|
inputSchema: { vault: address, holder: address },
|
|
1563
1612
|
annotations: PREPARE_HINTS
|
|
1564
1613
|
}, (a) => run(() => prepareClaim(client, a)));
|
|
1614
|
+
var KEEPER = "Open to anyone and pays its caller (docs/SDK.md \xA79); it gives no say over where the money goes. ";
|
|
1615
|
+
server.registerTool("payd_pending_work", {
|
|
1616
|
+
description: "For keepers: which Payd vaults have a harvest or a buyBasket that would succeed right now, simulated from `from`. Omit vault to scan every launch. " + KEEPER,
|
|
1617
|
+
inputSchema: { from: address, vault: address.optional() },
|
|
1618
|
+
annotations: READ_ONLY
|
|
1619
|
+
}, (a) => run(() => pendingWork(client, a)));
|
|
1620
|
+
server.registerTool("payd_prepare_harvest", {
|
|
1621
|
+
description: "Pull a launch's creator fees out of the Pons escrow and split them. " + KEEPER + PREPARE,
|
|
1622
|
+
inputSchema: { vault: address, from: address },
|
|
1623
|
+
annotations: PREPARE_HINTS
|
|
1624
|
+
}, (a) => run(() => prepareHarvest(client, a)));
|
|
1625
|
+
server.registerTool("payd_prepare_buy_basket", {
|
|
1626
|
+
description: "Buy a launch's whole stock basket for every closed epoch not yet bought; slippage is bounded by the vault's own oracle floor. Harvest first. " + KEEPER + PREPARE,
|
|
1627
|
+
inputSchema: { vault: address, from: address },
|
|
1628
|
+
annotations: PREPARE_HINTS
|
|
1629
|
+
}, (a) => run(() => prepareBuyBasket(client, a)));
|
|
1565
1630
|
await server.connect(new StdioServerTransport());
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@paydprotocol/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Keyless MCP server for Payd on Robinhood Chain: read launches, baskets and holder shares, and prepare unsigned transactions for your own wallet.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|