@noelclaw/mcp 1.4.0 → 1.5.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 +258 -238
- package/dist/index.js +1 -1
- package/dist/server.js +3 -4
- package/dist/tools/defi.js +1 -24
- package/dist/tools/insight.js +11 -25
- package/dist/tools/market.js +111 -29
- package/dist/tools/miroshark.js +1 -1
- package/dist/tools/research.js +3 -24
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,238 +1,258 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
[](https://www.npmjs.com/package/@noelclaw/mcp)
|
|
4
|
-
|
|
5
|
-
Noelclaw as an MCP skill
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
|
103
|
-
|
|
104
|
-
| `
|
|
105
|
-
| `
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
|
117
|
-
|
|
118
|
-
| `
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
|
143
|
-
|
|
144
|
-
| `
|
|
145
|
-
| `
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
|
165
|
-
|
|
166
|
-
| `
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
|
183
|
-
|
|
184
|
-
| `
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
1
|
+
# @noelclaw/mcp
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@noelclaw/mcp)
|
|
4
|
+
|
|
5
|
+
Noelclaw as an MCP skill — persistent memory, multi-agent coordination, scenario simulation, DeFi execution, and Sentinel-gated playbooks. Works with Claude, Cursor, Hermes, Windsurf, and any MCP-compatible client.
|
|
6
|
+
|
|
7
|
+
**37 tools** across market data, research, vault, swarm, MiroShark simulation, DeFi, automation, and framework.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx @noelclaw/mcp
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Quick Install
|
|
16
|
+
|
|
17
|
+
### Claude Code
|
|
18
|
+
```bash
|
|
19
|
+
claude mcp add noelclaw -e NOELCLAW_API_KEY=noel_... -- npx @noelclaw/mcp
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### Claude Desktop
|
|
23
|
+
Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (Mac) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
|
|
24
|
+
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"mcpServers": {
|
|
28
|
+
"noelclaw": {
|
|
29
|
+
"command": "npx",
|
|
30
|
+
"args": ["@noelclaw/mcp"],
|
|
31
|
+
"env": {
|
|
32
|
+
"NOELCLAW_API_KEY": "noel_..."
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Cursor / Windsurf
|
|
40
|
+
```json
|
|
41
|
+
{
|
|
42
|
+
"mcpServers": {
|
|
43
|
+
"noelclaw": {
|
|
44
|
+
"command": "npx",
|
|
45
|
+
"args": ["@noelclaw/mcp"],
|
|
46
|
+
"env": {
|
|
47
|
+
"NOELCLAW_API_KEY": "noel_..."
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Hermes
|
|
55
|
+
```yaml
|
|
56
|
+
mcp_servers:
|
|
57
|
+
noelclaw:
|
|
58
|
+
command: npx
|
|
59
|
+
args:
|
|
60
|
+
- "@noelclaw/mcp"
|
|
61
|
+
env:
|
|
62
|
+
NOELCLAW_API_KEY: "noel_..."
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Authentication
|
|
68
|
+
|
|
69
|
+
Get a key instantly — no signup:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
curl -X POST https://api.noelclaw.com/auth/key
|
|
73
|
+
# → { "apiKey": "noel_..." }
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Set `NOELCLAW_API_KEY` in your MCP config. That's it.
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Tools
|
|
81
|
+
|
|
82
|
+
### Market Data
|
|
83
|
+
|
|
84
|
+
| Tool | Description |
|
|
85
|
+
|------|-------------|
|
|
86
|
+
| `get_market_data` | Live prices for BTC, ETH, SOL — sourced from CoinGecko via swarm. Pass a token symbol to focus |
|
|
87
|
+
| `get_token_data` | Price, 24h change, market cap, and volume for any specific token |
|
|
88
|
+
|
|
89
|
+
### Research & AI
|
|
90
|
+
|
|
91
|
+
| Tool | Description |
|
|
92
|
+
|------|-------------|
|
|
93
|
+
| `research` | Deep research via Bankr (real-time). Returns overview, key findings, market impact, sentiment |
|
|
94
|
+
| `get_insight` | Noel's daily crypto + macro insight — price action, narratives, on-chain signals, one takeaway |
|
|
95
|
+
| `ask_noel` | Ask Noel AI for DeFi analysis, trade ideas, and market research with live context |
|
|
96
|
+
| `humanize_text` | Remove AI tells from text — fixes 29 AI patterns, makes output sound natural. Powered by MiniMax-M2.7. Requires `MINIMAX_API_KEY` |
|
|
97
|
+
|
|
98
|
+
### Noel-Vault
|
|
99
|
+
|
|
100
|
+
> Persistent memory across sessions. Save findings, recall by key, search full-text. Every save auto-versions.
|
|
101
|
+
|
|
102
|
+
| Tool | Description |
|
|
103
|
+
|------|-------------|
|
|
104
|
+
| `vault_save` | Save any content — research, execution logs, workflows, prompts, files, memory |
|
|
105
|
+
| `vault_read` | Read an entry by key |
|
|
106
|
+
| `vault_list` | List all entries with type, title, version, last updated |
|
|
107
|
+
| `vault_search` | Full-text search across all content |
|
|
108
|
+
| `vault_history` | Version history with commit messages |
|
|
109
|
+
| `vault_diff` | Line-by-line diff between two versions |
|
|
110
|
+
| `vault_export` | Export full vault or filter by type |
|
|
111
|
+
|
|
112
|
+
### Noel-Swarm
|
|
113
|
+
|
|
114
|
+
> Shared memory bus for multi-agent coordination. All agents read/write the same store with freshness tracking and execution scoring.
|
|
115
|
+
|
|
116
|
+
| Tool | Description |
|
|
117
|
+
|------|-------------|
|
|
118
|
+
| `start_swarm` | Start a swarm session |
|
|
119
|
+
| `stop_swarm` | Stop the active session |
|
|
120
|
+
| `get_swarm_status` | Session state, memory snapshot, execution scores |
|
|
121
|
+
| `write_swarm_memory` | Write a key-value entry with optional TTL. Use `market/*` / `dex/*` keys for live CoinGecko / DexScreener data |
|
|
122
|
+
| `get_swarm_memory` | Read by key — returns value + freshness metadata |
|
|
123
|
+
| `get_execution_scores` | Per-agent, per-skill performance scores |
|
|
124
|
+
|
|
125
|
+
### MiroShark
|
|
126
|
+
|
|
127
|
+
> Multi-agent scenario simulation — describe any scenario in plain English, get back a full simulation with AI agents acting as market participants, analysts, and social actors.
|
|
128
|
+
|
|
129
|
+
| Tool | Description |
|
|
130
|
+
|------|-------------|
|
|
131
|
+
| `miroshark_simulate` | Run a simulation from a plain-English scenario. Handles full setup automatically (knowledge graph, 42+ agents). Returns a simulation ID |
|
|
132
|
+
| `miroshark_status` | Poll progress — surfaces agent actions, round count, consensus when complete |
|
|
133
|
+
|
|
134
|
+
No extra env vars needed. MiroShark is hosted on Noelclaw's infrastructure.
|
|
135
|
+
|
|
136
|
+
### Wallet & DeFi `beta`
|
|
137
|
+
|
|
138
|
+
> On-chain operations on Base mainnet. Transactions are signed client-side — no private key ever leaves your machine.
|
|
139
|
+
|
|
140
|
+
| Tool | Description |
|
|
141
|
+
|------|-------------|
|
|
142
|
+
| `get_wallet_address` | Show your local MCP wallet address |
|
|
143
|
+
| `swap_tokens` | Swap tokens on Base mainnet via 0x Permit2 (ETH, USDC, USDT, DAI, WETH) |
|
|
144
|
+
| `send_token` | Send ETH or any ERC-20 to any address |
|
|
145
|
+
| `claim_fees` | Claim accumulated ETH from Flaunch token swap fees |
|
|
146
|
+
|
|
147
|
+
### Automations `beta`
|
|
148
|
+
|
|
149
|
+
| Tool | Description |
|
|
150
|
+
|------|-------------|
|
|
151
|
+
| `create_automation` | Create an automation in plain English — DCA, price alerts, conditional buys/sells |
|
|
152
|
+
| `list_automations` | List all automations with status and next scheduled run |
|
|
153
|
+
| `pause_automation` | Pause or resume an automation |
|
|
154
|
+
| `delete_automation` | Permanently delete an automation |
|
|
155
|
+
|
|
156
|
+
### Noel Framework `beta`
|
|
157
|
+
|
|
158
|
+
> Sentinel-gated agent execution. Every action checked against 5 mechanical rules before it runs.
|
|
159
|
+
|
|
160
|
+
| Tool | Description |
|
|
161
|
+
|------|-------------|
|
|
162
|
+
| `create_task_packet` | Convert plain-English intent into a structured task scope with permissions and constraints |
|
|
163
|
+
| `list_task_packets` | List all task packets |
|
|
164
|
+
| `list_playbooks` | List available playbooks |
|
|
165
|
+
| `run_playbook` | Execute a Sentinel-gated playbook — halts if any step is blocked |
|
|
166
|
+
| `get_noel_ledger` | Full audit trail of every Sentinel decision |
|
|
167
|
+
| `get_sentinel_rules` | Exact rules per agent role |
|
|
168
|
+
|
|
169
|
+
### Social
|
|
170
|
+
|
|
171
|
+
| Tool | Description |
|
|
172
|
+
|------|-------------|
|
|
173
|
+
| `post_tweet` | Post a tweet. Requires `TWITTER_BEARER_TOKEN` or delegated via Noelclaw |
|
|
174
|
+
| `set_telegram` | Connect Telegram for push notifications from market and swarm events |
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## Environment Variables
|
|
179
|
+
|
|
180
|
+
### Required
|
|
181
|
+
|
|
182
|
+
| Var | Description |
|
|
183
|
+
|-----|-------------|
|
|
184
|
+
| `NOELCLAW_API_KEY` | Your API key (`noel_...`) — get one at `POST https://api.noelclaw.com/auth/key` |
|
|
185
|
+
|
|
186
|
+
### Optional
|
|
187
|
+
|
|
188
|
+
| Var | Used for |
|
|
189
|
+
|-----|---------|
|
|
190
|
+
| `MINIMAX_API_KEY` | `humanize_text` tool — powered by MiniMax-M2.7 |
|
|
191
|
+
| `BANKR_API_KEY` | `research` tool — Bankr Agent deep research |
|
|
192
|
+
| `TELEGRAM_BOT_TOKEN` | Your own Telegram bot for notifications |
|
|
193
|
+
| `TELEGRAM_CHAT_ID` | Your Telegram chat ID |
|
|
194
|
+
| `ALCHEMY_API_KEY` | Faster Base RPC for swaps |
|
|
195
|
+
| `GROK_API_KEY` | Grok integration via BYOK |
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## Usage Examples
|
|
200
|
+
|
|
201
|
+
```
|
|
202
|
+
# Live market data
|
|
203
|
+
get_market_data() # BTC, ETH, SOL prices
|
|
204
|
+
get_token_data(question: "What is the price of HYPE?")
|
|
205
|
+
|
|
206
|
+
# Research
|
|
207
|
+
research(query: "What is happening with the Base ecosystem this week?")
|
|
208
|
+
get_insight()
|
|
209
|
+
ask_noel(question: "What are the risks of holding ETH through a Fed meeting?")
|
|
210
|
+
|
|
211
|
+
# Humanize AI-generated text
|
|
212
|
+
humanize_text(text: "In today's rapidly evolving landscape, it is worth noting...")
|
|
213
|
+
|
|
214
|
+
# Save findings to vault
|
|
215
|
+
vault_save(type: "research", key: "research/base-may-2026", title: "Base Ecosystem", content: "...")
|
|
216
|
+
vault_search(query: "Base ecosystem")
|
|
217
|
+
vault_history(key: "research/base-may-2026")
|
|
218
|
+
|
|
219
|
+
# Coordinate agents via swarm
|
|
220
|
+
start_swarm()
|
|
221
|
+
write_swarm_memory(agentId: "analyst", key: "research/btc", value: "bullish", ttlSeconds: 3600)
|
|
222
|
+
get_swarm_memory(key: "market/BTC") # real-time CoinGecko price
|
|
223
|
+
get_swarm_memory(key: "dex/PEPE") # real-time DexScreener data
|
|
224
|
+
|
|
225
|
+
# Run a MiroShark simulation
|
|
226
|
+
miroshark_simulate(scenario: "What happens if the US passes a Bitcoin strategic reserve bill?")
|
|
227
|
+
miroshark_status(simulation_id: "sim_abc123")
|
|
228
|
+
|
|
229
|
+
# DeFi (beta)
|
|
230
|
+
swap_tokens(fromToken: "ETH", toToken: "USDC", amount: "0.01")
|
|
231
|
+
send_token(token: "USDC", toAddress: "0x...", amount: "10")
|
|
232
|
+
claim_fees()
|
|
233
|
+
|
|
234
|
+
# Sentinel-gated execution (beta)
|
|
235
|
+
create_task_packet(task: "Monitor portfolio, max $0 spend, read only")
|
|
236
|
+
run_playbook(playbook_name: "Daily Market Scan")
|
|
237
|
+
get_noel_ledger()
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## Troubleshooting
|
|
243
|
+
|
|
244
|
+
| Error | Fix |
|
|
245
|
+
|-------|-----|
|
|
246
|
+
| Tools not appearing | Restart your MCP client after adding the config |
|
|
247
|
+
| `401 Unauthorized` | Check `NOELCLAW_API_KEY` is set — get one at `POST https://api.noelclaw.com/auth/key` |
|
|
248
|
+
| `humanize_text` fails | Set `MINIMAX_API_KEY` in your MCP env config |
|
|
249
|
+
| `research` fails | Set `BANKR_API_KEY` — Bankr access required for deep research |
|
|
250
|
+
| Server starts but no response | Expected — server waits for MCP stdin, not HTTP |
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## Links
|
|
255
|
+
|
|
256
|
+
- npm: [npmjs.com/package/@noelclaw/mcp](https://npmjs.com/package/@noelclaw/mcp)
|
|
257
|
+
- GitHub: [github.com/noelclaw/mcp](https://github.com/noelclaw/mcp)
|
|
258
|
+
- Platform: [noelclaw.com](https://noelclaw.com)
|
package/dist/index.js
CHANGED
|
@@ -19,7 +19,7 @@ async function main() {
|
|
|
19
19
|
try {
|
|
20
20
|
const wallet = await (0, wallet_js_1.getOrCreateWallet)();
|
|
21
21
|
console.error(`\x1b[36m ◆ wallet\x1b[0m ${wallet.address}`);
|
|
22
|
-
console.error(`\x1b[36m ◆ status\x1b[0m ready ·
|
|
22
|
+
console.error(`\x1b[36m ◆ status\x1b[0m ready · 34 tools loaded\n`);
|
|
23
23
|
}
|
|
24
24
|
catch (err) {
|
|
25
25
|
console.error(`[noelclaw] wallet init failed: ${err}`);
|
package/dist/server.js
CHANGED
|
@@ -34,9 +34,8 @@ function containsSensitiveRequest(args) {
|
|
|
34
34
|
}
|
|
35
35
|
exports.ALL_TOOLS = [
|
|
36
36
|
...market_js_1.MARKET_TOOLS, // 2 — market data, token data
|
|
37
|
-
...
|
|
38
|
-
...
|
|
39
|
-
...defi_js_1.DEFI_TOOLS, // 3 — swap, send, claim
|
|
37
|
+
...insight_js_1.INSIGHT_TOOLS, // 1 — ask_noel
|
|
38
|
+
...defi_js_1.DEFI_TOOLS, // 2 — swap, send
|
|
40
39
|
...automation_js_1.AUTOMATION_TOOLS, // 4 — create, list, pause, delete
|
|
41
40
|
...swarm_js_1.SWARM_TOOLS, // 6 — start, stop, status, memory, scores
|
|
42
41
|
...framework_js_1.FRAMEWORK_TOOLS, // 6 — task packets, playbooks, sentinel, ledger
|
|
@@ -45,7 +44,7 @@ exports.ALL_TOOLS = [
|
|
|
45
44
|
...twitter_js_1.TWITTER_TOOLS, // 1 — post tweet
|
|
46
45
|
...miroshark_js_1.MIROSHARK_TOOLS, // 2 — simulate, status
|
|
47
46
|
...humanizer_js_1.HUMANIZER_TOOLS, // 1 — humanize_text
|
|
48
|
-
// total:
|
|
47
|
+
// total: 34
|
|
49
48
|
];
|
|
50
49
|
exports.server = new index_js_1.Server({ name: "noelclaw", version: "2.1.0" }, { capabilities: { tools: {} } });
|
|
51
50
|
exports.server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({ tools: exports.ALL_TOOLS }));
|
package/dist/tools/defi.js
CHANGED
|
@@ -32,15 +32,6 @@ exports.DEFI_TOOLS = [
|
|
|
32
32
|
required: ["token", "toAddress", "amount"],
|
|
33
33
|
},
|
|
34
34
|
},
|
|
35
|
-
{
|
|
36
|
-
name: "claim_fees",
|
|
37
|
-
description: "Claim accumulated ETH from your Flaunch token swap fees. Calls claim() on the Flaunch PositionManager — pulls all pending ETH from your deployed tokens to your wallet.",
|
|
38
|
-
inputSchema: {
|
|
39
|
-
type: "object",
|
|
40
|
-
properties: {},
|
|
41
|
-
required: [],
|
|
42
|
-
},
|
|
43
|
-
},
|
|
44
35
|
];
|
|
45
36
|
const SwapSchema = zod_1.z.object({ fromToken: zod_1.z.string().min(1), toToken: zod_1.z.string().min(1), amount: zod_1.z.string().min(1) });
|
|
46
37
|
const SendSchema = zod_1.z.object({ token: zod_1.z.string().min(1), toAddress: zod_1.z.string().regex(/^0x[0-9a-fA-F]{40}$/, "must be a valid 0x address"), amount: zod_1.z.string().min(1) });
|
|
@@ -50,7 +41,7 @@ async function handleDefiTool(name, args) {
|
|
|
50
41
|
const parsed = SwapSchema.safeParse(args);
|
|
51
42
|
if (!parsed.success)
|
|
52
43
|
return { content: [{ type: "text", text: `Invalid input: ${String(parsed.error.issues[0].path[0])} ${parsed.error.issues[0].message}` }], isError: true };
|
|
53
|
-
|
|
44
|
+
const { fromToken, toToken, amount } = parsed.data;
|
|
54
45
|
const wallet = await (0, wallet_js_1.getOrCreateWallet)();
|
|
55
46
|
const result = await (0, convex_js_1.callConvex)("/mcp/defi/swap", "POST", { fromToken, toToken, amount }, "swap_tokens");
|
|
56
47
|
if (!result.success)
|
|
@@ -74,7 +65,6 @@ async function handleDefiTool(name, args) {
|
|
|
74
65
|
if (!result.success)
|
|
75
66
|
return { content: [{ type: "text", text: `Send failed: ${result.error}` }], isError: true };
|
|
76
67
|
const txHash = await (0, wallet_js_1.signAndBroadcast)(wallet, result.txData);
|
|
77
|
-
// Collect 0.5% platform fee as a separate tx if the server returned fee data
|
|
78
68
|
if (result.feeTxData) {
|
|
79
69
|
try {
|
|
80
70
|
await (0, wallet_js_1.signAndBroadcast)(wallet, result.feeTxData);
|
|
@@ -88,19 +78,6 @@ async function handleDefiTool(name, args) {
|
|
|
88
78
|
}],
|
|
89
79
|
};
|
|
90
80
|
}
|
|
91
|
-
case "claim_fees": {
|
|
92
|
-
const wallet = await (0, wallet_js_1.getOrCreateWallet)();
|
|
93
|
-
const result = await (0, convex_js_1.callConvex)("/mcp/token/claim", "POST", {}, "claim_fees");
|
|
94
|
-
if (result.error)
|
|
95
|
-
return { content: [{ type: "text", text: `Claim failed: ${result.error}` }], isError: true };
|
|
96
|
-
const txHash = await (0, wallet_js_1.signAndBroadcast)(wallet, result);
|
|
97
|
-
return {
|
|
98
|
-
content: [{
|
|
99
|
-
type: "text",
|
|
100
|
-
text: [`✅ ETH claimed successfully!`, `Tx Hash: \`${txHash}\``, `https://basescan.org/tx/${txHash}`].join("\n"),
|
|
101
|
-
}],
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
81
|
default:
|
|
105
82
|
return null;
|
|
106
83
|
}
|
package/dist/tools/insight.js
CHANGED
|
@@ -5,11 +5,6 @@ exports.handleInsightTool = handleInsightTool;
|
|
|
5
5
|
const zod_1 = require("zod");
|
|
6
6
|
const convex_js_1 = require("../convex.js");
|
|
7
7
|
exports.INSIGHT_TOOLS = [
|
|
8
|
-
{
|
|
9
|
-
name: "get_insight",
|
|
10
|
-
description: "Get Noel's daily crypto + macro insight. Covers Bitcoin/ETH price action, macro events, trending narratives on X/Twitter, and one actionable takeaway.",
|
|
11
|
-
inputSchema: { type: "object", properties: {}, required: [] },
|
|
12
|
-
},
|
|
13
8
|
{
|
|
14
9
|
name: "ask_noel",
|
|
15
10
|
description: "Ask Noel AI for DeFi analysis, trade ideas, market outlook, and crypto research. Noel has live market context.",
|
|
@@ -36,24 +31,15 @@ const AskNoelSchema = zod_1.z.object({
|
|
|
36
31
|
messages: zod_1.z.array(zod_1.z.object({ role: zod_1.z.enum(["user", "assistant"]), content: zod_1.z.string() })).optional(),
|
|
37
32
|
});
|
|
38
33
|
async function handleInsightTool(name, args) {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
question: parsed.data.question,
|
|
51
|
-
agentId: "noel-default",
|
|
52
|
-
messages: parsed.data.messages ?? [],
|
|
53
|
-
}, "ask_noel");
|
|
54
|
-
return { content: [{ type: "text", text: data.answer ?? JSON.stringify(data) }] };
|
|
55
|
-
}
|
|
56
|
-
default:
|
|
57
|
-
return null;
|
|
58
|
-
}
|
|
34
|
+
if (name !== "ask_noel")
|
|
35
|
+
return null;
|
|
36
|
+
const parsed = AskNoelSchema.safeParse(args);
|
|
37
|
+
if (!parsed.success)
|
|
38
|
+
return { content: [{ type: "text", text: `Invalid input: question ${parsed.error.issues[0].message}` }], isError: true };
|
|
39
|
+
const data = await (0, convex_js_1.callConvex)("/mcp/chat", "POST", {
|
|
40
|
+
question: parsed.data.question,
|
|
41
|
+
agentId: "noel-default",
|
|
42
|
+
messages: parsed.data.messages ?? [],
|
|
43
|
+
}, "ask_noel");
|
|
44
|
+
return { content: [{ type: "text", text: data.answer ?? JSON.stringify(data) }] };
|
|
59
45
|
}
|
package/dist/tools/market.js
CHANGED
|
@@ -3,23 +3,62 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.MARKET_TOOLS = void 0;
|
|
4
4
|
exports.handleMarketTool = handleMarketTool;
|
|
5
5
|
const zod_1 = require("zod");
|
|
6
|
-
const
|
|
6
|
+
const COINGECKO = "https://api.coingecko.com/api/v3";
|
|
7
|
+
const SYMBOL_TO_ID = {
|
|
8
|
+
BTC: "bitcoin", ETH: "ethereum", SOL: "solana", BNB: "binancecoin",
|
|
9
|
+
USDT: "tether", USDC: "usd-coin", XRP: "ripple", DOGE: "dogecoin",
|
|
10
|
+
ADA: "cardano", AVAX: "avalanche-2", DOT: "polkadot", LINK: "chainlink",
|
|
11
|
+
UNI: "uniswap", OP: "optimism", ARB: "arbitrum", PEPE: "pepe",
|
|
12
|
+
SUI: "sui", APT: "aptos", NEAR: "near", INJ: "injective-protocol",
|
|
13
|
+
TIA: "celestia", MATIC: "matic-network", TON: "the-open-network",
|
|
14
|
+
SHIB: "shiba-inu", WIF: "dogwifcoin", BONK: "bonk", HYPE: "hyperliquid",
|
|
15
|
+
};
|
|
16
|
+
async function cgFetch(path) {
|
|
17
|
+
const res = await fetch(`${COINGECKO}${path}`, {
|
|
18
|
+
headers: { Accept: "application/json" },
|
|
19
|
+
signal: AbortSignal.timeout(15000),
|
|
20
|
+
});
|
|
21
|
+
if (!res.ok)
|
|
22
|
+
throw new Error(`CoinGecko ${res.status}`);
|
|
23
|
+
return res.json();
|
|
24
|
+
}
|
|
25
|
+
function fmt(n, decimals = 2) {
|
|
26
|
+
if (n == null)
|
|
27
|
+
return "—";
|
|
28
|
+
return n.toLocaleString("en-US", { maximumFractionDigits: decimals });
|
|
29
|
+
}
|
|
30
|
+
function fmtPrice(n) {
|
|
31
|
+
if (n == null)
|
|
32
|
+
return "—";
|
|
33
|
+
if (n >= 1)
|
|
34
|
+
return `$${n.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
|
|
35
|
+
return `$${n.toPrecision(4)}`;
|
|
36
|
+
}
|
|
37
|
+
function fmtB(n) {
|
|
38
|
+
if (n == null)
|
|
39
|
+
return "—";
|
|
40
|
+
if (n >= 1e9)
|
|
41
|
+
return `$${(n / 1e9).toFixed(2)}B`;
|
|
42
|
+
if (n >= 1e6)
|
|
43
|
+
return `$${(n / 1e6).toFixed(1)}M`;
|
|
44
|
+
return `$${fmt(n)}`;
|
|
45
|
+
}
|
|
7
46
|
exports.MARKET_TOOLS = [
|
|
8
47
|
{
|
|
9
48
|
name: "get_market_data",
|
|
10
|
-
description: "Get live crypto market data: top 20 coins by market cap, trending coins, and key prices for BTC/ETH/SOL.
|
|
49
|
+
description: "Get live crypto market data: top 20 coins by market cap, trending coins, and key prices for BTC/ETH/SOL.",
|
|
11
50
|
inputSchema: {
|
|
12
51
|
type: "object",
|
|
13
|
-
properties: { token: { type: "string", description: "Optional:
|
|
52
|
+
properties: { token: { type: "string", description: "Optional: focus on a specific token, e.g. 'BTC', 'ETH'" } },
|
|
14
53
|
required: [],
|
|
15
54
|
},
|
|
16
55
|
},
|
|
17
56
|
{
|
|
18
57
|
name: "get_token_data",
|
|
19
|
-
description: "Get market data for specific
|
|
58
|
+
description: "Get live market data for a specific token. Returns price, 24h change, market cap, and volume.",
|
|
20
59
|
inputSchema: {
|
|
21
60
|
type: "object",
|
|
22
|
-
properties: { question: { type: "string", description: "
|
|
61
|
+
properties: { question: { type: "string", description: "Token to look up, e.g. 'ETH', 'show me SOL', 'PEPE price'" } },
|
|
23
62
|
required: ["question"],
|
|
24
63
|
},
|
|
25
64
|
},
|
|
@@ -31,40 +70,83 @@ async function handleMarketTool(name, args) {
|
|
|
31
70
|
case "get_market_data": {
|
|
32
71
|
const parsed = GetMarketDataSchema.safeParse(args ?? {});
|
|
33
72
|
if (!parsed.success)
|
|
34
|
-
return { content: [{ type: "text", text: `Invalid input:
|
|
73
|
+
return { content: [{ type: "text", text: `Invalid input: ${parsed.error.issues[0].message}` }], isError: true };
|
|
35
74
|
const { token } = parsed.data;
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
75
|
+
if (token) {
|
|
76
|
+
const sym = token.toUpperCase();
|
|
77
|
+
const id = SYMBOL_TO_ID[sym];
|
|
78
|
+
if (!id)
|
|
79
|
+
return { content: [{ type: "text", text: `Unknown token: ${sym}. Try get_token_data for specific lookup.` }], isError: true };
|
|
80
|
+
const [data, trending] = await Promise.all([
|
|
81
|
+
cgFetch(`/coins/markets?vs_currency=usd&ids=${id}&sparkline=false&price_change_percentage=24h`),
|
|
82
|
+
cgFetch("/search/trending"),
|
|
83
|
+
]);
|
|
84
|
+
const c = data[0];
|
|
85
|
+
if (!c)
|
|
86
|
+
return { content: [{ type: "text", text: `No data for ${sym}` }], isError: true };
|
|
87
|
+
const sign = (c.price_change_percentage_24h ?? 0) >= 0 ? "+" : "";
|
|
88
|
+
const lines = [
|
|
89
|
+
`**${c.symbol?.toUpperCase()} — ${c.name}**`,
|
|
90
|
+
`Price: ${fmtPrice(c.current_price)} (${sign}${fmt(c.price_change_percentage_24h)}% 24h)`,
|
|
91
|
+
`Market Cap: ${fmtB(c.market_cap)} (rank #${c.market_cap_rank ?? "—"})`,
|
|
92
|
+
`Volume 24h: ${fmtB(c.total_volume)}`,
|
|
93
|
+
`High/Low 24h: ${fmtPrice(c.high_24h)} / ${fmtPrice(c.low_24h)}`,
|
|
94
|
+
"",
|
|
95
|
+
`_Source: CoinGecko · ${new Date().toUTCString()}_`,
|
|
96
|
+
];
|
|
97
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
98
|
+
}
|
|
99
|
+
const [top20, trending] = await Promise.all([
|
|
100
|
+
cgFetch("/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=20&page=1&sparkline=false&price_change_percentage=24h"),
|
|
101
|
+
cgFetch("/search/trending"),
|
|
102
|
+
]);
|
|
103
|
+
const lines = [`**Crypto Market Overview** — ${new Date().toUTCString()}`, ""];
|
|
104
|
+
lines.push("**Key Prices**");
|
|
105
|
+
for (const sym of ["BTC", "ETH", "SOL"]) {
|
|
106
|
+
const c = top20.find((x) => x.symbol?.toUpperCase() === sym);
|
|
107
|
+
if (!c)
|
|
41
108
|
continue;
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
109
|
+
const sign = (c.price_change_percentage_24h ?? 0) >= 0 ? "+" : "";
|
|
110
|
+
lines.push(`• **${sym}**: ${fmtPrice(c.current_price)} (${sign}${fmt(c.price_change_percentage_24h)}% 24h) — mcap ${fmtB(c.market_cap)}`);
|
|
111
|
+
}
|
|
112
|
+
lines.push("", "**Top 20 by Market Cap**");
|
|
113
|
+
for (const c of top20) {
|
|
114
|
+
const sym = c.symbol?.toUpperCase();
|
|
115
|
+
const sign = (c.price_change_percentage_24h ?? 0) >= 0 ? "+" : "";
|
|
116
|
+
lines.push(`${c.market_cap_rank}. **${sym}** ${fmtPrice(c.current_price)} (${sign}${fmt(c.price_change_percentage_24h)}%) — ${fmtB(c.market_cap)}`);
|
|
117
|
+
}
|
|
118
|
+
const trendingCoins = trending?.coins?.slice(0, 7) ?? [];
|
|
119
|
+
if (trendingCoins.length > 0) {
|
|
120
|
+
lines.push("", "**Trending**");
|
|
121
|
+
for (const t of trendingCoins) {
|
|
122
|
+
const item = t.item;
|
|
123
|
+
lines.push(`• **${item.symbol}** (#${item.market_cap_rank ?? "—"}) — ${item.name}`);
|
|
124
|
+
}
|
|
46
125
|
}
|
|
126
|
+
lines.push("", `_Source: CoinGecko_`);
|
|
47
127
|
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
48
128
|
}
|
|
49
129
|
case "get_token_data": {
|
|
50
130
|
const parsed = GetTokenDataSchema.safeParse(args);
|
|
51
131
|
if (!parsed.success)
|
|
52
|
-
return { content: [{ type: "text", text: `Invalid input:
|
|
132
|
+
return { content: [{ type: "text", text: `Invalid input: ${parsed.error.issues[0].message}` }], isError: true };
|
|
53
133
|
const q = parsed.data.question.toUpperCase();
|
|
54
|
-
const
|
|
55
|
-
const
|
|
56
|
-
const data = await (
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const
|
|
61
|
-
const sign = (data.change_24h_pct ?? 0) >= 0 ? "+" : "";
|
|
134
|
+
const sym = Object.keys(SYMBOL_TO_ID).find((s) => new RegExp(`\\b${s}\\b`).test(q)) ?? "BTC";
|
|
135
|
+
const id = SYMBOL_TO_ID[sym];
|
|
136
|
+
const data = await cgFetch(`/coins/markets?vs_currency=usd&ids=${id}&sparkline=false&price_change_percentage=24h`);
|
|
137
|
+
const c = data[0];
|
|
138
|
+
if (!c)
|
|
139
|
+
return { content: [{ type: "text", text: `No data found for ${sym}` }], isError: true };
|
|
140
|
+
const sign = (c.price_change_percentage_24h ?? 0) >= 0 ? "+" : "";
|
|
62
141
|
const lines = [
|
|
63
|
-
`**${
|
|
64
|
-
`Price: ${
|
|
65
|
-
`Market Cap:
|
|
66
|
-
`Volume 24h:
|
|
67
|
-
`
|
|
142
|
+
`**${c.symbol?.toUpperCase()} — ${c.name}**`,
|
|
143
|
+
`Price: ${fmtPrice(c.current_price)} (${sign}${fmt(c.price_change_percentage_24h)}% 24h)`,
|
|
144
|
+
`Market Cap: ${fmtB(c.market_cap)} (rank #${c.market_cap_rank ?? "—"})`,
|
|
145
|
+
`Volume 24h: ${fmtB(c.total_volume)}`,
|
|
146
|
+
`High/Low 24h: ${fmtPrice(c.high_24h)} / ${fmtPrice(c.low_24h)}`,
|
|
147
|
+
`All-Time High: ${fmtPrice(c.ath)} (${c.ath_change_percentage != null ? fmt(c.ath_change_percentage) + "% from ATH" : "—"})`,
|
|
148
|
+
"",
|
|
149
|
+
`_Source: CoinGecko · ${new Date().toUTCString()}_`,
|
|
68
150
|
];
|
|
69
151
|
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
70
152
|
}
|
package/dist/tools/miroshark.js
CHANGED
|
@@ -134,7 +134,7 @@ async function handleMirosharkTool(name, args) {
|
|
|
134
134
|
if (!simId)
|
|
135
135
|
throw new Error("No simulation_id in create response");
|
|
136
136
|
// Step 6: kick off agent preparation (async — don't block)
|
|
137
|
-
const prepared = await miroJson("/miroshark/api/simulation/prepare", "POST", { simulation_id: simId });
|
|
137
|
+
const prepared = await miroJson("/miroshark/api/simulation/prepare", "POST", { simulation_id: simId, parallel_profile_count: 10 });
|
|
138
138
|
const prepTaskId = prepared.task_id;
|
|
139
139
|
return {
|
|
140
140
|
content: [{
|
package/dist/tools/research.js
CHANGED
|
@@ -2,28 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.RESEARCH_TOOLS = void 0;
|
|
4
4
|
exports.handleResearchTool = handleResearchTool;
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
{
|
|
9
|
-
name: "research",
|
|
10
|
-
description: "Research any crypto topic on demand — like Perplexity but for crypto. Ask about a token, protocol, market event, or trend. Noel searches the web and returns a structured analysis.",
|
|
11
|
-
inputSchema: {
|
|
12
|
-
type: "object",
|
|
13
|
-
properties: { query: { type: "string", description: "Topic to research" } },
|
|
14
|
-
required: ["query"],
|
|
15
|
-
},
|
|
16
|
-
},
|
|
17
|
-
];
|
|
18
|
-
const ResearchSchema = zod_1.z.object({ query: zod_1.z.string().min(1) });
|
|
19
|
-
async function handleResearchTool(name, args) {
|
|
20
|
-
if (name !== "research")
|
|
21
|
-
return null;
|
|
22
|
-
const parsed = ResearchSchema.safeParse(args);
|
|
23
|
-
if (!parsed.success)
|
|
24
|
-
return { content: [{ type: "text", text: `Invalid input: query ${parsed.error.issues[0].message}` }], isError: true };
|
|
25
|
-
const data = await (0, convex_js_1.callConvex)("/mcp/research", "POST", { query: parsed.data.query }, "research");
|
|
26
|
-
if (!data.success)
|
|
27
|
-
return { content: [{ type: "text", text: `Research failed: ${data.error ?? "unknown error"}` }] };
|
|
28
|
-
return { content: [{ type: "text", text: data.text ?? "No results returned." }] };
|
|
5
|
+
exports.RESEARCH_TOOLS = [];
|
|
6
|
+
async function handleResearchTool(_name, _args) {
|
|
7
|
+
return null;
|
|
29
8
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@noelclaw/mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Noelclaw as an MCP skill — persistent memory, multi-agent coordination, scenario simulation, DeFi execution, and Sentinel-gated playbooks.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|