@moly-mcp/lido 1.0.6 → 1.0.8
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/dist/alerts-ARQAPRIT.js +16 -0
- package/dist/bin.js +278 -15
- package/dist/chunk-6F64RPQQ.js +65 -0
- package/dist/chunk-6UIRFWG4.js +73 -0
- package/dist/chunk-CH4MXPWS.js +41 -0
- package/dist/chunk-CQ6ZSCMZ.js +97 -0
- package/dist/chunk-EKZFGIVK.js +289 -0
- package/dist/chunk-EQYEWCQO.js +233 -0
- package/dist/chunk-GL6TLHSF.js +215 -0
- package/dist/{chunk-PIFEXJ56.js → chunk-P6VFMSPM.js} +19 -2
- package/dist/chunk-PDX44BCA.js +11 -0
- package/dist/chunk-RR74UAKD.js +163 -0
- package/dist/daemon-GU45VVNU.js +214 -0
- package/dist/position-LKVHTEKX.js +10 -0
- package/dist/server/index.js +190 -12
- package/dist/{session-RFQTJ6WZ.js → session-37TYTCEU.js} +350 -36
- package/dist/store-5CEITPDY.js +14 -0
- package/dist/store-SKFUVSK4.js +19 -0
- package/dist/store-WRLUM7OW.js +16 -0
- package/package.json +6 -1
- package/dist/chunk-RE3UIDLV.js +0 -545
package/dist/server/index.js
CHANGED
|
@@ -1,32 +1,64 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
getSettings,
|
|
4
|
+
stakeEth,
|
|
5
|
+
updateSettings
|
|
6
|
+
} from "../chunk-CQ6ZSCMZ.js";
|
|
2
7
|
import {
|
|
3
8
|
castVote,
|
|
4
9
|
claimWithdrawals,
|
|
5
|
-
getBalance,
|
|
6
|
-
getConversionRate,
|
|
7
10
|
getProposal,
|
|
8
11
|
getProposals,
|
|
9
|
-
getRewards,
|
|
10
|
-
getSettings,
|
|
11
12
|
getWithdrawalRequests,
|
|
12
13
|
getWithdrawalStatus,
|
|
13
|
-
requestWithdrawal
|
|
14
|
-
|
|
14
|
+
requestWithdrawal
|
|
15
|
+
} from "../chunk-EQYEWCQO.js";
|
|
16
|
+
import {
|
|
17
|
+
configureAlertChannels,
|
|
18
|
+
listAlerts,
|
|
19
|
+
removeAlertById,
|
|
20
|
+
setAlert
|
|
21
|
+
} from "../chunk-6UIRFWG4.js";
|
|
22
|
+
import "../chunk-6F64RPQQ.js";
|
|
23
|
+
import {
|
|
24
|
+
bridgeToEthereum,
|
|
25
|
+
getBridgeQuote,
|
|
26
|
+
getBridgeStatus,
|
|
27
|
+
getL2Balance,
|
|
28
|
+
getTotalPosition
|
|
29
|
+
} from "../chunk-GL6TLHSF.js";
|
|
30
|
+
import {
|
|
31
|
+
getBalance,
|
|
32
|
+
getConversionRate,
|
|
33
|
+
getRewards,
|
|
15
34
|
unwrapWsteth,
|
|
16
|
-
updateSettings,
|
|
17
35
|
wrapSteth
|
|
18
|
-
} from "../chunk-
|
|
36
|
+
} from "../chunk-EKZFGIVK.js";
|
|
19
37
|
import {
|
|
20
38
|
loadConfig
|
|
21
|
-
} from "../chunk-
|
|
39
|
+
} from "../chunk-P6VFMSPM.js";
|
|
40
|
+
import {
|
|
41
|
+
loadBounds,
|
|
42
|
+
saveBounds
|
|
43
|
+
} from "../chunk-CH4MXPWS.js";
|
|
44
|
+
import {
|
|
45
|
+
initLedger,
|
|
46
|
+
ledgerStats,
|
|
47
|
+
queryLedger
|
|
48
|
+
} from "../chunk-RR74UAKD.js";
|
|
49
|
+
import "../chunk-PDX44BCA.js";
|
|
22
50
|
|
|
23
51
|
// src/server/index.ts
|
|
24
52
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
25
53
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
26
54
|
import { z } from "zod";
|
|
55
|
+
try {
|
|
56
|
+
initLedger();
|
|
57
|
+
} catch {
|
|
58
|
+
}
|
|
27
59
|
var cfg = loadConfig();
|
|
28
|
-
var modeNote = cfg.mode === "simulation" ? "
|
|
29
|
-
var server = new McpServer({ name: "@moly/lido", version: "1.0.0" });
|
|
60
|
+
var modeNote = cfg.mode === "simulation" ? "SIMULATION \u2014 dry_run true by default, no real transactions" : "LIVE \u2014 real transactions on " + (cfg.network === "mainnet" ? "Ethereum Mainnet" : "Hoodi Testnet");
|
|
61
|
+
var server = new McpServer({ name: "@moly-mcp/lido", version: "1.0.0" });
|
|
30
62
|
server.tool(
|
|
31
63
|
"get_balance",
|
|
32
64
|
`Get ETH, stETH, and wstETH balances for an address. ${modeNote}`,
|
|
@@ -174,7 +206,153 @@ server.tool(
|
|
|
174
206
|
content: [{ type: "text", text: JSON.stringify(updateSettings({ network, mode, rpc, model }), null, 2) }]
|
|
175
207
|
})
|
|
176
208
|
);
|
|
209
|
+
server.tool(
|
|
210
|
+
"set_alert",
|
|
211
|
+
"Create a new alert. Conditions: balance_below, balance_above, reward_rate_below, reward_rate_above, withdrawal_ready, proposal_new, conversion_rate_above, conversion_rate_below. Default channel: telegram.",
|
|
212
|
+
{
|
|
213
|
+
condition: z.string().describe("Alert condition type"),
|
|
214
|
+
threshold: z.number().optional().describe("Numeric threshold (required for _above/_below conditions)"),
|
|
215
|
+
channel: z.enum(["telegram", "webhook"]).optional().default("telegram").describe("Notification channel")
|
|
216
|
+
},
|
|
217
|
+
async ({ condition, threshold, channel }) => ({
|
|
218
|
+
content: [{ type: "text", text: JSON.stringify(setAlert({ condition, threshold, channel }), null, 2) }]
|
|
219
|
+
})
|
|
220
|
+
);
|
|
221
|
+
server.tool(
|
|
222
|
+
"list_alerts",
|
|
223
|
+
"List all configured alerts.",
|
|
224
|
+
{},
|
|
225
|
+
async () => ({
|
|
226
|
+
content: [{ type: "text", text: JSON.stringify(listAlerts(), null, 2) }]
|
|
227
|
+
})
|
|
228
|
+
);
|
|
229
|
+
server.tool(
|
|
230
|
+
"remove_alert",
|
|
231
|
+
"Remove an alert by ID.",
|
|
232
|
+
{ id: z.string().describe("Alert ID to remove") },
|
|
233
|
+
async ({ id }) => ({
|
|
234
|
+
content: [{ type: "text", text: JSON.stringify(removeAlertById(id), null, 2) }]
|
|
235
|
+
})
|
|
236
|
+
);
|
|
237
|
+
server.tool(
|
|
238
|
+
"configure_alert_channels",
|
|
239
|
+
"Configure Telegram and/or webhook notification channels for alerts.",
|
|
240
|
+
{
|
|
241
|
+
telegram_token: z.string().optional().describe("Telegram bot token"),
|
|
242
|
+
telegram_chat_id: z.string().optional().describe("Telegram chat ID"),
|
|
243
|
+
webhook_url: z.string().optional().describe("Webhook URL for HTTP POST notifications")
|
|
244
|
+
},
|
|
245
|
+
async ({ telegram_token, telegram_chat_id, webhook_url }) => ({
|
|
246
|
+
content: [{ type: "text", text: JSON.stringify(configureAlertChannels({ telegram_token, telegram_chat_id, webhook_url }), null, 2) }]
|
|
247
|
+
})
|
|
248
|
+
);
|
|
249
|
+
server.tool(
|
|
250
|
+
"get_total_position",
|
|
251
|
+
"Aggregated cross-chain position: ETH, stETH, wstETH across Ethereum + Base + Arbitrum, converted to ETH equivalent.",
|
|
252
|
+
{ address: z.string().optional().describe("Ethereum address (defaults to configured wallet)") },
|
|
253
|
+
async ({ address }) => ({
|
|
254
|
+
content: [{ type: "text", text: JSON.stringify(await getTotalPosition(address), null, 2) }]
|
|
255
|
+
})
|
|
256
|
+
);
|
|
257
|
+
server.tool(
|
|
258
|
+
"get_bounds",
|
|
259
|
+
"Get current policy bounds (max stake per tx, daily limit, min ETH reserve, governance auto-vote).",
|
|
260
|
+
{},
|
|
261
|
+
async () => ({
|
|
262
|
+
content: [{ type: "text", text: JSON.stringify(loadBounds(), null, 2) }]
|
|
263
|
+
})
|
|
264
|
+
);
|
|
265
|
+
server.tool(
|
|
266
|
+
"set_bounds",
|
|
267
|
+
"Update policy bounds that gate write operations.",
|
|
268
|
+
{
|
|
269
|
+
maxStakePerTx: z.number().optional().describe("Max ETH per single stake"),
|
|
270
|
+
maxDailyStake: z.number().optional().describe("Max ETH staked per day"),
|
|
271
|
+
minEthReserve: z.number().optional().describe("Min ETH to keep unstaked for gas"),
|
|
272
|
+
autoRestakeThreshold: z.number().optional().describe("Auto-restake rewards threshold"),
|
|
273
|
+
governanceAutoVote: z.boolean().optional().describe("Allow agent to auto-vote")
|
|
274
|
+
},
|
|
275
|
+
async (patch) => {
|
|
276
|
+
const current = loadBounds();
|
|
277
|
+
if (patch.maxStakePerTx !== void 0) current.maxStakePerTx = patch.maxStakePerTx;
|
|
278
|
+
if (patch.maxDailyStake !== void 0) current.maxDailyStake = patch.maxDailyStake;
|
|
279
|
+
if (patch.minEthReserve !== void 0) current.minEthReserve = patch.minEthReserve;
|
|
280
|
+
if (patch.autoRestakeThreshold !== void 0) current.autoRestakeThreshold = patch.autoRestakeThreshold;
|
|
281
|
+
if (patch.governanceAutoVote !== void 0) current.governanceAutoVote = patch.governanceAutoVote;
|
|
282
|
+
saveBounds(current);
|
|
283
|
+
return { content: [{ type: "text", text: JSON.stringify(current, null, 2) }] };
|
|
284
|
+
}
|
|
285
|
+
);
|
|
286
|
+
server.tool(
|
|
287
|
+
"get_l2_balance",
|
|
288
|
+
"Get ETH and wstETH balances on Base or Arbitrum. Mainnet only. Use this before bridging to check available funds.",
|
|
289
|
+
{
|
|
290
|
+
source_chain: z.enum(["base", "arbitrum"]).describe("L2 chain to query"),
|
|
291
|
+
address: z.string().optional().describe("Address to check (defaults to configured wallet)")
|
|
292
|
+
},
|
|
293
|
+
async ({ source_chain, address }) => ({
|
|
294
|
+
content: [{ type: "text", text: JSON.stringify(await getL2Balance(source_chain, address), null, 2) }]
|
|
295
|
+
})
|
|
296
|
+
);
|
|
297
|
+
server.tool(
|
|
298
|
+
"get_bridge_quote",
|
|
299
|
+
"Get a quote for bridging ETH or wstETH from an L2 to Ethereum L1 via LI.FI. Mainnet only. Requires a configured wallet address.",
|
|
300
|
+
{
|
|
301
|
+
source_chain: z.enum(["base", "arbitrum"]).describe("L2 to bridge from"),
|
|
302
|
+
token: z.enum(["ETH", "wstETH"]).describe("Token to bridge"),
|
|
303
|
+
amount: z.string().describe('Amount to bridge (e.g. "0.1")'),
|
|
304
|
+
to_token: z.enum(["ETH", "wstETH"]).optional().describe("Token to receive on L1 (default ETH)")
|
|
305
|
+
},
|
|
306
|
+
async ({ source_chain, token, amount, to_token }) => ({
|
|
307
|
+
content: [{ type: "text", text: JSON.stringify(await getBridgeQuote(source_chain, token, amount, to_token), null, 2) }]
|
|
308
|
+
})
|
|
309
|
+
);
|
|
310
|
+
server.tool(
|
|
311
|
+
"bridge_to_ethereum",
|
|
312
|
+
"Bridge ETH or wstETH from Base/Arbitrum to Ethereum L1 via LI.FI. Mainnet only. Requires a private key. In simulation mode this returns a quote without broadcasting.",
|
|
313
|
+
{
|
|
314
|
+
source_chain: z.enum(["base", "arbitrum"]).describe("L2 to bridge from"),
|
|
315
|
+
token: z.enum(["ETH", "wstETH"]).describe("Token to bridge"),
|
|
316
|
+
amount: z.string().describe("Amount to bridge"),
|
|
317
|
+
to_token: z.enum(["ETH", "wstETH"]).optional().describe("Token to receive on L1 (default ETH)"),
|
|
318
|
+
dry_run: z.boolean().optional().describe("Simulate without broadcasting")
|
|
319
|
+
},
|
|
320
|
+
async ({ source_chain, token, amount, to_token, dry_run }) => ({
|
|
321
|
+
content: [{ type: "text", text: JSON.stringify(await bridgeToEthereum(source_chain, token, amount, to_token, dry_run), null, 2) }]
|
|
322
|
+
})
|
|
323
|
+
);
|
|
324
|
+
server.tool(
|
|
325
|
+
"get_bridge_status",
|
|
326
|
+
"Check the status of an in-progress bridge transaction. Mainnet only. Use the tx hash returned by bridge_to_ethereum.",
|
|
327
|
+
{
|
|
328
|
+
tx_hash: z.string().describe("Bridge transaction hash on the L2"),
|
|
329
|
+
source_chain: z.enum(["base", "arbitrum"]).describe("L2 the bridge was sent from")
|
|
330
|
+
},
|
|
331
|
+
async ({ tx_hash, source_chain }) => ({
|
|
332
|
+
content: [{ type: "text", text: JSON.stringify(await getBridgeStatus(tx_hash, source_chain), null, 2) }]
|
|
333
|
+
})
|
|
334
|
+
);
|
|
335
|
+
server.tool(
|
|
336
|
+
"get_trade_history",
|
|
337
|
+
"Query the activity ledger with filters.",
|
|
338
|
+
{
|
|
339
|
+
tool: z.string().optional().describe("Filter by tool name (e.g. stake_eth)"),
|
|
340
|
+
since: z.string().optional().describe("ISO date to filter from"),
|
|
341
|
+
limit: z.number().int().optional().default(50).describe("Max results")
|
|
342
|
+
},
|
|
343
|
+
async (opts) => ({
|
|
344
|
+
content: [{ type: "text", text: JSON.stringify(queryLedger(opts), null, 2) }]
|
|
345
|
+
})
|
|
346
|
+
);
|
|
347
|
+
server.tool(
|
|
348
|
+
"get_staking_summary",
|
|
349
|
+
"Aggregate stats from the activity ledger: total operations, staked ETH, errors.",
|
|
350
|
+
{ since: z.string().optional().describe("ISO date to filter from") },
|
|
351
|
+
async ({ since }) => ({
|
|
352
|
+
content: [{ type: "text", text: JSON.stringify(ledgerStats(since), null, 2) }]
|
|
353
|
+
})
|
|
354
|
+
);
|
|
177
355
|
var transport = new StdioServerTransport();
|
|
178
356
|
await server.connect(transport);
|
|
179
|
-
process.stderr.write(`@moly/lido MCP server started \u2014 ${modeNote}
|
|
357
|
+
process.stderr.write(`@moly-mcp/lido MCP server started \u2014 ${modeNote}
|
|
180
358
|
`);
|