dexe-mcp 0.5.7 → 0.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.
Files changed (89) hide show
  1. package/CHANGELOG.md +641 -497
  2. package/README.md +193 -104
  3. package/SECURITY.md +96 -0
  4. package/dist/config.d.ts +9 -0
  5. package/dist/config.d.ts.map +1 -1
  6. package/dist/config.js +60 -0
  7. package/dist/config.js.map +1 -1
  8. package/dist/governor/adapter.d.ts +90 -0
  9. package/dist/governor/adapter.d.ts.map +1 -0
  10. package/dist/governor/adapter.js +169 -0
  11. package/dist/governor/adapter.js.map +1 -0
  12. package/dist/governor/configs/compound.json +32 -0
  13. package/dist/governor/configs/optimism.json +28 -0
  14. package/dist/governor/configs/uniswap.json +32 -0
  15. package/dist/governor/encoder.d.ts +59 -0
  16. package/dist/governor/encoder.d.ts.map +1 -0
  17. package/dist/governor/encoder.js +290 -0
  18. package/dist/governor/encoder.js.map +1 -0
  19. package/dist/governor/index.d.ts +11 -0
  20. package/dist/governor/index.d.ts.map +1 -0
  21. package/dist/governor/index.js +20 -0
  22. package/dist/governor/index.js.map +1 -0
  23. package/dist/governor/loader.d.ts +42 -0
  24. package/dist/governor/loader.d.ts.map +1 -0
  25. package/dist/governor/loader.js +103 -0
  26. package/dist/governor/loader.js.map +1 -0
  27. package/dist/governor/tally.d.ts +48 -0
  28. package/dist/governor/tally.d.ts.map +1 -0
  29. package/dist/governor/tally.js +103 -0
  30. package/dist/governor/tally.js.map +1 -0
  31. package/dist/governor/tools/build.d.ts +3 -0
  32. package/dist/governor/tools/build.d.ts.map +1 -0
  33. package/dist/governor/tools/build.js +137 -0
  34. package/dist/governor/tools/build.js.map +1 -0
  35. package/dist/governor/tools/extras.d.ts +4 -0
  36. package/dist/governor/tools/extras.d.ts.map +1 -0
  37. package/dist/governor/tools/extras.js +197 -0
  38. package/dist/governor/tools/extras.js.map +1 -0
  39. package/dist/governor/tools/read.d.ts +4 -0
  40. package/dist/governor/tools/read.d.ts.map +1 -0
  41. package/dist/governor/tools/read.js +174 -0
  42. package/dist/governor/tools/read.js.map +1 -0
  43. package/dist/governor/tools/simulate.d.ts +6 -0
  44. package/dist/governor/tools/simulate.d.ts.map +1 -0
  45. package/dist/governor/tools/simulate.js +191 -0
  46. package/dist/governor/tools/simulate.js.map +1 -0
  47. package/dist/lib/broadcastGuards.d.ts +41 -0
  48. package/dist/lib/broadcastGuards.d.ts.map +1 -0
  49. package/dist/lib/broadcastGuards.js +85 -0
  50. package/dist/lib/broadcastGuards.js.map +1 -0
  51. package/dist/lib/ethersProvider.d.ts +96 -0
  52. package/dist/lib/ethersProvider.d.ts.map +1 -0
  53. package/dist/lib/ethersProvider.js +170 -0
  54. package/dist/lib/ethersProvider.js.map +1 -0
  55. package/dist/lib/ipfs.d.ts +7 -0
  56. package/dist/lib/ipfs.d.ts.map +1 -1
  57. package/dist/lib/ipfs.js +32 -1
  58. package/dist/lib/ipfs.js.map +1 -1
  59. package/dist/lib/signer.d.ts +2 -0
  60. package/dist/lib/signer.d.ts.map +1 -1
  61. package/dist/lib/signer.js +4 -0
  62. package/dist/lib/signer.js.map +1 -1
  63. package/dist/tools/flow.d.ts.map +1 -1
  64. package/dist/tools/flow.js +13 -0
  65. package/dist/tools/flow.js.map +1 -1
  66. package/dist/tools/getConfig.d.ts.map +1 -1
  67. package/dist/tools/getConfig.js +17 -0
  68. package/dist/tools/getConfig.js.map +1 -1
  69. package/dist/tools/inbox.js +8 -8
  70. package/dist/tools/index.d.ts.map +1 -1
  71. package/dist/tools/index.js +6 -0
  72. package/dist/tools/index.js.map +1 -1
  73. package/dist/tools/ipfs.d.ts.map +1 -1
  74. package/dist/tools/ipfs.js +437 -16
  75. package/dist/tools/ipfs.js.map +1 -1
  76. package/dist/tools/predict.js +17 -17
  77. package/dist/tools/safe.d.ts +5 -0
  78. package/dist/tools/safe.d.ts.map +1 -0
  79. package/dist/tools/safe.js +264 -0
  80. package/dist/tools/safe.js.map +1 -0
  81. package/dist/tools/simulate.d.ts +7 -0
  82. package/dist/tools/simulate.d.ts.map +1 -1
  83. package/dist/tools/simulate.js +8 -0
  84. package/dist/tools/simulate.js.map +1 -1
  85. package/dist/tools/subgraph.js +162 -162
  86. package/dist/tools/txSend.d.ts.map +1 -1
  87. package/dist/tools/txSend.js +25 -0
  88. package/dist/tools/txSend.js.map +1 -1
  89. package/package.json +95 -84
package/README.md CHANGED
@@ -1,56 +1,99 @@
1
- # dexe-mcp
1
+ <p align="center">
2
+ <a href="https://www.npmjs.com/package/dexe-mcp">
3
+ <img src="./assets/hero.svg" alt="dexe-mcp — the runtime for autonomous DAOs" width="100%"/>
4
+ </a>
5
+ </p>
2
6
 
3
- ![npm](https://img.shields.io/npm/v/dexe-mcp.svg)
7
+ <p align="center">
8
+ <a href="https://www.npmjs.com/package/dexe-mcp"><img alt="npm" src="https://img.shields.io/npm/v/dexe-mcp.svg?style=flat-square&labelColor=0b0f1e&color=9BB4FF"></a>
9
+ <a href="https://nodejs.org"><img alt="node" src="https://img.shields.io/node/v/dexe-mcp.svg?style=flat-square&labelColor=0b0f1e&color=E07AFF"></a>
10
+ <a href="https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/LICENSE"><img alt="license" src="https://img.shields.io/npm/l/dexe-mcp.svg?style=flat-square&labelColor=0b0f1e&color=FFC878"></a>
11
+ <a href="https://modelcontextprotocol.io"><img alt="MCP-compatible" src="https://img.shields.io/badge/MCP-compatible-9BB4FF?style=flat-square&labelColor=0b0f1e"></a>
12
+ <a href="https://github.com/edward-arinin-web-dev/dexe-mcp"><img alt="tools" src="https://img.shields.io/badge/tools-149-7CF2D1?style=flat-square&labelColor=0b0f1e"></a>
13
+ <a href="https://github.com/edward-arinin-web-dev/dexe-mcp"><img alt="proposal types" src="https://img.shields.io/badge/proposal--types-33-E07AFF?style=flat-square&labelColor=0b0f1e"></a>
14
+ </p>
4
15
 
5
- MCP server that gives AI agents **full DeXe Protocol DAO operations coverage** — deploy DAOs, build any of the 33 proposal types the DeXe UI exposes, upload metadata to IPFS, stake/delegate/vote/execute/claim. Plus dev tooling: build/test/lint, contract introspection, ABI-aware calldata decoding.
16
+ <h2 align="center">Governance, as a function call.</h2>
6
17
 
7
- **Two write modes, calldata-default.** Every write tool returns a ready-to-sign `TxPayload = { to, data, value, chainId, description }` that the agent's wallet (MetaMask, Safe, hardware, etc.) signs and submits — no key in the MCP. Power users who *want* the server to sign and broadcast can opt in by setting `DEXE_PRIVATE_KEY`; that unlocks `dexe_tx_send`, `dexe_tx_status`, and the auto-broadcast branch of `dexe_proposal_create` / `dexe_proposal_vote_and_execute`. Default stays calldata-only.
18
+ <p align="center">
19
+ <code>dexe-mcp</code> turns the entire DeXe Protocol — every DAO, every proposal type, every read, every write — into <b>one Model Context Protocol server</b>.<br/>
20
+ Plug it into Claude, Cursor, ChatGPT, or any tool-using LLM and watch your agent <b>deploy DAOs, draft proposals, vote, delegate, execute, claim</b> — straight from natural language.<br/>
21
+ <sub>Calldata-first by default: keys stay in your wallet. Broadcast mode? One env var.</sub>
22
+ </p>
8
23
 
9
- **126 tools** across 14 groups. Call `dexe_proposal_catalog` at runtime for the full proposal-type map, or browse the [catalog](#tool-catalog) below.
24
+ <p align="center">
25
+ <a href="#quickstart"><b>Quickstart</b></a> &nbsp;·&nbsp;
26
+ <a href="#what-you-can-build">What you can build</a> &nbsp;·&nbsp;
27
+ <a href="#built-for-whats-next">Built for what's next</a> &nbsp;·&nbsp;
28
+ <a href="#tool-catalog">Tool catalog</a> &nbsp;·&nbsp;
29
+ <a href="#swarm-test-harness">Swarm tests</a> &nbsp;·&nbsp;
30
+ <a href="https://github.com/edward-arinin-web-dev/dexe-mcp/tree/main/docs">Docs</a>
31
+ </p>
10
32
 
11
- > **End-to-end coverage.** Every proposal-builder tool ships with a swarm-test scenario that exercises it on BSC testnet. Latest pass (2026-05-12): **57 scenarios shipped**, broadcasts validated against two fixture DAOs (Polaris 50%-quorum + Sentinel 5%-quorum-with-validators). See [Swarm test harness](#swarm-test-harness) below.
33
+ ---
12
34
 
13
- ## Prerequisites
35
+ ## The shift
14
36
 
15
- - **Node.js 20** with a working `npm` (`node --version` and `npm --version` must both succeed).
16
- - **Git** — only needed the first time a build tool runs, to clone DeXe-Protocol. Skippable if you point `DEXE_PROTOCOL_PATH` at an existing checkout.
37
+ For a decade, DAOs lived behind dashboards. Every action was a click. Every read was a tab. Every coordination loop needed a human at the keyboard.
17
38
 
18
- ## Install
39
+ That era is ending.
19
40
 
20
- ```bash
21
- npm install -g dexe-mcp
22
- ```
41
+ LLMs can now reason about voting power, weigh proposals against a mandate, draft calldata, simulate execution, and ask your wallet to sign — **continuously, across every DAO you care about, all at once.** What was a UI is becoming a conversation. What was a treasurer's spreadsheet is becoming an always-on agent.
23
42
 
24
- Register the server with your MCP client (`.mcp.json`, `claude_desktop_config.json`, etc.):
43
+ **`dexe-mcp` is the substrate that makes it real for the DeXe stack — and now for external OpenZeppelin Governor DAOs as well.** One MCP server. 149 typed tools across 18 groups. Every flow the DeXe frontend exposes — plus a generic `dexe_gov_*` surface targeting Uniswap, Compound, and Optimism.
25
44
 
26
- ```json
27
- {
28
- "mcpServers": {
29
- "dexe": {
30
- "command": "dexe-mcp"
31
- }
32
- }
33
- }
34
- ```
45
+ | | What you get |
46
+ |-----|------|
47
+ | **Total protocol coverage** | All **33 proposal types**. Validator chamber. Expert delegation. OTC multi-tier sales with merkle whitelists. Internal config. Off-chain backend. Nothing hand-rolled. Nothing missing. |
48
+ | **Key-safe by default** | Every write returns `TxPayload = { to, data, value, chainId }`. Your wallet — MetaMask, Safe, Ledger, anything — signs. **No keys touch the MCP unless you explicitly set `DEXE_PRIVATE_KEY`.** |
49
+ | **Battle-tested on-chain** | **57 swarm-test scenarios** running on BSC testnet against real fixture DAOs. Every builder validated end-to-end — draft → IPFS → propose → vote → execute. Latest pass: 2026-05-12. |
50
+ | **AI-native, model-agnostic** | Tool names, argument schemas, and return shapes are tuned for LLM chaining. Works with Claude, GPT, Gemini, Mistral, Llama — anything that can call MCP tools. |
51
+ | **Open source, no middleman** | MIT. Your RPC. Your wallet. Your keys. Your rules. No telemetry. No SaaS gatekeeper. No rate limits. Run it on your laptop or behind your agent fleet. |
35
52
 
36
- If your client can't spawn the bare `dexe-mcp` command directly (a known issue with some MCP clients on Windows when PATH-shim resolution is involved), point it at the installed script via Node:
53
+ ---
37
54
 
38
- ```json
39
- {
40
- "mcpServers": {
41
- "dexe": {
42
- "command": "node",
43
- "args": ["<output of `npm root -g`>/dexe-mcp/dist/index.js"]
44
- }
45
- }
46
- }
47
- ```
55
+ ## What you can build
56
+
57
+ > **One MCP server. Dozens of products that didn't exist a year ago.**
58
+
59
+ - **Governance copilots in chat** — *"Show every proposal I haven't voted on across all my DAOs, ranked by deadline."* The agent fans out `dexe_user_inbox`, ranks results, drafts your votes. You hit sign.
60
+ - **Intent-driven proposal drafting** — *"Stream 50,000 USDT from treasury to the dev fund, vesting linearly over six months."* The agent picks the right builder (`_token_distribution`), assembles nested calldata, pins metadata to IPFS, returns one signable payload. What used to be a 14-field form is now a sentence.
61
+ - **AI delegates that reason** — agents that read every proposal, weigh it against a written mandate, vote, and publish their reasoning on-chain. Real accountability for delegated power.
62
+ - **24/7 autonomous treasury bots** — policy expressed as code, executed as proposals. Market triggers, runway thresholds, vesting schedules — all enforced without a human in the loop, every action a signed on-chain decision.
63
+ - **Multi-DAO coalition orchestration** — one agent coordinating votes across allied protocols, tracking quorums, building coalitions, executing in lockstep.
64
+ - **Conversational DAO frontends** — apps where there *is* no UI. The MCP server is the backend. The chat is the dashboard. The wallet is the only button.
65
+ - **Adversarial governance simulators** — spin up swarms of AI proposers, voters, and validators to red-team a parameter change *before* it hits mainnet. The swarm harness ships with this already (see [Swarm tests](#swarm-test-harness)).
66
+ - **OTC sale autopilots** — open multi-tier sales with merkle whitelists, manage buyer flows, fulfill vested payouts — all without a sale-management UI.
67
+ - **Forensics and compliance** — `dexe_decode_proposal` + `_decode_calldata` make any historic on-chain proposal human-readable. Agents narrate every governance decision for audits, postmortems, and research.
68
+
69
+ If you can describe a DeXe governance operation in a sentence, `dexe-mcp` has the tool.
70
+
71
+ ---
72
+
73
+ ## Built for what's next
74
+
75
+ The next generation of DAOs will be **operated by language, not by clicks.**
76
+
77
+ - **AI delegates will outvote human ones.** They read every proposal. They show their reasoning. They never miss a deadline.
78
+ - **Treasuries will defend themselves.** Policy bots react to market moves, rebalance, claim, redelegate — all through governance, never around it.
79
+ - **Cross-DAO coordination will be ambient.** Coalitions form in seconds via agent-to-agent negotiation, ratified by on-chain votes.
80
+ - **Governance frontends will collapse into chat.** The dashboard moves into the conversation. The UI is the prompt.
81
+ - **Every proposal will be simulated first.** Adversarial AI swarms stress-test changes before they reach mainnet.
82
+ - **Audit will run continuously.** Compliance agents decode and narrate every historical decision in real time.
48
83
 
49
- Run `npm root -g` to resolve the path on your machine. Restart the MCP client and the `dexe_*` tools will appear.
84
+ `dexe-mcp` is the connective tissue. Bring your model. Bring your wallet. Bring your DAO.
85
+
86
+ ---
50
87
 
51
88
  ## Quickstart
52
89
 
53
- Minimum config to get **read-only** access to a BSC mainnet DAO:
90
+ **1.** Install:
91
+
92
+ ```bash
93
+ npm install -g dexe-mcp
94
+ ```
95
+
96
+ **2.** Register with your MCP client (`.mcp.json`, `claude_desktop_config.json`, Cursor settings, etc.):
54
97
 
55
98
  ```json
56
99
  {
@@ -66,35 +109,50 @@ Minimum config to get **read-only** access to a BSC mainnet DAO:
66
109
  }
67
110
  ```
68
111
 
69
- Add `DEXE_PINATA_JWT` for IPFS uploads, `DEXE_BACKEND_API_URL` for off-chain proposals, and per-chain subgraph URLs for `dexe_proposal_voters` and the DAO-list reads. Full matrix → [`docs/ENVIRONMENT.md`](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/docs/ENVIRONMENT.md).
112
+ > **Windows note:** if your MCP client can't resolve the `dexe-mcp` shim on PATH, point it at the installed script directly:
113
+ > ```json
114
+ > { "command": "node", "args": ["<npm root -g>/dexe-mcp/dist/index.js"] }
115
+ > ```
116
+ > (Run `npm root -g` to get the absolute path.)
70
117
 
71
- Three first-call examples (full set in [`docs/USAGE.md`](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/docs/USAGE.md)):
118
+ **3.** Ask your agent something governance-shaped:
72
119
 
73
120
  ```jsonc
74
- // 1) discover available proposal types
121
+ // Discover every proposal type your DAO can run
75
122
  dexe_proposal_catalog({ category: "all", implementedOnly: true })
76
123
 
77
- // 2) read a DAO
124
+ // Snapshot a DAO — treasury, voters, settings, validators, everything
78
125
  dexe_dao_info({ govPool: "0x..." })
79
126
 
80
- // 3) build a token-transfer proposal (calldata only)
127
+ // Draft a token-transfer proposal (returns ready-to-sign calldata)
81
128
  dexe_proposal_build_token_transfer({
82
- govPool: "0x...",
83
- token: "0x...",
129
+ govPool: "0x...",
130
+ token: "0x...",
84
131
  recipient: "0x...",
85
- amount: "1000000000000000000"
132
+ amount: "1000000000000000000"
86
133
  })
87
134
  ```
88
135
 
136
+ The agent gets back a `TxPayload`. Pass it to your wallet. Sign. Submit. Done.
137
+
138
+ **Want the MCP to broadcast too?** Set `DEXE_PRIVATE_KEY` and unlock the composite signing flow (`dexe_proposal_create`, `dexe_proposal_vote_and_execute`, `dexe_tx_send`, `dexe_tx_status`). Strictly opt-in — default stays calldata-only.
139
+
140
+ ---
141
+
142
+ ## Prerequisites
143
+
144
+ - **Node.js ≥ 20** with a working `npm` (`node --version` and `npm --version` must both succeed).
145
+ - **Git** — needed the first time a build tool (`dexe_compile` / `dexe_test` / `dexe_lint`) runs, to shallow-clone DeXe-Protocol. Skippable if you set `DEXE_PROTOCOL_PATH` to an existing checkout.
146
+
89
147
  ## First run
90
148
 
91
- The MCP server starts instantly. On the first build-tool call (`dexe_compile` / `dexe_test` / `dexe_lint`), dexe-mcp will automatically shallow-clone DeXe-Protocol into a platform cache directory and run `npm install` there once. If you prefer to reuse an existing checkout, set `DEXE_PROTOCOL_PATH` in the MCP `env` block and nothing will be cloned.
149
+ The MCP server starts instantly. On the first build-tool call, dexe-mcp shallow-clones DeXe-Protocol into a platform cache directory and runs `npm install` there once. Most tools never need that checkout reads, proposal builders, vote tools, and deploy only need an RPC URL.
92
150
 
93
- Most tools don't need the protocol checkout at all — read/proposal/vote/deploy builders only need an RPC URL. Only the dev-tooling group (`dexe_compile`, `dexe_test`, `dexe_coverage`, `dexe_lint`, and the introspection tools) depends on artifacts.
151
+ ---
94
152
 
95
153
  ## Environment variables
96
154
 
97
- All optional. Tools that need a missing variable fail with a clear message pointing at exactly what to set. Full matrix + per-tool requirements → [`docs/ENVIRONMENT.md`](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/docs/ENVIRONMENT.md).
155
+ All optional. Tools that need a missing variable fail with a clear, actionable message pointing at exactly what to set. Full matrix → [`docs/ENVIRONMENT.md`](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/docs/ENVIRONMENT.md).
98
156
 
99
157
  | Variable | Required for | Purpose |
100
158
  |----------|--------------|---------|
@@ -103,86 +161,92 @@ All optional. Tools that need a missing variable fail with a clear message point
103
161
  | `DEXE_CHAIN_ID` | reads | Defaults to `56` (BSC mainnet). Override for other chains |
104
162
  | `DEXE_CONTRACTS_REGISTRY` | reads (optional) | Override the ContractsRegistry root; defaults to the known per-chain address |
105
163
  | `DEXE_PINATA_JWT` | IPFS uploads | Pinata JWT for pinning proposal/DAO metadata |
106
- | `DEXE_IPFS_GATEWAY` | IPFS fetch | **Dedicated** gateway URL (Pinata provides one alongside your JWT; Filebase / Quicknode / self-hosted also work). Public gateways are unreliable and NOT defaulted |
164
+ | `DEXE_IPFS_GATEWAY` | IPFS fetch | **Dedicated** gateway URL (Pinata, Filebase, Quicknode, self-hosted). Public gateways are unreliable and NOT defaulted |
107
165
  | `DEXE_IPFS_GATEWAYS_FALLBACK` | IPFS fetch (optional) | Comma-separated public gateways tried sequentially after the primary |
108
- | `DEXE_SUBGRAPH_POOLS_URL` | `dexe_read_dao_list`, `dexe_read_dao_members`, `dexe_read_delegation_map`, `dexe_read_dao_experts`, `dexe_user_inbox`, `dexe_proposal_voters`, `dexe_dao_predict_addresses` | The Graph endpoint for the DeXe pools subgraph |
166
+ | `DEXE_SUBGRAPH_POOLS_URL` | `dexe_read_dao_list`, `_dao_members`, `_delegation_map`, `_dao_experts`, `_user_inbox`, `_proposal_voters`, `_dao_predict_addresses` | The Graph endpoint for the DeXe pools subgraph |
109
167
  | `DEXE_SUBGRAPH_VALIDATORS_URL` | `dexe_read_validator_list` | The Graph endpoint for the DeXe validators subgraph |
110
168
  | `DEXE_SUBGRAPH_INTERACTIONS_URL` | `dexe_read_user_activity` | The Graph endpoint for the DeXe interactions subgraph |
111
- | `DEXE_GRAPH_API_KEY` | subgraph reads (optional) | Bearer token for `gateway.thegraph.com`. Required only when `DEXE_SUBGRAPH_*_URL` does not embed the key in the path (`/api/<key>/subgraphs/...`). Auto-extracted from the URL when present |
169
+ | `DEXE_GRAPH_API_KEY` | subgraph reads (optional) | Bearer token for `gateway.thegraph.com`. Required only when the URL doesn't embed the key. Auto-extracted from `/api/<key>/...` URLs |
112
170
  | `DEXE_BACKEND_API_URL` | off-chain proposals | DeXe backend (e.g. `https://api.dexe.io`) |
171
+ | `DEXE_PRIVATE_KEY` | broadcast mode (opt-in) | Enables `_tx_send`, `_tx_status`, and the broadcast branch of composite flows. Default stays calldata-only |
172
+
173
+ ---
113
174
 
114
175
  ## Documentation
115
176
 
116
177
  Full docs in [`docs/`](https://github.com/edward-arinin-web-dev/dexe-mcp/tree/main/docs):
117
178
 
118
- - [`docs/TOOLS.md`](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/docs/TOOLS.md) — complete catalog of all 126 tools, organized by category, with one-line descriptions and required envs per tool.
119
- - [`docs/USAGE.md`](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/docs/USAGE.md) — 10 worked examples (deploy DAO, create proposals, vote, delegate, validator chamber, decode calldata, off-chain proposals, multicall batching). Copy-pasteable JSON.
120
- - [`docs/ENVIRONMENT.md`](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/docs/ENVIRONMENT.md) — full env-var reference: minimum block to get started, per-category requirements, calldata vs signer mode, chain-specific config, IPFS gateway rationale, subgraph migration, swarm harness envs, common pitfalls.
121
-
122
- ## Tool surface (high-level)
123
-
124
- | Group | Tools | What |
125
- |-------|-------|------|
126
- | Dev tooling | 4 | Hardhat wrappers: `dexe_compile`, `_test`, `_coverage`, `_lint` |
127
- | Contract introspection | 10 | `_list_contracts`, `_get_abi`, `_get_methods`, `_get_selectors`, `_find_selector`, `_get_natspec`, `_get_source`, `_decode_calldata`, `_decode_proposal`, `_list_gov_contract_types` |
128
- | DAO reads | 25 | `_dao_info`, `_dao_predict_addresses`, `_dao_registry_lookup`, `_proposal_state/_list/_voters`, `_vote_user_power/_get_votes`, `_read_*` family |
129
- | IPFS | 6 | Pinata uploads, gateway fetch, CID computation |
130
- | DAO deploy | 1 | `dexe_dao_build_deploy` (encodes `PoolFactory.deployGovPool` with full nested struct + predicted addr wiring) |
131
- | Proposal catalog + primitives | 5 | `dexe_proposal_catalog` enumerates **all 33** types; primitives: `_build_external`, `_build_internal`, `_build_custom_abi`, `_build_offchain` |
132
- | External proposal wrappers | 20 | Token transfer / distribution / sale (single + multi-tier), treasury withdraw, validators, experts, staking tier, math model, blacklist, reward multiplier, apply to DAO, modify profile, change voting settings, new proposal type, addToWhitelist, etc. |
133
- | Internal validator wrappers | 4 | `_change_validator_balances`, `_change_validator_settings`, `_monthly_withdraw`, `_offchain_internal_proposal` |
134
- | Off-chain backend | 8 | `_offchain_single_option/_multi_option/_for_against/_settings`, auth flow (`_auth_request_nonce`, `_auth_login_request`), `_offchain_build_vote/_cancel_vote` |
135
- | Vote / stake / delegate / execute / claim | 16 | `_vote_build_*` family every direct EOA write on GovPool / Validators |
136
- | Composite signing flows | 5 | `_proposal_create`, `_proposal_vote_and_execute`, `_tx_send`, `_tx_status`, `_get_config` (signing tools opt-in via `DEXE_PRIVATE_KEY`; `_get_config` is read-only diagnostic for the multi-chain config) |
137
- | Subgraph reads | 7 | DAO list, members, experts, user activity, delegation map, distribution status, OTC sale tiers per DAO (decentralized network endpoints + RPC fallback) |
138
- | Merkle utility | 2 | `dexe_merkle_build`, `dexe_merkle_proof`OZ `StandardMerkleTree`-compatible (sorted-pair commutative keccak, double-hash leaf) |
139
- | OTC composites | 4 | `dexe_otc_dao_open_sale`, `_buyer_status`, `_buyer_buy`, `_buyer_claim_all` full project-owner + buyer flows over `TokenSaleProposal`. See [`docs/OTC.md`](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/docs/OTC.md) |
140
- | Simulator | 3 | `dexe_sim_calldata`, `_sim_proposal`, `_sim_buy` `eth_call`-based preflight with revert-reason decoding. See [`docs/SIMULATOR.md`](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/docs/SIMULATOR.md) |
141
- | Multi-DAO inbox + forecast | 2 | `dexe_user_inbox` — pending items across N DAOs (unvoted proposals, claimable rewards, locked deposits). `_proposal_forecast` — pass-rate prediction with quorum projection + risk flags. See [`docs/INBOX.md`](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/docs/INBOX.md) |
142
-
143
- Total: **126**. Per-tool descriptions, args, return shapes [`docs/TOOLS.md`](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/docs/TOOLS.md).
179
+ - [**`docs/TOOLS.md`**](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/docs/TOOLS.md) — complete catalog of all 149 tools, grouped, with one-line descriptions and required envs.
180
+ - [**`docs/GOVERNOR.md`**](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/docs/GOVERNOR.md) — external OpenZeppelin / Bravo Governor surface (Uniswap, Compound, Optimism). Family branching, fixture map, paste-able JSON examples, Tally parity harness.
181
+ - [**`docs/USAGE.md`**](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/docs/USAGE.md) — 10 worked examples (deploy DAO, create/vote/execute proposals, delegate, validator chamber, decode calldata, off-chain proposals, multicall batching). Copy-pasteable JSON.
182
+ - [**`docs/ENVIRONMENT.md`**](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/docs/ENVIRONMENT.md) — env-var reference: minimum block to get started, per-category requirements, calldata vs signer mode, chain config, IPFS gateway rationale, subgraph migration, swarm-harness envs, common pitfalls.
183
+ - [**`docs/OTC.md`**](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/docs/OTC.md) multi-tier OTC sale flows (project-owner and buyer paths).
184
+ - [**`docs/SIMULATOR.md`**](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/docs/SIMULATOR.md) — `eth_call`-based preflight with revert-reason decoding.
185
+ - [**`docs/INBOX.md`**](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/docs/INBOX.md) cross-DAO inbox and proposal forecast.
186
+
187
+ ---
188
+
189
+ ## Tool catalog
190
+
191
+ **149 tools, 18 groups.** Run `dexe_proposal_catalog` at runtime for the live proposal-type map. Full per-tool reference → [`docs/TOOLS.md`](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/docs/TOOLS.md).
192
+
193
+ | Group | # | What it gives you |
194
+ |-------|---|------|
195
+ | **Dev tooling** | 4 | One-command Hardhat lifecycle for the DeXe-Protocol monorepo — `dexe_compile`, `_test`, `_coverage`, `_lint`. Auto-clones the repo on first call. |
196
+ | **Contract introspection** | 10 | Ask the protocol about itself list contracts, fetch ABIs, look up selectors, read NatSpec, view source, decode arbitrary calldata or full proposal payloads. The agent's reverse-engineer toolkit. |
197
+ | **DAO reads** | 19 | Everything you'd see on a DAO dashboard, returned as JSON — `dao_info`, predicted helper addresses, proposal state/list/voters, voting power, treasury, settings, validators, staking, distributions, privacy policy. |
198
+ | **IPFS** | 9 | Pinata uploads for files / avatars / DAO + proposal metadata, smart metadata updates, deterministic identicon generation, gateway-fallback fetch, CID computation without uploading. |
199
+ | **DAO deploy** | 1 | `dexe_dao_build_deploy` — encodes the full nested `PoolFactory.deployGovPool` struct with predicted helper addresses pre-wired. From idea to a live DAO in one signed tx. |
200
+ | **Proposal catalog + primitives** | 5 | `dexe_proposal_catalog` enumerates **all 33** proposal types with metadata + gating. Primitives `_build_external`, `_build_internal`, `_build_custom_abi`, `_build_offchain` cover anything not in a named wrapper. |
201
+ | **External proposal wrappers** | 20 | Named builders for every common action: token transfer / distribution / sale (single + multi-tier), treasury withdraw, validators, experts, staking tier, math model, blacklist, reward multiplier, apply to DAO, modify profile, change voting settings, new proposal type, whitelist, and more. |
202
+ | **Internal validator wrappers** | 4 | Validator-chamber proposals: `_change_validator_balances`, `_change_validator_settings`, `_monthly_withdraw`, `_offchain_internal_proposal`. |
203
+ | **Off-chain backend** | 8 | Full DeXe-backend integration — nonce + SIWE login, off-chain proposal creation (single-option / multi-option / for-against / settings), off-chain vote + cancel. |
204
+ | **Vote / stake / delegate / execute / claim** | 26 | Every direct EOA write on `GovPool` and `Validators` — deposit, vote, delegate, undelegate, execute, claim rewards, micropool rewards, staking flows, token-sale buy/claim/vesting, distribution claim, NFT multiplier lock/unlock, privacy policy signing, multicall. |
205
+ | **Composite signing flows** | 5 | High-level flows for power users: `_proposal_create`, `_proposal_vote_and_execute`, `_tx_send`, `_tx_status`, `_get_config`. Signing tools opt-in via `DEXE_PRIVATE_KEY`. |
206
+ | **Subgraph reads** | 7 | The Graph queries: DAO list, members, experts, validator list, user activity, delegation map, OTC sale tiers. Decentralized-network endpoints + RPC fallback. |
207
+ | **Merkle utility** | 2 | `dexe_merkle_build`, `dexe_merkle_proof` — OZ `StandardMerkleTree`-compatible. For whitelisted sales and airdrops. |
208
+ | **OTC composites** | 4 | Full project-owner + buyer flows over `TokenSaleProposal`: open multi-tier sale, check buyer status, buy native or with merkle proof, claim vested payouts. See [`docs/OTC.md`](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/docs/OTC.md). |
209
+ | **Safe multisig** | 2 | Queue a tx in the Safe Transaction Service for owners to co-sign instead of broadcasting — `dexe_safe_info` (on-chain nonce/threshold/owners + endpoint), `dexe_safe_propose_tx` (compute `safeTxHash`, sign as owner, POST to the queue; dry-run by default). See [`docs/SAFE.md`](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/docs/SAFE.md). |
210
+ | **Simulator** | 3 | `eth_call`-based preflight with decoded revert reasons — `_sim_calldata`, `_sim_proposal`, `_sim_buy`. Catch reverts before you pay gas. See [`docs/SIMULATOR.md`](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/docs/SIMULATOR.md). |
211
+ | **Multi-DAO inbox + forecast** | 2 | `dexe_user_inbox` aggregates pending items (unvoted proposals, claimable rewards, locked deposits) across N DAOs. `_proposal_forecast` predicts pass rate with quorum projection + risk flags. See [`docs/INBOX.md`](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/docs/INBOX.md). |
212
+ | **External Governor DAOs** | 18 | `dexe_gov_*` — read, build, simulate, and decode against OpenZeppelin Governor + Compound Bravo DAOs. Tier-1: Uniswap, Compound, Optimism. Config-only addition for new DAOs. Family-aware (OZ vs Bravo) propose / castVote / queue / execute / cancel / delegate. Eth-call dry-run + vote-impact projection. hasVoted + state + hashProposal + decode + descriptionHash utilities. Tally state-enum parity harness. See [`docs/GOVERNOR.md`](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/docs/GOVERNOR.md). |
213
+
214
+ ---
144
215
 
145
216
  ## Swarm test harness
146
217
 
147
- `tests/swarm/` is a multi-agent DAO testing harness that exercises every dexe-mcp
148
- tool against real BSC-testnet DAOs. Scenarios are JSON specs; the orchestrator
149
- loads them, resolves agent wallets, and runs each step through either an inline
150
- ethers dispatcher or the dexe-mcp stdio bridge.
151
-
152
- **57 scenarios shipped** covering:
153
-
154
- - Reset + delegation chains (S00, S01, S06, S14)
155
- - Validator chamber pass / veto / full lifecycle (S02, S03, S07)
156
- - Read-only snapshots: expert state, participation, validators, cross-DAO,
157
- catalog, multi-proposal state, user activity (S04, S05, S09, S10, S11, S13, S15)
158
- - Cancel-vote, decode-and-introspect (S08, S12)
159
- - Build-only sanity for every proposal type in `dexe_proposal_catalog`
160
- (token transfer, blacklist, withdraw treasury, apply to dao, token
161
- distribution, token sale + recover, manage validators, change validator
162
- balances/settings, monthly withdraw, add/remove expert (local + global),
163
- delegate/revoke from expert, reward multiplier (4 modes), change voting
164
- settings, new proposal type, change math model, custom ABI, manual calldata,
165
- create staking tier, off-chain validator + for/against + settings) (S16–S40)
166
- - OTC multi-tier sale flows: open sale, buyer buy native + merkle (S41–S46)
167
- - Simulator + inbox + per-DAO reads (S47, S48, S50, S51)
168
- - **Broadcast lifecycle for the v0.5.6 builder rewrites: `withdraw_treasury`,
169
- `apply_to_dao`, `reward_multiplier mint` (S52–S54)**
170
- - **Broadcast lifecycle for the most-used proposal types: `token_transfer`,
171
- `blacklist`, `add_expert` (S55–S57)**
218
+ [`tests/swarm/`](https://github.com/edward-arinin-web-dev/dexe-mcp/tree/main/tests/swarm) is a multi-agent DAO testing harness that runs every `dexe-mcp` tool against real BSC-testnet DAOs. Scenarios are JSON specs; the orchestrator resolves agent wallets and runs each step through either an inline ethers dispatcher or the dexe-mcp stdio bridge.
219
+
220
+ It's also a reference implementation of one of the futures we described above — **adversarial AI agents stress-testing a DAO before it ships.**
221
+
222
+ **57 scenarios shipped.** Coverage:
223
+
224
+ - **Reset + delegation chains** — S00, S01, S06, S14
225
+ - **Validator chamber** pass / veto / full lifecycle (S02, S03, S07)
226
+ - **Read-only snapshots** expert state, participation, validators, cross-DAO, catalog, multi-proposal state, user activity (S04, S05, S09–S15)
227
+ - **Cancel-vote + decode-and-introspect** S08, S12
228
+ - **Build-only sanity for every proposal type** in `dexe_proposal_catalog` — token transfer, blacklist, withdraw treasury, apply to DAO, token distribution, token sale + recover, manage validators, change validator balances/settings, monthly withdraw, add/remove expert (local + global), delegate/revoke from expert, reward multiplier (4 modes), change voting settings, new proposal type, change math model, custom ABI, manual calldata, create staking tier, off-chain validator + for/against + settings (S16–S40)
229
+ - **OTC multi-tier sale flows** — open sale, buyer buy native + merkle (S41–S46)
230
+ - **Simulator + inbox + per-DAO reads** S47, S48, S50, S51
231
+ - **Broadcast lifecycle (v0.5.6 builder rewrites)** `withdraw_treasury`, `apply_to_dao`, `reward_multiplier mint` (S52–S54)
232
+ - **Broadcast lifecycle (most-used proposal types)** `token_transfer`, `blacklist`, `add_expert` (S55–S57)
172
233
 
173
234
  ```bash
174
235
  # 1) generate 9 wallets (8 agents + funder), fund the funder from your wallet
175
236
  # 2) deploy fixture DAOs via dexe_dao_build_deploy (one 50% quorum + one with validators)
176
237
  # 3) configure SWARM_DAOS_TESTNET / SWARM_TOKENS_TESTNET / SWARM_RPC_URL_TESTNET
238
+
177
239
  npm run swarm:preflight # red/green table per wallet
178
240
  npm run swarm:fund -- --confirm # broadcast top-ups from funder
179
241
  npm run swarm:run # full sweep, all scenarios
180
242
  npm run swarm:run -- --scenarios=S00-reset,S01-delegation-chain-3hop --dry-run
181
243
  ```
182
244
 
183
- Setup runbook: [`tests/swarm/README.md`](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/tests/swarm/README.md).
184
- Scenario schema: [`tests/swarm/scenarios/_schema.md`](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/tests/swarm/scenarios/_schema.md).
185
- Per-role agent prompts: `tests/swarm/prompts/`.
245
+ - Setup runbook [`tests/swarm/README.md`](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/tests/swarm/README.md)
246
+ - Scenario schema [`tests/swarm/scenarios/_schema.md`](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/tests/swarm/scenarios/_schema.md)
247
+ - Per-role agent prompts → [`tests/swarm/prompts/`](https://github.com/edward-arinin-web-dev/dexe-mcp/tree/main/tests/swarm/prompts)
248
+
249
+ ---
186
250
 
187
251
  ## Contributing
188
252
 
@@ -195,6 +259,31 @@ npm run typecheck
195
259
  npm run dev # watch mode
196
260
  ```
197
261
 
262
+ Issues, PRs, and proposal-type requests welcome → [GitHub issues](https://github.com/edward-arinin-web-dev/dexe-mcp/issues).
263
+
264
+ ## Security
265
+
266
+ Supply-chain hardening is enforced in CI. See [SECURITY.md](SECURITY.md) for the full policy, threat model, and how to report a vulnerability. Highlights:
267
+
268
+ - **Signed release tags.** Every release tag is GPG-signed and `release.yml` runs `git verify-tag` before publishing — an unsigned or untrusted tag aborts the release. Verify any tag yourself after cloning:
269
+
270
+ ```bash
271
+ gpg --recv-keys <MAINTAINER_KEY_ID> # import maintainer key once
272
+ git verify-tag v0.5.9 # or the shorthand: git tag -v v0.5.9
273
+ ```
274
+
275
+ A `Good signature` line is the only acceptable result; `no signature found` or `No public key` means do not trust the tag.
276
+ - **npm provenance.** Releases publish with `npm publish --provenance`; verify with `npm audit signatures` against an installed copy.
277
+ - **Reproducible installs.** A `verify-lockfile` CI job installs strictly from the committed `package-lock.json` and fails on any drift.
278
+ - **Continuous scanning.** CodeQL (SAST) runs on every PR and weekly; OSSF Scorecard runs weekly and on push to `main`; Dependency Review runs on every PR.
279
+
198
280
  ## License
199
281
 
200
282
  MIT. See [LICENSE](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/LICENSE).
283
+
284
+ ---
285
+
286
+ <p align="center">
287
+ <b>The runtime for autonomous DAOs.</b><br/>
288
+ <sub>Built for the DeXe Protocol governance stack on BNB Chain. Not affiliated with DeXe Network — independent open-source integration.</sub>
289
+ </p>
package/SECURITY.md ADDED
@@ -0,0 +1,96 @@
1
+ # Security Policy
2
+
3
+ ## Supported Versions
4
+
5
+ Only the latest published version on npm receives security updates. Pin to the latest minor (`^0.5`) in your MCP client config.
6
+
7
+ ## Automated security checks
8
+
9
+ The repo runs four GitHub Actions security workflows continuously:
10
+
11
+ - **CI** (`ci.yml`) — typecheck and build on every push to `main` and every pull request, against Node 20 and 22, plus a `verify-lockfile` integrity job. The test step (`vitest`) runs whenever test files are present on the branch; it is currently a no-op via `--passWithNoTests` (the suite lives on `governor-adapter`) and becomes an enforcing gate once those tests merge. Read-only `GITHUB_TOKEN` scope.
12
+ - **Dependency Review** (`dependency-review.yml`) — every PR is checked against the GitHub Advisory Database. Fails the PR check if any added/updated dependency carries a `high` or `critical` CVE, or if it introduces a forbidden license (GPL/AGPL).
13
+ - **OSSF Scorecard** (`scorecard.yml`) — weekly + on push to `main`. Audits branch protection, signed releases, pinned dependencies, token permissions, and a dozen other supply-chain checks. Results uploaded to GitHub code-scanning (SARIF) and published as a public score at `https://api.securityscorecards.dev/projects/github.com/edward-arinin-web-dev/dexe-mcp/badge`.
14
+ - **CodeQL** (`codeql.yml`) — GitHub-native SAST with the `security-extended` query suite. Runs on every PR/main push and weekly. Scans for prototype pollution, command injection, ReDoS, unsafe deserialization, path traversal, and other CWE patterns. Findings land in the repo's Security tab.
15
+
16
+ ## Release provenance
17
+
18
+ Every npm release from `v0.5.9` onwards is published via `.github/workflows/release.yml` with `npm publish --provenance`. The signed attestation links the tarball to the exact git commit and GitHub Actions run that produced it. Verify in three ways:
19
+
20
+ - The npmjs.com page for the package shows a "Provenance" badge with the source repo and workflow run.
21
+ - `npm view dexe-mcp dist.signatures` returns Sigstore signatures.
22
+ - `npm audit signatures` against an installed copy fails if the registry tarball was tampered with.
23
+
24
+ If you ever install a `dexe-mcp` version that lacks a provenance attestation (and is not a pre-`v0.5.9` historical release), treat it as suspect and report.
25
+
26
+ ## Signed release tags
27
+
28
+ Every release tag is GPG-signed by the maintainer, and `release.yml` runs `git verify-tag "$GITHUB_REF_NAME"` **before** the publish step — an unsigned tag, an invalid signature, or a tag signed by an unknown key aborts the release, so a pushed tag can never publish to npm without a valid maintainer signature.
29
+
30
+ To verify a tag yourself after cloning the repo:
31
+
32
+ ```bash
33
+ # Import the maintainer's public key once (key id published alongside releases).
34
+ gpg --recv-keys <MAINTAINER_KEY_ID>
35
+
36
+ # Verify a specific tag — exits non-zero if unsigned or signed by an unknown key.
37
+ git verify-tag v0.5.9
38
+ # Equivalent shorthand:
39
+ git tag -v v0.5.9
40
+ ```
41
+
42
+ A clean `gpg: Good signature from "<maintainer>"` line is the only acceptable result. `error: ... no signature found` (unsigned) or `Can't check signature: No public key` (unknown signer) means do not trust the tag.
43
+
44
+ ## Reporting a Vulnerability
45
+
46
+ If you find a vulnerability in `dexe-mcp` — whether in the calldata builders, the optional signer (`DEXE_PRIVATE_KEY`), IPFS upload paths, or the Hardhat bridge — please **do not** open a public GitHub issue.
47
+
48
+ Email: **edward.arinin@gmail.com**
49
+
50
+ Include:
51
+
52
+ - A description of the issue and its impact (what an attacker can do, under what conditions).
53
+ - A minimal reproduction: the tool call, env vars (redacted), and the resulting behavior.
54
+ - Affected version (`dexe-mcp --version` or check `package.json`).
55
+ - Suggested mitigation, if you have one.
56
+
57
+ You should expect an acknowledgement within 72 hours. A coordinated-disclosure timeline will be agreed before any public advisory is filed.
58
+
59
+ ## Scope
60
+
61
+ In scope:
62
+
63
+ - Calldata-builder tools (`dexe_proposal_build_*`, `dexe_vote_build_*`, `dexe_dao_build_deploy`) that produce calldata that does not match the intended action.
64
+ - Signer mode (`dexe_tx_send`, auto-broadcast in `dexe_proposal_create` / `dexe_proposal_vote_and_execute`) leaking or misusing the configured private key.
65
+ - IPFS upload paths that exfiltrate non-public data or accept unsafe input.
66
+ - Hardhat bridge (`dexe_compile`, `dexe_test`, etc.) executing unintended shell commands.
67
+ - Dependency vulnerabilities reachable through `dexe-mcp`'s exposed tool surface.
68
+
69
+ Out of scope:
70
+
71
+ - Vulnerabilities in the on-chain DeXe Protocol contracts (report at <https://github.com/dexe-network>).
72
+ - Issues that require the operator to set obviously unsafe env values (e.g. `DEXE_PRIVATE_KEY=<a key the attacker already controls>`).
73
+ - General npm-registry / npm-cli / Node.js issues unrelated to this package.
74
+
75
+ ## Threat Model
76
+
77
+ `dexe-mcp` runs **locally** alongside an MCP client (Claude Desktop, Claude Code, etc.). It does not bind a network port and does not expose itself to the public internet. The interesting attack surfaces are:
78
+
79
+ 1. The operator's private key in signer mode — never logged, never sent off-host, only used by `ethers.Wallet` to sign payloads the operator has already approved at the agent level.
80
+ 2. Calldata correctness — every `_build_*` tool emits a `TxPayload` the operator can decode (`dexe_decode_calldata`, `dexe_decode_proposal`) and sign-verify before broadcasting.
81
+ 3. IPFS pinning credentials — keep `PINATA_JWT` scoped to a project-specific key.
82
+
83
+ If you believe any of the above is broken, please report per the process above.
84
+
85
+ ## Signer broadcast guards
86
+
87
+ When signer mode is enabled (`DEXE_PRIVATE_KEY`), `dexe_tx_send` runs four opt-in guards before broadcasting (`src/lib/broadcastGuards.ts`). They narrow the blast radius of a compromised or runaway MCP host — the host can still *call* the tool, but cannot send to arbitrary destinations, drain arbitrary value, pay gas for reverting txs, or loop unbounded. Each is a no-op unless its env var is set; a failed guard returns `{ status: "rejected", guard, reason }` with **no gas spent**.
88
+
89
+ | Guard | Env var | What it blocks |
90
+ |-------|---------|----------------|
91
+ | **B6** destination allowlist | `DEXE_SIGNER_ALLOWLIST` | Broadcasts to any `to` not on the comma-separated list. |
92
+ | **B7** value cap | `DEXE_SIGNER_MAX_VALUE_WEI` | Broadcasts whose `value` (wei) exceeds the cap. |
93
+ | **B9** auto-simulation | _(always on in signer mode)_ | Doomed txs — `eth_call` preflight aborts with the decoded revert reason before gas is spent. |
94
+ | **B10** rate limit | `DEXE_SIGNER_MAX_BROADCASTS_PER_MIN` | More than N broadcasts in a rolling 60s window. |
95
+
96
+ These are defense-in-depth, **not** a substitute for keeping the key off-host. For prod governance/treasury actions, prefer calldata mode + Safe Multisig / Ledger. See `docs/ENVIRONMENT.md` §4 for the recommended config block.
package/dist/config.d.ts CHANGED
@@ -34,6 +34,15 @@ export interface DexeConfig {
34
34
  forkBlock?: number;
35
35
  /** Private key for tx signing. When set, `dexe_tx_send` can broadcast. */
36
36
  privateKey?: string;
37
+ /**
38
+ * B6 — destination allowlist for `dexe_tx_send`. Lowercased, checksummed-then-
39
+ * lowercased addresses. Undefined/empty = no restriction.
40
+ */
41
+ signerAllowlist?: string[];
42
+ /** B7 — max wei value per broadcast. Undefined = no cap. */
43
+ signerMaxValueWei?: bigint;
44
+ /** B10 — max broadcasts per rolling minute. Undefined = no limit. */
45
+ signerMaxBroadcastsPerMin?: number;
37
46
  }
38
47
  /**
39
48
  * Reads environment and returns a frozen config. **Fast and side-effect-free**
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,UAAU;IACzB,mFAAmF;IACnF,YAAY,EAAE,MAAM,CAAC;IAErB,uEAAuE;IACvE,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACzC;;;;OAIG;IACH,cAAc,EAAE,MAAM,CAAC;IAEvB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8CAA8C;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,yEAAyE;IACzE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,yCAAyC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0EAA0E;IAC1E,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,UAAU,CAAC,CA4ItD;AAcD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,WAAW,CAW9E"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,UAAU;IACzB,mFAAmF;IACnF,YAAY,EAAE,MAAM,CAAC;IAErB,uEAAuE;IACvE,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACzC;;;;OAIG;IACH,cAAc,EAAE,MAAM,CAAC;IAEvB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8CAA8C;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,yEAAyE;IACzE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,yCAAyC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0EAA0E;IAC1E,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,4DAA4D;IAC5D,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,qEAAqE;IACrE,yBAAyB,CAAC,EAAE,MAAM,CAAC;CACpC;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,UAAU,CAAC,CAwMtD;AAcD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,WAAW,CAW9E"}
package/dist/config.js CHANGED
@@ -34,6 +34,20 @@ export async function loadConfig() {
34
34
  if (rpcMainnet) {
35
35
  chains.set(56, { chainId: 56, rpcUrl: rpcMainnet });
36
36
  }
37
+ // Generic per-chain RPC: DEXE_RPC_URL_<chainId> (e.g. DEXE_RPC_URL_1,
38
+ // DEXE_RPC_URL_10). Enables chains beyond BSC — notably the external
39
+ // Governor DAOs, which live on Ethereum (1) and Optimism (10). The numeric
40
+ // suffix never collides with the named *_TESTNET / *_MAINNET vars above.
41
+ for (const [key, val] of Object.entries(process.env)) {
42
+ const m = /^DEXE_RPC_URL_(\d+)$/.exec(key);
43
+ if (!m)
44
+ continue;
45
+ const url = val?.trim();
46
+ if (!url)
47
+ continue;
48
+ const cid = Number(m[1]);
49
+ chains.set(cid, { chainId: cid, rpcUrl: url });
50
+ }
37
51
  // Legacy single-chain env (still supported)
38
52
  const legacyRpc = process.env.DEXE_RPC_URL?.trim() || undefined;
39
53
  let legacyChainId;
@@ -106,6 +120,49 @@ export async function loadConfig() {
106
120
  const addr = new Wallet(privateKey).address;
107
121
  process.stderr.write(`[dexe-mcp] signing enabled for ${addr}\n`);
108
122
  }
123
+ // ---- signer broadcast guard B6 (destination allowlist) -----------------
124
+ // Opt-in; only meaningful in signer mode. Parses to undefined when unset,
125
+ // leaving the default posture unchanged.
126
+ let signerAllowlist;
127
+ const allowlistRaw = process.env.DEXE_SIGNER_ALLOWLIST?.trim();
128
+ if (allowlistRaw) {
129
+ const { isAddress, getAddress } = await import("ethers");
130
+ const normalized = [];
131
+ for (const entry of allowlistRaw.split(",").map(s => s.trim()).filter(Boolean)) {
132
+ if (!isAddress(entry)) {
133
+ fatal(`DEXE_SIGNER_ALLOWLIST contains an invalid address: ${entry}`);
134
+ }
135
+ normalized.push(getAddress(entry).toLowerCase());
136
+ }
137
+ if (normalized.length > 0)
138
+ signerAllowlist = normalized;
139
+ }
140
+ // ---- signer broadcast guard B7 (value cap) -----------------------------
141
+ let signerMaxValueWei;
142
+ const maxValueRaw = process.env.DEXE_SIGNER_MAX_VALUE_WEI?.trim();
143
+ if (maxValueRaw) {
144
+ let parsed;
145
+ try {
146
+ parsed = BigInt(maxValueRaw);
147
+ }
148
+ catch {
149
+ fatal(`DEXE_SIGNER_MAX_VALUE_WEI must be a non-negative integer (wei), got: ${maxValueRaw}`);
150
+ }
151
+ if (parsed < 0n) {
152
+ fatal(`DEXE_SIGNER_MAX_VALUE_WEI must be a non-negative integer (wei), got: ${maxValueRaw}`);
153
+ }
154
+ signerMaxValueWei = parsed;
155
+ }
156
+ // ---- signer broadcast guard B10 (rate limit) ---------------------------
157
+ let signerMaxBroadcastsPerMin;
158
+ const maxBroadcastsRaw = process.env.DEXE_SIGNER_MAX_BROADCASTS_PER_MIN?.trim();
159
+ if (maxBroadcastsRaw) {
160
+ const n = Number(maxBroadcastsRaw);
161
+ if (!Number.isInteger(n) || n <= 0) {
162
+ fatal(`DEXE_SIGNER_MAX_BROADCASTS_PER_MIN must be a positive integer, got: ${maxBroadcastsRaw}`);
163
+ }
164
+ signerMaxBroadcastsPerMin = n;
165
+ }
109
166
  let forkBlock;
110
167
  if (process.env.DEXE_FORK_BLOCK) {
111
168
  const n = Number(process.env.DEXE_FORK_BLOCK);
@@ -128,6 +185,9 @@ export async function loadConfig() {
128
185
  subgraphInteractionsUrl,
129
186
  forkBlock,
130
187
  privateKey,
188
+ signerAllowlist,
189
+ signerMaxValueWei,
190
+ signerMaxBroadcastsPerMin,
131
191
  });
132
192
  }
133
193
  /**