@drparadox05/lido-mcp-server 0.1.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/.env.example +7 -0
- package/DEMO.md +145 -0
- package/README.md +252 -0
- package/dist/config/env.js +53 -0
- package/dist/index.js +12 -0
- package/dist/lido/abis.js +261 -0
- package/dist/lido/account.js +108 -0
- package/dist/lido/advisor.js +474 -0
- package/dist/lido/clients.js +34 -0
- package/dist/lido/governance.js +223 -0
- package/dist/lido/index.js +8 -0
- package/dist/lido/networks.js +76 -0
- package/dist/lido/rewards.js +116 -0
- package/dist/lido/setup.js +378 -0
- package/dist/lido/staking.js +185 -0
- package/dist/lido/types.js +11 -0
- package/dist/lido/utils.js +54 -0
- package/dist/lido/withdrawals.js +294 -0
- package/dist/lido.js +1 -0
- package/dist/server/createServer.js +311 -0
- package/dist/server/index.js +1 -0
- package/dist/shared/mcp.js +37 -0
- package/dist/uniswap/api.js +104 -0
- package/dist/uniswap/index.js +318 -0
- package/dist/uniswap/tokens.js +44 -0
- package/dist/uniswap/types.js +6 -0
- package/lido.skill.md +131 -0
- package/package.json +60 -0
package/.env.example
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
LIDO_PRIVATE_KEY=0x_your_private_key_here
|
|
2
|
+
ETHEREUM_RPC_URL=https://eth-mainnet.your-rpc.example
|
|
3
|
+
BASE_RPC_URL=https://mainnet.base.org
|
|
4
|
+
OPTIMISM_RPC_URL=https://mainnet.optimism.io
|
|
5
|
+
ARBITRUM_RPC_URL=https://arb1.arbitrum.io/rpc
|
|
6
|
+
UNISWAP_API_KEY=your_uniswap_api_key_here
|
|
7
|
+
UNISWAP_UNIVERSAL_ROUTER_VERSION=2.0
|
package/DEMO.md
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# Demo Guide
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
This guide gives a judge or developer a fast path to evaluate the Lido MCP server in Cursor or Claude Desktop.
|
|
6
|
+
|
|
7
|
+
The strongest story is:
|
|
8
|
+
|
|
9
|
+
- inspect setup
|
|
10
|
+
- inspect the full Lido portfolio
|
|
11
|
+
- preflight a write safely
|
|
12
|
+
- dry-run the write
|
|
13
|
+
- preflight a Uniswap bridge or swap route safely
|
|
14
|
+
- dry-run the Uniswap route with approvals surfaced explicitly
|
|
15
|
+
- inspect governance context
|
|
16
|
+
|
|
17
|
+
## Recommended flow
|
|
18
|
+
|
|
19
|
+
### 1. Check setup
|
|
20
|
+
|
|
21
|
+
Prompt:
|
|
22
|
+
|
|
23
|
+
```text
|
|
24
|
+
Show my Lido MCP setup status.
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Expected outcome:
|
|
28
|
+
|
|
29
|
+
- confirms wallet configuration
|
|
30
|
+
- confirms RPC availability
|
|
31
|
+
- shows readable and writable networks
|
|
32
|
+
|
|
33
|
+
### 2. Inspect the full portfolio
|
|
34
|
+
|
|
35
|
+
Prompt:
|
|
36
|
+
|
|
37
|
+
```text
|
|
38
|
+
Show my aggregated Lido portfolio summary.
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Expected outcome:
|
|
42
|
+
|
|
43
|
+
- balances across Ethereum, Base, Optimism, and Arbitrum
|
|
44
|
+
- total stETH-equivalent exposure
|
|
45
|
+
- withdrawal queue status and claimable ETH
|
|
46
|
+
- recent governance context
|
|
47
|
+
- action recommendations
|
|
48
|
+
|
|
49
|
+
### 3. Preflight a write before execution
|
|
50
|
+
|
|
51
|
+
Prompt:
|
|
52
|
+
|
|
53
|
+
```text
|
|
54
|
+
Preflight wrapping 0.1 stETH into wstETH on Ethereum.
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Expected outcome:
|
|
58
|
+
|
|
59
|
+
- checks wallet presence
|
|
60
|
+
- validates balance
|
|
61
|
+
- checks allowance
|
|
62
|
+
- states whether approval is required
|
|
63
|
+
- recommends the next safe command
|
|
64
|
+
|
|
65
|
+
### 4. Dry-run the actual write
|
|
66
|
+
|
|
67
|
+
Prompt:
|
|
68
|
+
|
|
69
|
+
```text
|
|
70
|
+
Dry run wrapping 0.1 stETH into wstETH on Ethereum.
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Expected outcome:
|
|
74
|
+
|
|
75
|
+
- returns the simulated request
|
|
76
|
+
- shows whether approval is part of the path
|
|
77
|
+
- does not broadcast a transaction
|
|
78
|
+
|
|
79
|
+
### 5. Inspect governance
|
|
80
|
+
|
|
81
|
+
Prompt:
|
|
82
|
+
|
|
83
|
+
```text
|
|
84
|
+
Show the 5 most recent Lido governance proposals and whether my wallet can vote.
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Expected outcome:
|
|
88
|
+
|
|
89
|
+
- recent proposals
|
|
90
|
+
- execution state
|
|
91
|
+
- wallet voting eligibility if a wallet is configured
|
|
92
|
+
|
|
93
|
+
### 6. Preflight a Uniswap bridge or swap route
|
|
94
|
+
|
|
95
|
+
Prompt:
|
|
96
|
+
|
|
97
|
+
```text
|
|
98
|
+
Preflight a Uniswap route from ETH on Ethereum into wstETH on Base.
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Expected outcome:
|
|
102
|
+
|
|
103
|
+
- confirms Uniswap API readiness
|
|
104
|
+
- resolves token aliases and source/destination chains
|
|
105
|
+
- shows whether approval is required on the source chain
|
|
106
|
+
- reports the selected routing type and whether the server can execute it live
|
|
107
|
+
- recommends the next safe command
|
|
108
|
+
|
|
109
|
+
### 7. Dry-run the Uniswap route
|
|
110
|
+
|
|
111
|
+
Prompt:
|
|
112
|
+
|
|
113
|
+
```text
|
|
114
|
+
Dry run a Uniswap route from wstETH on Base into native ETH on Base.
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Expected outcome:
|
|
118
|
+
|
|
119
|
+
- returns approval transaction details if needed
|
|
120
|
+
- returns the generated swap transaction calldata
|
|
121
|
+
- does not broadcast any transaction
|
|
122
|
+
- makes the route shape and gas expectations explicit before execution
|
|
123
|
+
|
|
124
|
+
## Copy-paste prompt set
|
|
125
|
+
|
|
126
|
+
```text
|
|
127
|
+
Show my Lido MCP setup status.
|
|
128
|
+
Show my aggregated Lido portfolio summary.
|
|
129
|
+
Show bridgable destinations for wstETH on Ethereum.
|
|
130
|
+
Preflight a Uniswap route from ETH on Ethereum into wstETH on Base.
|
|
131
|
+
Dry run a Uniswap route from wstETH on Base into native ETH on Base.
|
|
132
|
+
Preflight staking 0.01 ETH on Ethereum.
|
|
133
|
+
Preflight wrapping 0.1 stETH into wstETH on Ethereum.
|
|
134
|
+
Dry run wrapping 0.1 stETH into wstETH on Ethereum.
|
|
135
|
+
Show my withdrawal requests and claimable ETH on Ethereum.
|
|
136
|
+
Show the 5 most recent Lido governance proposals.
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## What judges should notice
|
|
140
|
+
|
|
141
|
+
- all write actions are safe by default because `dry_run=true`
|
|
142
|
+
- the preflight tool turns raw contract actions into agent-friendly safety checks
|
|
143
|
+
- the Uniswap route preflight exposes approval requirements and route compatibility before any source-chain transaction is sent
|
|
144
|
+
- the portfolio summary tool gives a single high-signal view instead of forcing many separate calls
|
|
145
|
+
- Ethereum is the canonical execution layer for Lido core actions while L2s provide read visibility for bridged assets
|
package/README.md
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
# Lido MCP Server
|
|
2
|
+
|
|
3
|
+
A reference MCP server for Lido that exposes real on-chain tools for:
|
|
4
|
+
|
|
5
|
+
- staking ETH into `stETH`
|
|
6
|
+
- wrapping and unwrapping `stETH` and `wstETH`
|
|
7
|
+
- requesting and claiming withdrawals through the Lido withdrawal queue
|
|
8
|
+
- balance and reward-aware position queries
|
|
9
|
+
- Lido DAO governance proposal queries and voting
|
|
10
|
+
- Uniswap-powered swaps and cross-chain bridge routing with approval-aware preflight and dry-run execution
|
|
11
|
+
- agent-friendly discovery and mental-model guidance for safe tool selection
|
|
12
|
+
|
|
13
|
+
The server uses direct contract calls through `viem`.
|
|
14
|
+
It is not a REST wrapper.
|
|
15
|
+
All write tools support `dry_run` and default to `true`.
|
|
16
|
+
|
|
17
|
+
## Installation & usage
|
|
18
|
+
|
|
19
|
+
**For users:** See [USER_GUIDE.md](USER_GUIDE.md) for complete setup instructions.
|
|
20
|
+
|
|
21
|
+
**Quick start:**
|
|
22
|
+
|
|
23
|
+
You don't need to manually install anything. Just add this to your MCP client config (Cursor, Claude Desktop, etc.):
|
|
24
|
+
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"mcpServers": {
|
|
28
|
+
"lido": {
|
|
29
|
+
"command": "npx",
|
|
30
|
+
"args": ["-y", "lido-mcp-server"],
|
|
31
|
+
"env": {
|
|
32
|
+
"LIDO_PRIVATE_KEY": "0x...",
|
|
33
|
+
"ETHEREUM_RPC_URL": "https://eth-mainnet.g.alchemy.com/v2/...",
|
|
34
|
+
"UNISWAP_API_KEY": "..."
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
> [!TIP]
|
|
42
|
+
> **Important:** To get the best out of this server, feed the `lido.skill.md` file to your AI agent (in custom instructions or workspace rules). This ensures the agent understands Lido's rebasing mechanics and safety patterns.
|
|
43
|
+
|
|
44
|
+
**Configuration templates:**
|
|
45
|
+
- [Example Config](mcp.config.example.json) - Standard configuration example
|
|
46
|
+
|
|
47
|
+
## Project structure
|
|
48
|
+
|
|
49
|
+
```text
|
|
50
|
+
src/
|
|
51
|
+
config/
|
|
52
|
+
env.ts
|
|
53
|
+
lido/
|
|
54
|
+
abis.ts
|
|
55
|
+
advisor.ts
|
|
56
|
+
account.ts
|
|
57
|
+
clients.ts
|
|
58
|
+
governance.ts
|
|
59
|
+
index.ts
|
|
60
|
+
networks.ts
|
|
61
|
+
rewards.ts
|
|
62
|
+
setup.ts
|
|
63
|
+
staking.ts
|
|
64
|
+
types.ts
|
|
65
|
+
utils.ts
|
|
66
|
+
withdrawals.ts
|
|
67
|
+
server/
|
|
68
|
+
createServer.ts
|
|
69
|
+
index.ts
|
|
70
|
+
shared/
|
|
71
|
+
mcp.ts
|
|
72
|
+
uniswap/
|
|
73
|
+
api.ts
|
|
74
|
+
index.ts
|
|
75
|
+
tokens.ts
|
|
76
|
+
types.ts
|
|
77
|
+
index.ts
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
The repo is structured so contract metadata, runtime configuration, chain clients, business logic, and MCP transport wiring are separated.
|
|
81
|
+
Sensitive environment access is centralized in `src/config/env.ts` instead of being scattered across the codebase.
|
|
82
|
+
|
|
83
|
+
## Supported networks
|
|
84
|
+
|
|
85
|
+
- `ethereum`
|
|
86
|
+
- `base`
|
|
87
|
+
- `optimism`
|
|
88
|
+
- `arbitrum`
|
|
89
|
+
|
|
90
|
+
Core staking, withdrawal queue actions, wrapping, and governance execute on `ethereum`.
|
|
91
|
+
L2 networks are supported for balance-aware reads of bridged Lido assets.
|
|
92
|
+
|
|
93
|
+
## Implemented MCP tools
|
|
94
|
+
|
|
95
|
+
- `lido_get_setup`
|
|
96
|
+
- `lido_get_agent_guide`
|
|
97
|
+
- `lido_get_account_overview`
|
|
98
|
+
- `lido_get_portfolio_summary`
|
|
99
|
+
- `lido_preflight_write_action`
|
|
100
|
+
- `lido_get_rewards`
|
|
101
|
+
- `lido_stake_eth`
|
|
102
|
+
- `lido_wrap_steth`
|
|
103
|
+
- `lido_unwrap_wsteth`
|
|
104
|
+
- `lido_request_unstake`
|
|
105
|
+
- `lido_get_withdrawal_requests`
|
|
106
|
+
- `lido_claim_withdrawals`
|
|
107
|
+
- `lido_get_governance_proposals`
|
|
108
|
+
- `lido_vote_on_proposal`
|
|
109
|
+
- `lido_execute_proposal`
|
|
110
|
+
- `lido_preflight_uniswap_route`
|
|
111
|
+
- `lido_execute_uniswap_route`
|
|
112
|
+
- `lido_get_uniswap_route_status`
|
|
113
|
+
- `lido_get_uniswap_bridgable_tokens`
|
|
114
|
+
|
|
115
|
+
## Quick start
|
|
116
|
+
|
|
117
|
+
### 1. Install dependencies
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
npm install
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### 2. Configure environment
|
|
124
|
+
|
|
125
|
+
Copy `.env.example` to `.env` or export variables in your shell.
|
|
126
|
+
|
|
127
|
+
Required for writes:
|
|
128
|
+
|
|
129
|
+
- `LIDO_PRIVATE_KEY`
|
|
130
|
+
- `ETHEREUM_RPC_URL`
|
|
131
|
+
|
|
132
|
+
Useful variables:
|
|
133
|
+
|
|
134
|
+
- `ETHEREUM_RPC_URL`
|
|
135
|
+
- `BASE_RPC_URL`
|
|
136
|
+
- `OPTIMISM_RPC_URL`
|
|
137
|
+
- `ARBITRUM_RPC_URL`
|
|
138
|
+
|
|
139
|
+
Required for Uniswap-powered route discovery and execution:
|
|
140
|
+
|
|
141
|
+
- `UNISWAP_API_KEY`
|
|
142
|
+
|
|
143
|
+
Optional for Uniswap route generation:
|
|
144
|
+
|
|
145
|
+
- `UNISWAP_UNIVERSAL_ROUTER_VERSION`
|
|
146
|
+
|
|
147
|
+
### 3. Build
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
npm run build
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### 4. Run over stdio
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
npm start
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
For local development:
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
npm run dev
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Judge and developer quick prompts
|
|
166
|
+
|
|
167
|
+
Use these prompts directly in Cursor or Claude after connecting the MCP server:
|
|
168
|
+
|
|
169
|
+
```text
|
|
170
|
+
Show my Lido MCP setup status.
|
|
171
|
+
Show the Lido agent guide for staking.
|
|
172
|
+
Show my aggregated Lido portfolio summary.
|
|
173
|
+
Show bridgable destinations for wstETH on Ethereum.
|
|
174
|
+
Preflight a Uniswap route from ETH on Ethereum into wstETH on Base.
|
|
175
|
+
Dry run a Uniswap route from wstETH on Base into native ETH on Base.
|
|
176
|
+
Preflight staking 0.01 ETH on Ethereum.
|
|
177
|
+
Preflight wrapping 0.1 stETH into wstETH on Ethereum.
|
|
178
|
+
Dry run wrapping 0.1 stETH into wstETH on Ethereum.
|
|
179
|
+
Show my withdrawal requests and claimable ETH on Ethereum.
|
|
180
|
+
Show the 5 most recent Lido governance proposals.
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
A fuller walkthrough lives in `DEMO.md`.
|
|
184
|
+
|
|
185
|
+
## Cursor or Claude MCP configuration
|
|
186
|
+
|
|
187
|
+
Use a stdio MCP entry that launches the server from this repo.
|
|
188
|
+
|
|
189
|
+
Example:
|
|
190
|
+
|
|
191
|
+
```json
|
|
192
|
+
{
|
|
193
|
+
"mcpServers": {
|
|
194
|
+
"lido": {
|
|
195
|
+
"command": "node",
|
|
196
|
+
"args": ["/home/drparadox/synthesis_hack/dist/index.js"],
|
|
197
|
+
"env": {
|
|
198
|
+
"LIDO_PRIVATE_KEY": "0x...",
|
|
199
|
+
"ETHEREUM_RPC_URL": "https://eth-mainnet.your-rpc.example",
|
|
200
|
+
"BASE_RPC_URL": "https://mainnet.base.org",
|
|
201
|
+
"OPTIMISM_RPC_URL": "https://mainnet.optimism.io",
|
|
202
|
+
"ARBITRUM_RPC_URL": "https://arb1.arbitrum.io/rpc",
|
|
203
|
+
"UNISWAP_API_KEY": "your-uniswap-api-key"
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
If you prefer running TypeScript directly during development, point the MCP client at `tsx` and `/home/drparadox/synthesis_hack/src/index.ts` instead.
|
|
211
|
+
|
|
212
|
+
## Safety model
|
|
213
|
+
|
|
214
|
+
- All write tools default to `dry_run=true`
|
|
215
|
+
- `lido_get_setup` returns recommended first tools, safety defaults, quickstart prompts, and Uniswap API readiness metadata
|
|
216
|
+
- `lido_get_agent_guide` returns the Lido mental model, network boundaries, workflow guidance, and topic-specific tool recommendations
|
|
217
|
+
- `lido_preflight_write_action` can validate the path before a Lido-core write is even dry-run
|
|
218
|
+
- `lido_preflight_uniswap_route` checks approval requirements, route type, and execution compatibility before a Uniswap swap or bridge is attempted
|
|
219
|
+
- `lido_execute_uniswap_route` defaults to `dry_run=true` and uses a direct approval-then-swap flow with `x-permit2-disabled=true`
|
|
220
|
+
- `lido_get_uniswap_route_status` can track the source-chain transaction status for swap and bridge routes after submission
|
|
221
|
+
- Approval-dependent flows report when an approval is required before the main action can execute
|
|
222
|
+
- Withdrawal requests are treated as queue entries, not instant ETH exits
|
|
223
|
+
- Governance writes require the configured wallet to be eligible to act
|
|
224
|
+
|
|
225
|
+
## Notes on rewards
|
|
226
|
+
|
|
227
|
+
Lido rewards are not a simple claimable bucket.
|
|
228
|
+
|
|
229
|
+
- `stETH` rewards appear through rebasing balances
|
|
230
|
+
- `wstETH` rewards appear through an increasing conversion rate to `stETH`
|
|
231
|
+
|
|
232
|
+
The `lido_get_rewards` tool can return current reward context or a net on-chain balance delta since a historical block.
|
|
233
|
+
That historical delta should only be interpreted as pure staking rewards when the address had no transfers in or out during the interval.
|
|
234
|
+
|
|
235
|
+
## Notes on unstaking
|
|
236
|
+
|
|
237
|
+
Unstaking on Lido is a two-phase path:
|
|
238
|
+
|
|
239
|
+
- request withdrawal from `stETH` or `wstETH`
|
|
240
|
+
- wait for queue finalization and then claim ETH
|
|
241
|
+
|
|
242
|
+
The server exposes both phases separately.
|
|
243
|
+
|
|
244
|
+
## Skill file
|
|
245
|
+
|
|
246
|
+
The repo includes `lido.skill.md`, which gives an agent the correct mental model for:
|
|
247
|
+
|
|
248
|
+
- rebasing `stETH`
|
|
249
|
+
- non-rebasing `wstETH`
|
|
250
|
+
- L2 vs Ethereum responsibilities
|
|
251
|
+
- safe approval and queue usage
|
|
252
|
+
- governance caution
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { dirname, resolve } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
const PRIVATE_KEY_ENV_KEYS = ['LIDO_PRIVATE_KEY', 'WALLET_PRIVATE_KEY', 'PRIVATE_KEY'];
|
|
5
|
+
function stripWrappingQuotes(value) {
|
|
6
|
+
if ((value.startsWith('"') && value.endsWith('"'))
|
|
7
|
+
|| (value.startsWith("'") && value.endsWith("'"))) {
|
|
8
|
+
return value.slice(1, -1);
|
|
9
|
+
}
|
|
10
|
+
return value;
|
|
11
|
+
}
|
|
12
|
+
function loadDotEnvFile() {
|
|
13
|
+
const currentDir = dirname(fileURLToPath(import.meta.url));
|
|
14
|
+
const envPath = resolve(currentDir, '../../.env');
|
|
15
|
+
if (!existsSync(envPath)) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const content = readFileSync(envPath, 'utf8');
|
|
19
|
+
for (const rawLine of content.split(/\r?\n/u)) {
|
|
20
|
+
const line = rawLine.trim();
|
|
21
|
+
if (!line || line.startsWith('#')) {
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
const separatorIndex = line.indexOf('=');
|
|
25
|
+
if (separatorIndex <= 0) {
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
const key = line.slice(0, separatorIndex).trim();
|
|
29
|
+
const value = stripWrappingQuotes(line.slice(separatorIndex + 1).trim());
|
|
30
|
+
if (!key || process.env[key] !== undefined) {
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
process.env[key] = value;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
loadDotEnvFile();
|
|
37
|
+
export function getOptionalEnv(name) {
|
|
38
|
+
const value = process.env[name]?.trim();
|
|
39
|
+
return value && value.length > 0 ? value : undefined;
|
|
40
|
+
}
|
|
41
|
+
export function hasPrivateKeyConfigured() {
|
|
42
|
+
return PRIVATE_KEY_ENV_KEYS.some((name) => Boolean(getOptionalEnv(name)));
|
|
43
|
+
}
|
|
44
|
+
export function getPrivateKey() {
|
|
45
|
+
const value = PRIVATE_KEY_ENV_KEYS.map((name) => getOptionalEnv(name)).find((candidate) => Boolean(candidate));
|
|
46
|
+
if (!value) {
|
|
47
|
+
throw new Error(`No private key configured. Set ${PRIVATE_KEY_ENV_KEYS.join(', ')}.`);
|
|
48
|
+
}
|
|
49
|
+
if (!/^0x[0-9a-fA-F]{64}$/.test(value)) {
|
|
50
|
+
throw new Error('Configured private key is not a valid 32-byte hex string.');
|
|
51
|
+
}
|
|
52
|
+
return value;
|
|
53
|
+
}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
2
|
+
import { createServer } from './server/createServer.js';
|
|
3
|
+
async function main() {
|
|
4
|
+
process.stdin.resume();
|
|
5
|
+
const server = createServer();
|
|
6
|
+
const transport = new StdioServerTransport();
|
|
7
|
+
await server.connect(transport);
|
|
8
|
+
}
|
|
9
|
+
main().catch((error) => {
|
|
10
|
+
console.error(error);
|
|
11
|
+
process.exit(1);
|
|
12
|
+
});
|