neuron-mcp-server 1.0.0 → 1.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 +13 -0
- package/AI_PERSONALITY_DESIGN_RESEARCH.md +1020 -0
- package/Dockerfile +18 -0
- package/README.md +146 -131
- package/dist/client.d.ts +6 -0
- package/dist/client.js +50 -12
- package/dist/client.js.map +1 -1
- package/dist/index.js +51 -7
- package/dist/index.js.map +1 -1
- package/dist/tools/ai.js +9 -3
- package/dist/tools/ai.js.map +1 -1
- package/dist/tools/approvals.d.ts +2 -0
- package/dist/tools/approvals.js +181 -0
- package/dist/tools/approvals.js.map +1 -0
- package/dist/tools/audit.js +7 -4
- package/dist/tools/audit.js.map +1 -1
- package/dist/tools/auth.js +119 -19
- package/dist/tools/auth.js.map +1 -1
- package/dist/tools/billing.js +22 -6
- package/dist/tools/billing.js.map +1 -1
- package/dist/tools/blog.js +98 -34
- package/dist/tools/blog.js.map +1 -1
- package/dist/tools/bot-api-keys.js +27 -12
- package/dist/tools/bot-api-keys.js.map +1 -1
- package/dist/tools/bot-api.js +53 -27
- package/dist/tools/bot-api.js.map +1 -1
- package/dist/tools/bots.js +116 -68
- package/dist/tools/bots.js.map +1 -1
- package/dist/tools/broadcasts.js +78 -38
- package/dist/tools/broadcasts.js.map +1 -1
- package/dist/tools/builtin-tools.js +19 -12
- package/dist/tools/builtin-tools.js.map +1 -1
- package/dist/tools/campaigns.js +149 -61
- package/dist/tools/campaigns.js.map +1 -1
- package/dist/tools/channels.js +163 -53
- package/dist/tools/channels.js.map +1 -1
- package/dist/tools/contact-lists.js +111 -51
- package/dist/tools/contact-lists.js.map +1 -1
- package/dist/tools/contacts.js +117 -44
- package/dist/tools/contacts.js.map +1 -1
- package/dist/tools/conversations.js +95 -50
- package/dist/tools/conversations.js.map +1 -1
- package/dist/tools/flows.d.ts +2 -0
- package/dist/tools/flows.js +242 -0
- package/dist/tools/flows.js.map +1 -0
- package/dist/tools/group-management.d.ts +2 -0
- package/dist/tools/group-management.js +239 -0
- package/dist/tools/group-management.js.map +1 -0
- package/dist/tools/leads.d.ts +2 -0
- package/dist/tools/leads.js +100 -0
- package/dist/tools/leads.js.map +1 -0
- package/dist/tools/list-campaigns.d.ts +2 -0
- package/dist/tools/list-campaigns.js +152 -0
- package/dist/tools/list-campaigns.js.map +1 -0
- package/dist/tools/list-pool.js +250 -33
- package/dist/tools/list-pool.js.map +1 -1
- package/dist/tools/media.js +12 -7
- package/dist/tools/media.js.map +1 -1
- package/dist/tools/newsletters.js +106 -26
- package/dist/tools/newsletters.js.map +1 -1
- package/dist/tools/organizations.js +76 -35
- package/dist/tools/organizations.js.map +1 -1
- package/dist/tools/outbound-webhooks.js +32 -20
- package/dist/tools/outbound-webhooks.js.map +1 -1
- package/dist/tools/payouts.js +44 -17
- package/dist/tools/payouts.js.map +1 -1
- package/dist/tools/personas.d.ts +2 -0
- package/dist/tools/personas.js +141 -0
- package/dist/tools/personas.js.map +1 -0
- package/dist/tools/polls.d.ts +2 -0
- package/dist/tools/polls.js +30 -0
- package/dist/tools/polls.js.map +1 -0
- package/dist/tools/pool.js +101 -43
- package/dist/tools/pool.js.map +1 -1
- package/dist/tools/products.d.ts +2 -0
- package/dist/tools/products.js +277 -0
- package/dist/tools/products.js.map +1 -0
- package/dist/tools/profile-privacy.d.ts +2 -0
- package/dist/tools/profile-privacy.js +195 -0
- package/dist/tools/profile-privacy.js.map +1 -0
- package/dist/tools/reflections.js +25 -13
- package/dist/tools/reflections.js.map +1 -1
- package/dist/tools/scheduled-messages.d.ts +2 -0
- package/dist/tools/scheduled-messages.js +124 -0
- package/dist/tools/scheduled-messages.js.map +1 -0
- package/dist/tools/social-channels.d.ts +2 -0
- package/dist/tools/social-channels.js +318 -0
- package/dist/tools/social-channels.js.map +1 -0
- package/dist/tools/tasks.d.ts +2 -0
- package/dist/tools/tasks.js +155 -0
- package/dist/tools/tasks.js.map +1 -0
- package/dist/tools/tools.js +86 -40
- package/dist/tools/tools.js.map +1 -1
- package/dist/tools/wallets.js +34 -12
- package/dist/tools/wallets.js.map +1 -1
- package/dist/tools/webhooks.js +35 -20
- package/dist/tools/webhooks.js.map +1 -1
- package/dist/tools/whatsapp-actions.d.ts +2 -0
- package/dist/tools/whatsapp-actions.js +186 -0
- package/dist/tools/whatsapp-actions.js.map +1 -0
- package/package.json +4 -31
- package/scripts/setup-delivahere-bot.ts +804 -0
- package/scripts/test-delivahere-bot.ts +128 -0
- package/scripts/update-letschop-prompt.ts +194 -0
- package/server.json +26 -0
- package/smithery.yaml +19 -0
- package/src/client.ts +169 -0
- package/src/index.ts +256 -0
- package/src/tools/ai.ts +35 -0
- package/src/tools/approvals.ts +231 -0
- package/src/tools/audit.ts +49 -0
- package/src/tools/auth.ts +536 -0
- package/src/tools/billing.ts +79 -0
- package/src/tools/blog.ts +264 -0
- package/src/tools/bot-api-keys.ts +87 -0
- package/src/tools/bot-api.ts +193 -0
- package/src/tools/bots.ts +320 -0
- package/src/tools/broadcasts.ts +224 -0
- package/src/tools/builtin-tools.ts +108 -0
- package/src/tools/campaigns.ts +429 -0
- package/src/tools/channels.ts +520 -0
- package/src/tools/contact-lists.ts +320 -0
- package/src/tools/contacts.ts +395 -0
- package/src/tools/conversations.ts +349 -0
- package/src/tools/flows.ts +298 -0
- package/src/tools/group-management.ts +265 -0
- package/src/tools/knowledge-bases.ts +451 -0
- package/src/tools/leads.ts +104 -0
- package/src/tools/list-campaigns.ts +190 -0
- package/src/tools/list-pool.ts +389 -0
- package/src/tools/media.ts +50 -0
- package/src/tools/newsletters.ts +271 -0
- package/src/tools/organizations.ts +287 -0
- package/src/tools/outbound-webhooks.ts +181 -0
- package/src/tools/payouts.ts +133 -0
- package/src/tools/personas.ts +145 -0
- package/src/tools/polls.ts +32 -0
- package/src/tools/pool.ts +293 -0
- package/src/tools/products.ts +280 -0
- package/src/tools/profile-privacy.ts +215 -0
- package/src/tools/reflections.ts +124 -0
- package/src/tools/scheduled-messages.ts +144 -0
- package/src/tools/social-channels.ts +396 -0
- package/src/tools/tasks.ts +198 -0
- package/src/tools/tools.ts +255 -0
- package/src/tools/wallets.ts +107 -0
- package/src/tools/webhooks.ts +166 -0
- package/src/tools/whatsapp-actions.ts +203 -0
- package/tsconfig.json +20 -0
- package/LICENSE +0 -21
package/Dockerfile
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
FROM node:22-alpine AS builder
|
|
2
|
+
WORKDIR /app
|
|
3
|
+
COPY package.json package-lock.json* ./
|
|
4
|
+
RUN npm ci
|
|
5
|
+
COPY tsconfig.json ./
|
|
6
|
+
COPY src/ ./src/
|
|
7
|
+
RUN npm run build
|
|
8
|
+
|
|
9
|
+
FROM node:22-alpine
|
|
10
|
+
WORKDIR /app
|
|
11
|
+
COPY package.json package-lock.json* ./
|
|
12
|
+
RUN npm ci --omit=dev
|
|
13
|
+
COPY --from=builder /app/dist ./dist
|
|
14
|
+
ENV NODE_ENV=production
|
|
15
|
+
ENV MCP_TRANSPORT=http
|
|
16
|
+
ENV PORT=3001
|
|
17
|
+
EXPOSE 3001
|
|
18
|
+
CMD ["node", "dist/index.js"]
|
package/README.md
CHANGED
|
@@ -1,178 +1,193 @@
|
|
|
1
1
|
# Neuron MCP Server
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Exposes the Neuron WhatsApp platform as MCP tools (bots, conversations, broadcasts, approvals, and more). Each tool proxies to the Neuron REST API (`NEURON_API_URL`, default `https://api.neuron.ng/api/v1`).
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
## Connect
|
|
7
6
|
|
|
8
|
-
|
|
7
|
+
- **Remote (Claude.ai / hosted clients):** `https://mcp.neuron.ng/mcp` (Streamable HTTP).
|
|
8
|
+
- **Local (Claude Code / IDE, stdio):** run `node dist/index.js` (or `npm run dev`). Configure with `MCP_TRANSPORT=stdio` (default).
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
## Auth
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
Two token types are used:
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
- **Session token** — most tools use the org-level token from `neuron_login` (or `NEURON_AUTH_TOKEN` / smithery `authToken`).
|
|
15
|
+
- **Bot API key (`nrn_`)** — the `neuron_bot_api_*` and `neuron_*_approval` tools take an explicit `apiKey` argument per call. Create one in the dashboard under your bot's API keys.
|
|
15
16
|
|
|
16
|
-
|
|
17
|
+
---
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
## Approvals — human-in-the-loop sign-off
|
|
19
20
|
|
|
20
|
-
|
|
21
|
-
{
|
|
22
|
-
"mcpServers": {
|
|
23
|
-
"neuron": {
|
|
24
|
-
"type": "url",
|
|
25
|
-
"url": "https://mcp.neuron.ng/mcp"
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
```
|
|
21
|
+
Ask a human to approve or reject an action over WhatsApp and get the decision back. The recipient replies `approve` / `reject` / `reject: <reason>` (or quotes the message). Use it to gate refunds, deploys, spend, publishing, or an agent's own tool use.
|
|
30
22
|
|
|
31
|
-
|
|
23
|
+
**Tools** (all take `apiKey`, a bot API key with the `nrn_` prefix):
|
|
32
24
|
|
|
33
|
-
|
|
25
|
+
| Tool | Purpose |
|
|
26
|
+
|---|---|
|
|
27
|
+
| `neuron_request_approval` | Create a request and send the WhatsApp prompt |
|
|
28
|
+
| `neuron_get_approval` | Fetch one approval; `waitSeconds` (1–60) long-polls until it resolves |
|
|
29
|
+
| `neuron_list_approvals` | List approvals, filter by `status` |
|
|
30
|
+
| `neuron_respond_approval` | Approve/reject programmatically — decide via MCP instead of WhatsApp |
|
|
31
|
+
| `neuron_cancel_approval` | Cancel a still-pending request |
|
|
34
32
|
|
|
35
|
-
|
|
33
|
+
An operator can resolve an approval from either side — a WhatsApp reply **or** `neuron_respond_approval`. Whichever lands first wins (exactly-once); the later one returns a "already resolved" error. Responding via MCP still fires the callback and posts the outcome to the WhatsApp chat.
|
|
36
34
|
|
|
37
|
-
```
|
|
38
|
-
|
|
35
|
+
```jsonc
|
|
36
|
+
neuron_respond_approval({
|
|
37
|
+
"apiKey": "nrn_...",
|
|
38
|
+
"approvalId": "b1f...",
|
|
39
|
+
"decision": "reject",
|
|
40
|
+
"reason": "duplicate charge",
|
|
41
|
+
"responderName": "Ops"
|
|
42
|
+
})
|
|
39
43
|
```
|
|
40
44
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
+
### Poll flow (simplest)
|
|
46
|
+
|
|
47
|
+
```jsonc
|
|
48
|
+
// 1. Request — omit `callback` for a poll-only flow
|
|
49
|
+
neuron_request_approval({
|
|
50
|
+
"apiKey": "nrn_...",
|
|
51
|
+
"to": "2348012345678",
|
|
52
|
+
"prompt": "Approve refund of ₦45,000 for order #1042?",
|
|
53
|
+
"metadata": { "orderId": "1042" }
|
|
54
|
+
})
|
|
55
|
+
// → { "approvalId": "b1f...", "status": "pending", "expiresAt": "..." }
|
|
56
|
+
|
|
57
|
+
// 2. Wait for the human (blocks up to 60s, repeat until resolved/expired)
|
|
58
|
+
neuron_get_approval({ "apiKey": "nrn_...", "approvalId": "b1f...", "waitSeconds": 60 })
|
|
59
|
+
// → { "status": "approved", "decision": "approve", "responder": { "name": "Tunde" }, ... }
|
|
45
60
|
```
|
|
46
61
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
62
|
+
### Webhook flow (no polling)
|
|
63
|
+
|
|
64
|
+
Supply a `callback.delivery` scheme and Neuron pushes the decision to you when it resolves:
|
|
65
|
+
|
|
66
|
+
```jsonc
|
|
67
|
+
neuron_request_approval({
|
|
68
|
+
"apiKey": "nrn_...",
|
|
69
|
+
"to": "2348012345678",
|
|
70
|
+
"prompt": "Ship deploy #42 to production?",
|
|
71
|
+
"callback": {
|
|
72
|
+
"response": { "schemes": ["keyword"] },
|
|
73
|
+
"delivery": { "scheme": "webhook_signed", "config": { "url": "https://your-app.com/hooks/approvals", "secret": "whsec_..." } }
|
|
74
|
+
},
|
|
75
|
+
"idempotencyKey": "deploy-42"
|
|
76
|
+
})
|
|
58
77
|
```
|
|
59
78
|
|
|
60
|
-
|
|
79
|
+
Your endpoint receives `{ "event": "approval.resolved", "data": { "approvalId", "decision", "reason", "responder", "metadata", ... } }`. For `webhook_signed`, verify the `X-Neuron-Signature: sha256=...` header (HMAC-SHA256 of the raw body with your secret).
|
|
61
80
|
|
|
62
|
-
|
|
81
|
+
### Callback schemes
|
|
63
82
|
|
|
64
|
-
|
|
83
|
+
- **`response.schemes`** — how a reply becomes a decision: `interactive` · `keyword` · `code` (one-time code in the prompt) · `llm` (natural-language). Ordered fallback; default `["keyword"]`.
|
|
84
|
+
- **`delivery.scheme`** — how the decision reaches you: `webhook_signed` (HMAC) · `webhook_simple` (URL-as-secret) · `neuron_message` (send as a WhatsApp message) · `neuron_tool` (invoke another Neuron tool) · `none` (poll).
|
|
85
|
+
- **`await: true`** — hold `neuron_request_approval` until resolved and return the decision inline (up to `awaitTimeoutSec`).
|
|
65
86
|
|
|
66
|
-
|
|
87
|
+
Full endpoint reference: `https://api.neuron.ng/api/docs` (see the **Approvals** tag).
|
|
67
88
|
|
|
68
|
-
|
|
89
|
+
## Tasks — scheduled autonomous bot actions
|
|
69
90
|
|
|
70
|
-
|
|
91
|
+
A **task** is a natural-language instruction a bot carries out on its own, on a schedule (e.g. *"every morning at 8am, message 10 people we haven't heard from in 10+ days with our intro offer"*). Each run is an agentic tool-loop. Within a run the bot can:
|
|
71
92
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
93
|
+
- **Select an audience** — by staleness (no reply in N days), tag, contact list, or search.
|
|
94
|
+
- **Compose accurately** — look facts, prices, menus, and links up in the bot's **knowledge base** (never guesses).
|
|
95
|
+
- **Reach people** — send text, image/document/video/audio, or polls to individuals; **broadcast** to many at once; **schedule** a future message; **post to a WhatsApp group**.
|
|
96
|
+
- **Orchestrate** — read a contact's history for context, tag contacts / add them to lists, enrol them in drip sequences, **compile an activity report**, notify the team, and schedule follow-up tasks.
|
|
75
97
|
|
|
76
|
-
|
|
98
|
+
Every send is automatically screened against the org's Do-Not-Contact list, a per-run action cap, and a no-repeat window; a task can optionally require WhatsApp approval before sending, or run as a dry run. You describe all of this in plain English in the `instruction` — the tools above are what the bot uses under the hood.
|
|
77
99
|
|
|
78
|
-
|
|
100
|
+
These tools use the session token (from `neuron_login`).
|
|
79
101
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
102
|
+
| Tool | Purpose |
|
|
103
|
+
| --- | --- |
|
|
104
|
+
| `neuron_draft_task` | Turn a plain-English description into a structured task spec (does **not** create it) |
|
|
105
|
+
| `neuron_create_task` | Create a task for a bot |
|
|
106
|
+
| `neuron_list_tasks` | List a bot's tasks |
|
|
107
|
+
| `neuron_update_task` | Update a task (partial) |
|
|
108
|
+
| `neuron_toggle_task` | Pause / resume a task |
|
|
109
|
+
| `neuron_run_task` | Run a task immediately (in addition to its schedule) |
|
|
110
|
+
| `neuron_get_task_runs` | Paginated run history — status, AI summary, tool steps, stats |
|
|
111
|
+
| `neuron_delete_task` | Delete a task (soft delete; stops it running) |
|
|
83
112
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
| **Contacts** | 12 | CRUD operations, import/export, semantic search, sync |
|
|
93
|
-
| **Contact Lists** | 11 | Segmentation, merge, membership management |
|
|
94
|
-
| **Channels** | 17 | WhatsApp connections, QR pairing, session management |
|
|
95
|
-
| **Broadcasts** | 7 | Bulk messaging to contact lists |
|
|
96
|
-
| **Campaigns** | 14 | Sponsored campaigns, marketplace, funding |
|
|
97
|
-
| **Newsletters** | 8 | WhatsApp Channel/newsletter management |
|
|
98
|
-
| **Webhooks** | 8 | Inbound and outbound webhook management |
|
|
99
|
-
| **Custom Tools** | 6 | HTTP API tools for bots with secret injection |
|
|
100
|
-
| **Blog** | 6 | Content publishing |
|
|
101
|
-
| **Organizations** | 7 | Team management, audit logs, member invitations |
|
|
102
|
-
| **Billing & Wallet** | 12 | Subscriptions, wallet, payouts, bank accounts |
|
|
103
|
-
| **Marketplace** | 8 | Publish and install bots and contact lists |
|
|
104
|
-
| **Reflections** | 4 | Self-learning bot improvement suggestions |
|
|
105
|
-
| **Media & AI** | 2 | Upload media, AI text rewriting |
|
|
106
|
-
|
|
107
|
-
## Environment Variables
|
|
108
|
-
|
|
109
|
-
| Variable | Description | Default |
|
|
110
|
-
|----------|-------------|---------|
|
|
111
|
-
| `NEURON_API_URL` | API base URL | `https://api.neuron.ng/api/v1` |
|
|
112
|
-
| `NEURON_AUTH_TOKEN` | Pre-set auth token | — |
|
|
113
|
-
| `MCP_TRANSPORT` | Transport mode: `stdio` or `http` | `stdio` |
|
|
114
|
-
| `PORT` | HTTP server port (when using `http` transport) | `3001` |
|
|
115
|
-
|
|
116
|
-
## IDE Setup
|
|
117
|
-
|
|
118
|
-
### Claude Code
|
|
119
|
-
|
|
120
|
-
Add to `~/.claude/mcp.json`:
|
|
121
|
-
|
|
122
|
-
```json
|
|
123
|
-
{
|
|
124
|
-
"mcpServers": {
|
|
125
|
-
"neuron": {
|
|
126
|
-
"command": "npx",
|
|
127
|
-
"args": ["-y", "neuron-mcp-server"]
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
```
|
|
113
|
+
### Schedule shapes
|
|
114
|
+
|
|
115
|
+
`scheduleKind` + `schedule`:
|
|
116
|
+
|
|
117
|
+
- **`cron`** — recurring at a clock time: `{ "time": "08:00", "days": [1,4] }` (`days` 0=Sun..6=Sat; empty/omitted = every day)
|
|
118
|
+
- **`interval`** — `{ "everyMinutes": 360 }`
|
|
119
|
+
- **`once`** — `{ "runAt": "2026-08-10T14:00:00Z" }`
|
|
120
|
+
- **`manual`** — `{}` (only runs via `neuron_run_task`)
|
|
132
121
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
122
|
+
`timezone` is IANA (e.g. `Africa/Lagos`). `config` accepts `{ channelId?, maxActions?, noRepeatDays?, requiresApproval?, approvalPhone?, dryRun? }`.
|
|
123
|
+
|
|
124
|
+
### Typical flow
|
|
125
|
+
|
|
126
|
+
```jsonc
|
|
127
|
+
// 1. Draft from natural language, review, then create.
|
|
128
|
+
neuron_draft_task({ "botId": "…", "prompt": "every morning at 8am, re-engage 10 contacts we haven't heard from in 10+ days with our intro message", "timezone": "Africa/Lagos" })
|
|
129
|
+
// -> { title, instruction, scheduleKind:"cron", schedule:{time:"08:00"}, timezone, config:{maxActions:10} }
|
|
130
|
+
|
|
131
|
+
neuron_create_task({ "botId": "…", "title": "Morning re-engage", "instruction": "…", "scheduleKind": "cron", "schedule": { "time": "08:00" }, "timezone": "Africa/Lagos", "config": { "maxActions": 10, "noRepeatDays": 14 } })
|
|
132
|
+
|
|
133
|
+
neuron_run_task({ "id": "…" }) // fire once now to test
|
|
134
|
+
neuron_get_task_runs({ "id": "…" }) // inspect what it did
|
|
144
135
|
```
|
|
145
136
|
|
|
146
|
-
|
|
137
|
+
Bots can also create their own tasks mid-conversation via the built-in `create_task` tool (enable it per bot under Built-in Tools).
|
|
138
|
+
|
|
139
|
+
Full endpoint reference: `https://api.neuron.ng/api/docs` (see the **Tasks** tag, and **Bot API** for the API-key-scoped `/bot-api/tasks*` endpoints).
|
|
147
140
|
|
|
148
|
-
|
|
141
|
+
## Leads — lead generation
|
|
149
142
|
|
|
150
|
-
|
|
143
|
+
A **lead** is a potential contact captured from a source: CSV, pasted text, a document, a web page, another tool's output, Instagram/X search, or a **live scraper** piping into the ingest endpoint. Leads live in a pool (deduped), and can be **converted** to contacts once they have a phone — then Tasks nurture them.
|
|
151
144
|
|
|
152
|
-
|
|
145
|
+
| Tool | Purpose |
|
|
146
|
+
| --- | --- |
|
|
147
|
+
| `neuron_create_lead_source` | Configure a source (type + config, optional recurring schedule) |
|
|
148
|
+
| `neuron_list_lead_sources` | List sources |
|
|
149
|
+
| `neuron_run_lead_source` | Run a source now → pull leads into the pool |
|
|
150
|
+
| `neuron_extract_leads` | One-off extraction (no persistent source) — e.g. paste text, scrape a page |
|
|
151
|
+
| `neuron_list_leads` | List/filter the pool by status/source/search |
|
|
152
|
+
| `neuron_lead_stats` | Counts by status |
|
|
153
|
+
| `neuron_convert_lead` | Promote a phone-bearing lead → contact (optionally add to a list) |
|
|
153
154
|
|
|
154
|
-
**
|
|
155
|
+
**Source `config` by type:** `text_paste {text}` · `web_scrape {url|urls[]|query}` · `document {mediaUrl,mimeType}` · `tool_output {toolId,args?}` · `instagram`/`x` `{channelId? OR usernames[]/handles[]/query, limit?}` · `facebook {query, country?}` (Meta Ads Library advertisers) · `csv {rows[]}` · `stream {triggerTaskId?}`. Add `enrich: true` to any source's config to auto-enrich new leads.
|
|
155
156
|
|
|
156
|
-
|
|
157
|
+
**Scraping backbone:** web / Instagram / X / Facebook scraping is **native when DeepAPI is configured** (`DEEPAPI_API_KEY`); without a connected social account it needs DeepAPI. `web_scrape` falls back to a basic static fetch. **TikTok** has no native provider — pipe a scraper in via `tool_output` or the ingest endpoint. **Enrichment:** `POST /leads/:id/enrich` researches a lead externally (DeepAPI) and fills missing email/company/title/bio. **Webhook:** subscribe an outbound webhook to `lead.created` to get every new lead pushed to your system.
|
|
157
158
|
|
|
158
|
-
|
|
159
|
+
**Live / external scrapers** push leads in continuously with a **bot API key** (not the session token):
|
|
159
160
|
|
|
160
161
|
```bash
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
npm run dev
|
|
162
|
+
curl -X POST https://api.neuron.ng/api/v1/bot-api/leads/ingest/bulk \
|
|
163
|
+
-H "Authorization: Bearer nrn_YOUR_KEY" -H "Content-Type: application/json" \
|
|
164
|
+
-d '{ "sourceId": "…optional stream source…", "leads": [ { "name": "Ada", "phone": "234…", "handle": "@ada", "company": "…" } ] }'
|
|
165
165
|
```
|
|
166
166
|
|
|
167
|
-
|
|
167
|
+
Dedup is automatic (by phone → email → platform:handle). If the `sourceId` is a stream source with `config.triggerTaskId`, that Task fires on new leads.
|
|
168
|
+
|
|
169
|
+
### Tasks × Leads
|
|
170
|
+
|
|
171
|
+
Inside a Task you can `generate_leads` (run a source), `list_leads`, and `convert_leads` — so a scheduled Task becomes **generate → convert → message/enrol**. Note: cold outreach on WhatsApp is a ban risk; lead messaging still runs behind the Do-Not-Contact list, the per-run cap, and the no-repeat window.
|
|
172
|
+
|
|
173
|
+
Full endpoint reference: `https://api.neuron.ng/api/docs` — dashboard `/leads` + `/lead-sources`, and **Bot API** `/bot-api/leads/ingest`.
|
|
174
|
+
|
|
175
|
+
## Personas — voice studio
|
|
176
|
+
|
|
177
|
+
A **persona** is a reusable *voice* distilled from a Collection of mined content (the web agent scrolls IG/X/TikTok/LinkedIn/Facebook and captures top-engagement posts into Collections). Building a persona analyzes the highest-engagement samples and reverse-engineers a **voiceProfile** (tone, diction, cadence, emoji/formatting habits, themes, dos/donts) plus representative **exemplars**. You then **generate** content in that voice, or **apply** the voice to a bot's persona.
|
|
168
178
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
179
|
+
| Tool | Purpose |
|
|
180
|
+
| --- | --- |
|
|
181
|
+
| `neuron_build_persona` | Distill a voice from a Collection's top-engagement items (needs ≥3 samples) |
|
|
182
|
+
| `neuron_list_personas` | List voice personas |
|
|
183
|
+
| `neuron_get_persona` | Get one persona's full voiceProfile + exemplars |
|
|
184
|
+
| `neuron_generate_from_persona` | Generate N content variations in the voice (topic/platform/format) |
|
|
185
|
+
| `neuron_apply_persona_to_bot` | Give a bot this voice — idempotent merge into its system prompt |
|
|
186
|
+
| `neuron_update_persona` | Rename or hand-tune the voiceProfile / exemplars |
|
|
187
|
+
| `neuron_delete_persona` | Delete a persona |
|
|
173
188
|
|
|
174
|
-
|
|
189
|
+
**The loop:** the web agent *mines* content into a Collection → `neuron_build_persona` *distills* the voice → `neuron_generate_from_persona` *writes* in it, and `neuron_apply_persona_to_bot` makes an engagement bot *speak* in it. Applying is idempotent (re-applying or swapping a persona replaces the voice block cleanly and is reversible).
|
|
175
190
|
|
|
176
|
-
|
|
191
|
+
**Bot API:** the same surface is on the bot API key — `GET /bot-api/personas`, `POST /bot-api/personas/build`, `GET /bot-api/personas/:id`, `POST /bot-api/personas/:id/generate`, and `POST /bot-api/personas/:id/apply` (applies the voice to the key's **own** bot).
|
|
177
192
|
|
|
178
|
-
|
|
193
|
+
Full endpoint reference: `https://api.neuron.ng/api/docs` — dashboard `/personas`.
|
package/dist/client.d.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
export declare function setAuthToken(token: string): void;
|
|
2
2
|
export declare function getAuthToken(): string;
|
|
3
3
|
export declare function getBaseUrl(): string;
|
|
4
|
+
export declare function setBaseUrl(url: string): void;
|
|
5
|
+
export declare function listInstances(): Array<{
|
|
6
|
+
url: string;
|
|
7
|
+
active: boolean;
|
|
8
|
+
authenticated: boolean;
|
|
9
|
+
}>;
|
|
4
10
|
interface ApiResponse<T = unknown> {
|
|
5
11
|
success: boolean;
|
|
6
12
|
data?: T;
|
package/dist/client.js
CHANGED
|
@@ -5,41 +5,79 @@ import { homedir } from "node:os";
|
|
|
5
5
|
// Resolve API URL: prefer NEURON_API_URL if it points to a real server (not Docker-internal hostnames)
|
|
6
6
|
const envUrl = process.env.NEURON_API_URL || "";
|
|
7
7
|
const isDockerInternal = envUrl.includes("neuron-api:") || (envUrl.includes("localhost") && !envUrl.includes("https://"));
|
|
8
|
-
const
|
|
8
|
+
const DEFAULT_BASE_URL = isDockerInternal ? "https://api.neuron.ng/api/v1" : (envUrl || "https://api.neuron.ng/api/v1");
|
|
9
|
+
let baseUrl = DEFAULT_BASE_URL;
|
|
10
|
+
// Token vault: stores tokens per base URL so switching instances preserves auth
|
|
11
|
+
const tokenVault = {};
|
|
9
12
|
const TOKEN_CACHE_DIR = join(homedir(), ".neuron");
|
|
10
13
|
const TOKEN_CACHE_FILE = join(TOKEN_CACHE_DIR, "mcp-token-cache.json");
|
|
11
|
-
function
|
|
14
|
+
function readCachedTokens() {
|
|
12
15
|
try {
|
|
13
16
|
const raw = readFileSync(TOKEN_CACHE_FILE, "utf-8");
|
|
14
17
|
const cache = JSON.parse(raw);
|
|
15
|
-
|
|
16
|
-
|
|
18
|
+
// Support legacy single-entry format
|
|
19
|
+
if (cache.baseUrl && cache.token && !cache.instances) {
|
|
20
|
+
return { [cache.baseUrl]: cache.token };
|
|
21
|
+
}
|
|
22
|
+
// Multi-instance format
|
|
23
|
+
if (cache.instances && typeof cache.instances === "object") {
|
|
24
|
+
return cache.instances;
|
|
17
25
|
}
|
|
18
26
|
}
|
|
19
27
|
catch {
|
|
20
28
|
// No cache or unreadable — that's fine
|
|
21
29
|
}
|
|
22
|
-
return
|
|
30
|
+
return {};
|
|
23
31
|
}
|
|
24
|
-
function
|
|
32
|
+
function writeCachedTokens() {
|
|
25
33
|
try {
|
|
26
34
|
mkdirSync(TOKEN_CACHE_DIR, { recursive: true, mode: 0o700 });
|
|
27
|
-
writeFileSync(TOKEN_CACHE_FILE, JSON.stringify({
|
|
35
|
+
writeFileSync(TOKEN_CACHE_FILE, JSON.stringify({ instances: tokenVault, activeBaseUrl: baseUrl }), { mode: 0o600 });
|
|
28
36
|
}
|
|
29
37
|
catch {
|
|
30
38
|
// Non-critical — best effort
|
|
31
39
|
}
|
|
32
40
|
}
|
|
33
|
-
|
|
41
|
+
// Initialize: load all cached tokens into the vault, then set active token
|
|
42
|
+
const cachedTokens = readCachedTokens();
|
|
43
|
+
for (const [url, token] of Object.entries(cachedTokens)) {
|
|
44
|
+
tokenVault[url] = token;
|
|
45
|
+
}
|
|
46
|
+
let authToken = process.env.NEURON_AUTH_TOKEN || tokenVault[baseUrl] || "";
|
|
34
47
|
export function setAuthToken(token) {
|
|
35
48
|
authToken = token;
|
|
36
|
-
|
|
49
|
+
if (token) {
|
|
50
|
+
tokenVault[baseUrl] = token;
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
delete tokenVault[baseUrl];
|
|
54
|
+
}
|
|
55
|
+
writeCachedTokens();
|
|
37
56
|
}
|
|
38
57
|
export function getAuthToken() {
|
|
39
58
|
return authToken;
|
|
40
59
|
}
|
|
41
60
|
export function getBaseUrl() {
|
|
42
|
-
return
|
|
61
|
+
return baseUrl;
|
|
62
|
+
}
|
|
63
|
+
export function setBaseUrl(url) {
|
|
64
|
+
// Save current token for current instance
|
|
65
|
+
if (authToken) {
|
|
66
|
+
tokenVault[baseUrl] = authToken;
|
|
67
|
+
}
|
|
68
|
+
// Switch to new instance
|
|
69
|
+
baseUrl = url;
|
|
70
|
+
// Restore token from vault if we've authenticated with this instance before
|
|
71
|
+
authToken = tokenVault[url] || "";
|
|
72
|
+
writeCachedTokens();
|
|
73
|
+
}
|
|
74
|
+
export function listInstances() {
|
|
75
|
+
const urls = new Set([baseUrl, ...Object.keys(tokenVault)]);
|
|
76
|
+
return Array.from(urls).map((url) => ({
|
|
77
|
+
url,
|
|
78
|
+
active: url === baseUrl,
|
|
79
|
+
authenticated: !!tokenVault[url],
|
|
80
|
+
}));
|
|
43
81
|
}
|
|
44
82
|
export async function api(method, endpoint, data, params, headers) {
|
|
45
83
|
try {
|
|
@@ -53,7 +91,7 @@ export async function api(method, endpoint, data, params, headers) {
|
|
|
53
91
|
const cleanEndpoint = endpoint.replace(/^\/+/, "");
|
|
54
92
|
const response = await axios({
|
|
55
93
|
method,
|
|
56
|
-
url: `${
|
|
94
|
+
url: `${baseUrl}/${cleanEndpoint}`,
|
|
57
95
|
data,
|
|
58
96
|
params: Object.keys(cleanParams).length > 0 ? cleanParams : undefined,
|
|
59
97
|
timeout: 60000,
|
|
@@ -80,7 +118,7 @@ export function handleError(error) {
|
|
|
80
118
|
const msg = body?.error?.message || `HTTP ${error.response.status}`;
|
|
81
119
|
return `Error: ${msg}`;
|
|
82
120
|
}
|
|
83
|
-
const url = error.config?.url ||
|
|
121
|
+
const url = error.config?.url || baseUrl;
|
|
84
122
|
if (error.code === "ECONNABORTED")
|
|
85
123
|
return `Error: Request timed out connecting to ${url}`;
|
|
86
124
|
if (error.code === "ECONNREFUSED") {
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -36,6 +36,9 @@ import { registerBotApiTools } from "./tools/bot-api.js";
|
|
|
36
36
|
import { registerConversationTools } from "./tools/conversations.js";
|
|
37
37
|
import { registerKnowledgeBaseTools } from "./tools/knowledge-bases.js";
|
|
38
38
|
import { registerToolsTools } from "./tools/tools.js";
|
|
39
|
+
import { registerTaskTools } from "./tools/tasks.js";
|
|
40
|
+
import { registerLeadTools } from "./tools/leads.js";
|
|
41
|
+
import { registerPersonaTools } from "./tools/personas.js";
|
|
39
42
|
import { registerWebhooksTools } from "./tools/webhooks.js";
|
|
40
43
|
import { registerReflectionsTools } from "./tools/reflections.js";
|
|
41
44
|
import { registerChannelsTools } from "./tools/channels.js";
|
|
@@ -46,6 +49,7 @@ import { registerBuiltinToolsTools } from "./tools/builtin-tools.js";
|
|
|
46
49
|
import { registerOutboundWebhookTools } from "./tools/outbound-webhooks.js";
|
|
47
50
|
import { registerContactsTools } from "./tools/contacts.js";
|
|
48
51
|
import { registerContactListsTools } from "./tools/contact-lists.js";
|
|
52
|
+
import { registerListCampaignTools } from "./tools/list-campaigns.js";
|
|
49
53
|
import { registerBroadcastsTools } from "./tools/broadcasts.js";
|
|
50
54
|
import { registerBillingTools } from "./tools/billing.js";
|
|
51
55
|
import { registerMediaTools } from "./tools/media.js";
|
|
@@ -56,6 +60,15 @@ import { registerPayoutTools } from "./tools/payouts.js";
|
|
|
56
60
|
import { registerBlogTools } from "./tools/blog.js";
|
|
57
61
|
import { registerNewsletterTools } from "./tools/newsletters.js";
|
|
58
62
|
import { registerListPoolTools } from "./tools/list-pool.js";
|
|
63
|
+
import { registerWhatsAppActionTools } from "./tools/whatsapp-actions.js";
|
|
64
|
+
import { registerGroupManagementTools } from "./tools/group-management.js";
|
|
65
|
+
import { registerPollTools } from "./tools/polls.js";
|
|
66
|
+
import { registerProfilePrivacyTools } from "./tools/profile-privacy.js";
|
|
67
|
+
import { registerSocialChannelsTools } from "./tools/social-channels.js";
|
|
68
|
+
import { registerScheduledMessageTools } from "./tools/scheduled-messages.js";
|
|
69
|
+
import { registerApprovalTools } from "./tools/approvals.js";
|
|
70
|
+
import { registerFlowTools } from "./tools/flows.js";
|
|
71
|
+
import { registerProductsTools } from "./tools/products.js";
|
|
59
72
|
function createServer() {
|
|
60
73
|
const server = new McpServer({
|
|
61
74
|
name: "neuron-mcp-server",
|
|
@@ -69,6 +82,9 @@ function createServer() {
|
|
|
69
82
|
registerConversationTools(server);
|
|
70
83
|
registerKnowledgeBaseTools(server);
|
|
71
84
|
registerToolsTools(server);
|
|
85
|
+
registerTaskTools(server);
|
|
86
|
+
registerLeadTools(server);
|
|
87
|
+
registerPersonaTools(server);
|
|
72
88
|
registerWebhooksTools(server);
|
|
73
89
|
registerReflectionsTools(server);
|
|
74
90
|
registerChannelsTools(server);
|
|
@@ -79,6 +95,7 @@ function createServer() {
|
|
|
79
95
|
registerOutboundWebhookTools(server);
|
|
80
96
|
registerContactsTools(server);
|
|
81
97
|
registerContactListsTools(server);
|
|
98
|
+
registerListCampaignTools(server);
|
|
82
99
|
registerBroadcastsTools(server);
|
|
83
100
|
registerBillingTools(server);
|
|
84
101
|
registerMediaTools(server);
|
|
@@ -89,6 +106,15 @@ function createServer() {
|
|
|
89
106
|
registerBlogTools(server);
|
|
90
107
|
registerNewsletterTools(server);
|
|
91
108
|
registerListPoolTools(server);
|
|
109
|
+
registerWhatsAppActionTools(server);
|
|
110
|
+
registerGroupManagementTools(server);
|
|
111
|
+
registerPollTools(server);
|
|
112
|
+
registerProfilePrivacyTools(server);
|
|
113
|
+
registerSocialChannelsTools(server);
|
|
114
|
+
registerScheduledMessageTools(server);
|
|
115
|
+
registerApprovalTools(server);
|
|
116
|
+
registerFlowTools(server);
|
|
117
|
+
registerProductsTools(server);
|
|
92
118
|
return server;
|
|
93
119
|
}
|
|
94
120
|
async function startStdio() {
|
|
@@ -162,17 +188,35 @@ async function startHttp() {
|
|
|
162
188
|
}
|
|
163
189
|
}
|
|
164
190
|
});
|
|
165
|
-
app.listen(PORT, "0.0.0.0", () => {
|
|
191
|
+
const httpServer = app.listen(PORT, "0.0.0.0", () => {
|
|
166
192
|
console.error(`Neuron MCP server listening on http://0.0.0.0:${PORT}/mcp`);
|
|
167
193
|
});
|
|
168
|
-
|
|
194
|
+
let shuttingDown = false;
|
|
195
|
+
const shutdownMcp = async () => {
|
|
196
|
+
if (shuttingDown)
|
|
197
|
+
return;
|
|
198
|
+
shuttingDown = true;
|
|
169
199
|
console.error("Shutting down...");
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
}
|
|
200
|
+
const forceTimer = setTimeout(() => {
|
|
201
|
+
console.error("MCP shutdown timed out, forcing exit");
|
|
202
|
+
process.exit(1);
|
|
203
|
+
}, 10_000);
|
|
204
|
+
forceTimer.unref();
|
|
205
|
+
// Stop accepting new connections and drain in-flight requests
|
|
206
|
+
await new Promise((resolve) => {
|
|
207
|
+
httpServer.close((err) => {
|
|
208
|
+
if (err)
|
|
209
|
+
console.error("Error closing HTTP server:", err);
|
|
210
|
+
resolve();
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
// Close all MCP session transports
|
|
214
|
+
await Promise.all(Object.keys(transports).map((sid) => transports[sid].close().catch(() => { }).then(() => { delete transports[sid]; })));
|
|
215
|
+
clearTimeout(forceTimer);
|
|
174
216
|
process.exit(0);
|
|
175
|
-
}
|
|
217
|
+
};
|
|
218
|
+
process.on("SIGINT", shutdownMcp);
|
|
219
|
+
process.on("SIGTERM", shutdownMcp);
|
|
176
220
|
}
|
|
177
221
|
const mode = process.env.MCP_TRANSPORT || "stdio";
|
|
178
222
|
if (mode === "http") {
|