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.
Files changed (150) hide show
  1. package/.env +13 -0
  2. package/AI_PERSONALITY_DESIGN_RESEARCH.md +1020 -0
  3. package/Dockerfile +18 -0
  4. package/README.md +146 -131
  5. package/dist/client.d.ts +6 -0
  6. package/dist/client.js +50 -12
  7. package/dist/client.js.map +1 -1
  8. package/dist/index.js +51 -7
  9. package/dist/index.js.map +1 -1
  10. package/dist/tools/ai.js +9 -3
  11. package/dist/tools/ai.js.map +1 -1
  12. package/dist/tools/approvals.d.ts +2 -0
  13. package/dist/tools/approvals.js +181 -0
  14. package/dist/tools/approvals.js.map +1 -0
  15. package/dist/tools/audit.js +7 -4
  16. package/dist/tools/audit.js.map +1 -1
  17. package/dist/tools/auth.js +119 -19
  18. package/dist/tools/auth.js.map +1 -1
  19. package/dist/tools/billing.js +22 -6
  20. package/dist/tools/billing.js.map +1 -1
  21. package/dist/tools/blog.js +98 -34
  22. package/dist/tools/blog.js.map +1 -1
  23. package/dist/tools/bot-api-keys.js +27 -12
  24. package/dist/tools/bot-api-keys.js.map +1 -1
  25. package/dist/tools/bot-api.js +53 -27
  26. package/dist/tools/bot-api.js.map +1 -1
  27. package/dist/tools/bots.js +116 -68
  28. package/dist/tools/bots.js.map +1 -1
  29. package/dist/tools/broadcasts.js +78 -38
  30. package/dist/tools/broadcasts.js.map +1 -1
  31. package/dist/tools/builtin-tools.js +19 -12
  32. package/dist/tools/builtin-tools.js.map +1 -1
  33. package/dist/tools/campaigns.js +149 -61
  34. package/dist/tools/campaigns.js.map +1 -1
  35. package/dist/tools/channels.js +163 -53
  36. package/dist/tools/channels.js.map +1 -1
  37. package/dist/tools/contact-lists.js +111 -51
  38. package/dist/tools/contact-lists.js.map +1 -1
  39. package/dist/tools/contacts.js +117 -44
  40. package/dist/tools/contacts.js.map +1 -1
  41. package/dist/tools/conversations.js +95 -50
  42. package/dist/tools/conversations.js.map +1 -1
  43. package/dist/tools/flows.d.ts +2 -0
  44. package/dist/tools/flows.js +242 -0
  45. package/dist/tools/flows.js.map +1 -0
  46. package/dist/tools/group-management.d.ts +2 -0
  47. package/dist/tools/group-management.js +239 -0
  48. package/dist/tools/group-management.js.map +1 -0
  49. package/dist/tools/leads.d.ts +2 -0
  50. package/dist/tools/leads.js +100 -0
  51. package/dist/tools/leads.js.map +1 -0
  52. package/dist/tools/list-campaigns.d.ts +2 -0
  53. package/dist/tools/list-campaigns.js +152 -0
  54. package/dist/tools/list-campaigns.js.map +1 -0
  55. package/dist/tools/list-pool.js +250 -33
  56. package/dist/tools/list-pool.js.map +1 -1
  57. package/dist/tools/media.js +12 -7
  58. package/dist/tools/media.js.map +1 -1
  59. package/dist/tools/newsletters.js +106 -26
  60. package/dist/tools/newsletters.js.map +1 -1
  61. package/dist/tools/organizations.js +76 -35
  62. package/dist/tools/organizations.js.map +1 -1
  63. package/dist/tools/outbound-webhooks.js +32 -20
  64. package/dist/tools/outbound-webhooks.js.map +1 -1
  65. package/dist/tools/payouts.js +44 -17
  66. package/dist/tools/payouts.js.map +1 -1
  67. package/dist/tools/personas.d.ts +2 -0
  68. package/dist/tools/personas.js +141 -0
  69. package/dist/tools/personas.js.map +1 -0
  70. package/dist/tools/polls.d.ts +2 -0
  71. package/dist/tools/polls.js +30 -0
  72. package/dist/tools/polls.js.map +1 -0
  73. package/dist/tools/pool.js +101 -43
  74. package/dist/tools/pool.js.map +1 -1
  75. package/dist/tools/products.d.ts +2 -0
  76. package/dist/tools/products.js +277 -0
  77. package/dist/tools/products.js.map +1 -0
  78. package/dist/tools/profile-privacy.d.ts +2 -0
  79. package/dist/tools/profile-privacy.js +195 -0
  80. package/dist/tools/profile-privacy.js.map +1 -0
  81. package/dist/tools/reflections.js +25 -13
  82. package/dist/tools/reflections.js.map +1 -1
  83. package/dist/tools/scheduled-messages.d.ts +2 -0
  84. package/dist/tools/scheduled-messages.js +124 -0
  85. package/dist/tools/scheduled-messages.js.map +1 -0
  86. package/dist/tools/social-channels.d.ts +2 -0
  87. package/dist/tools/social-channels.js +318 -0
  88. package/dist/tools/social-channels.js.map +1 -0
  89. package/dist/tools/tasks.d.ts +2 -0
  90. package/dist/tools/tasks.js +155 -0
  91. package/dist/tools/tasks.js.map +1 -0
  92. package/dist/tools/tools.js +86 -40
  93. package/dist/tools/tools.js.map +1 -1
  94. package/dist/tools/wallets.js +34 -12
  95. package/dist/tools/wallets.js.map +1 -1
  96. package/dist/tools/webhooks.js +35 -20
  97. package/dist/tools/webhooks.js.map +1 -1
  98. package/dist/tools/whatsapp-actions.d.ts +2 -0
  99. package/dist/tools/whatsapp-actions.js +186 -0
  100. package/dist/tools/whatsapp-actions.js.map +1 -0
  101. package/package.json +4 -31
  102. package/scripts/setup-delivahere-bot.ts +804 -0
  103. package/scripts/test-delivahere-bot.ts +128 -0
  104. package/scripts/update-letschop-prompt.ts +194 -0
  105. package/server.json +26 -0
  106. package/smithery.yaml +19 -0
  107. package/src/client.ts +169 -0
  108. package/src/index.ts +256 -0
  109. package/src/tools/ai.ts +35 -0
  110. package/src/tools/approvals.ts +231 -0
  111. package/src/tools/audit.ts +49 -0
  112. package/src/tools/auth.ts +536 -0
  113. package/src/tools/billing.ts +79 -0
  114. package/src/tools/blog.ts +264 -0
  115. package/src/tools/bot-api-keys.ts +87 -0
  116. package/src/tools/bot-api.ts +193 -0
  117. package/src/tools/bots.ts +320 -0
  118. package/src/tools/broadcasts.ts +224 -0
  119. package/src/tools/builtin-tools.ts +108 -0
  120. package/src/tools/campaigns.ts +429 -0
  121. package/src/tools/channels.ts +520 -0
  122. package/src/tools/contact-lists.ts +320 -0
  123. package/src/tools/contacts.ts +395 -0
  124. package/src/tools/conversations.ts +349 -0
  125. package/src/tools/flows.ts +298 -0
  126. package/src/tools/group-management.ts +265 -0
  127. package/src/tools/knowledge-bases.ts +451 -0
  128. package/src/tools/leads.ts +104 -0
  129. package/src/tools/list-campaigns.ts +190 -0
  130. package/src/tools/list-pool.ts +389 -0
  131. package/src/tools/media.ts +50 -0
  132. package/src/tools/newsletters.ts +271 -0
  133. package/src/tools/organizations.ts +287 -0
  134. package/src/tools/outbound-webhooks.ts +181 -0
  135. package/src/tools/payouts.ts +133 -0
  136. package/src/tools/personas.ts +145 -0
  137. package/src/tools/polls.ts +32 -0
  138. package/src/tools/pool.ts +293 -0
  139. package/src/tools/products.ts +280 -0
  140. package/src/tools/profile-privacy.ts +215 -0
  141. package/src/tools/reflections.ts +124 -0
  142. package/src/tools/scheduled-messages.ts +144 -0
  143. package/src/tools/social-channels.ts +396 -0
  144. package/src/tools/tasks.ts +198 -0
  145. package/src/tools/tools.ts +255 -0
  146. package/src/tools/wallets.ts +107 -0
  147. package/src/tools/webhooks.ts +166 -0
  148. package/src/tools/whatsapp-actions.ts +203 -0
  149. package/tsconfig.json +20 -0
  150. 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
- > WhatsApp automation platform with 120+ MCP tools for AI-powered chatbots, broadcasts, campaigns, and more.
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
- [![npm version](https://img.shields.io/npm/v/neuron-mcp-server)](https://www.npmjs.com/package/neuron-mcp-server)
6
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+ ## Connect
7
6
 
8
- ## What is Neuron?
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
- [Neuron](https://neuron.ng) is an AI-powered WhatsApp automation platform. This MCP server exposes **120+ tools** that let AI coding assistants — Claude Code, Cursor, Windsurf, and other MCP-compatible clients — manage your entire WhatsApp business programmatically.
10
+ ## Auth
11
11
 
12
- Build chatbots, send broadcasts, manage contacts, create campaigns, publish newsletters, and more — all through natural language with your AI assistant.
12
+ Two token types are used:
13
13
 
14
- ## Quick Start
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
- ### Option 1: Remote Server (Recommended — zero install)
17
+ ---
17
18
 
18
- Add to your MCP client config:
19
+ ## Approvals — human-in-the-loop sign-off
19
20
 
20
- ```json
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
- No installation required. Works immediately with any MCP client that supports Streamable HTTP.
23
+ **Tools** (all take `apiKey`, a bot API key with the `nrn_` prefix):
32
24
 
33
- ### Option 2: Local Server (via npm)
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
- Run directly with npx:
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
- ```bash
38
- npx neuron-mcp-server
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
- Or install globally:
42
-
43
- ```bash
44
- npm install -g neuron-mcp-server
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
- Claude Code config (`~/.claude/mcp.json`):
48
-
49
- ```json
50
- {
51
- "mcpServers": {
52
- "neuron": {
53
- "command": "npx",
54
- "args": ["-y", "neuron-mcp-server"]
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
- ## Authentication
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
- Three ways to authenticate:
81
+ ### Callback schemes
63
82
 
64
- ### 1. Browser Login (Recommended)
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
- Call `neuron_login()` with no arguments. The server returns a URL — open it in your browser to authorize securely. No credentials are shared with the AI.
87
+ Full endpoint reference: `https://api.neuron.ng/api/docs` (see the **Approvals** tag).
67
88
 
68
- ### 2. MCP Token
89
+ ## Tasks — scheduled autonomous bot actions
69
90
 
70
- Generate a token from your Neuron dashboard (**Settings > MCP Tokens**), then:
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
- neuron_login({ token: "your-mcp-token" })
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
- ### 3. Environment Variable
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
- Set `NEURON_AUTH_TOKEN` for unattended/CI use:
100
+ These tools use the session token (from `neuron_login`).
79
101
 
80
- ```bash
81
- NEURON_AUTH_TOKEN=your-token npx neuron-mcp-server
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
- ## Available Tools (120+)
85
-
86
- | Category | Tools | Description |
87
- |----------|-------|-------------|
88
- | **Authentication** | 8 | Login, register, org switching, profile management |
89
- | **Bot Management** | 7 | Create and manage AI chatbots with configurable LLM models |
90
- | **Conversations** | 11 | Message management, human takeover, send WhatsApp messages |
91
- | **Knowledge Bases** | 14 | Upload documents, semantic search, sync, ingest content |
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
- Or use the remote server:
134
-
135
- ```json
136
- {
137
- "mcpServers": {
138
- "neuron": {
139
- "type": "url",
140
- "url": "https://mcp.neuron.ng/mcp"
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
- ### Cursor
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
- **Settings > MCP Servers > Add Streamable HTTP**
141
+ ## Leads — lead generation
149
142
 
150
- URL: `https://mcp.neuron.ng/mcp`
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
- ### Windsurf
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
- **Settings > AI > MCP Servers > Add**
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
- Use either the remote URL or local npx command.
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
- ## Development
159
+ **Live / external scrapers** push leads in continuously with a **bot API key** (not the session token):
159
160
 
160
161
  ```bash
161
- git clone https://github.com/conquext/neuron-mcp-server.git
162
- cd neuron-mcp-server
163
- npm install
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
- ## Links
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
- - **Website:** [neuron.ng](https://neuron.ng)
170
- - **Documentation:** [neuron.ng/docs](https://neuron.ng/docs)
171
- - **MCP Server Docs:** [neuron.ng/docs/mcp-server](https://neuron.ng/docs/mcp-server)
172
- - **npm:** [npmjs.com/package/neuron-mcp-server](https://www.npmjs.com/package/neuron-mcp-server)
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
- Free to start — no credit card required.
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
- ## License
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
- [MIT](LICENSE)
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 BASE_URL = isDockerInternal ? "https://api.neuron.ng/api/v1" : (envUrl || "https://api.neuron.ng/api/v1");
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 readCachedToken() {
14
+ function readCachedTokens() {
12
15
  try {
13
16
  const raw = readFileSync(TOKEN_CACHE_FILE, "utf-8");
14
17
  const cache = JSON.parse(raw);
15
- if (cache.baseUrl === BASE_URL && cache.token) {
16
- return cache.token;
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 writeCachedToken(token) {
32
+ function writeCachedTokens() {
25
33
  try {
26
34
  mkdirSync(TOKEN_CACHE_DIR, { recursive: true, mode: 0o700 });
27
- writeFileSync(TOKEN_CACHE_FILE, JSON.stringify({ baseUrl: BASE_URL, token }), { mode: 0o600 });
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
- let authToken = process.env.NEURON_AUTH_TOKEN || readCachedToken();
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
- writeCachedToken(token);
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 BASE_URL;
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: `${BASE_URL}/${cleanEndpoint}`,
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 || BASE_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") {
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
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,EAAE,MAAM,SAAS,CAAC;AACjE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,uGAAuG;AACvG,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,EAAE,CAAC;AAChD,MAAM,gBAAgB,GAAG,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC;AAC1H,MAAM,gBAAgB,GAAG,gBAAgB,CAAC,CAAC,CAAC,8BAA8B,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,8BAA8B,CAAC,CAAC;AAExH,IAAI,OAAO,GAAG,gBAAgB,CAAC;AAE/B,gFAAgF;AAChF,MAAM,UAAU,GAA2B,EAAE,CAAC;AAE9C,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC;AACnD,MAAM,gBAAgB,GAAG,IAAI,CAAC,eAAe,EAAE,sBAAsB,CAAC,CAAC;AAEvE,SAAS,gBAAgB;IACvB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC;QACpD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC9B,qCAAqC;QACrC,IAAI,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC;YACrD,OAAO,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC;QAC1C,CAAC;QACD,wBAAwB;QACxB,IAAI,KAAK,CAAC,SAAS,IAAI,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ,EAAE,CAAC;YAC3D,OAAO,KAAK,CAAC,SAAmC,CAAC;QACnD,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,uCAAuC;IACzC,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,SAAS,iBAAiB;IACxB,IAAI,CAAC;QACH,SAAS,CAAC,eAAe,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAC7D,aAAa,CACX,gBAAgB,EAChB,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,UAAU,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC,EACjE,EAAE,IAAI,EAAE,KAAK,EAAE,CAChB,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,6BAA6B;IAC/B,CAAC;AACH,CAAC;AAED,2EAA2E;AAC3E,MAAM,YAAY,GAAG,gBAAgB,EAAE,CAAC;AACxC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;IACxD,UAAU,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAC1B,CAAC;AAED,IAAI,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,UAAU,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;AAE3E,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,SAAS,GAAG,KAAK,CAAC;IAClB,IAAI,KAAK,EAAE,CAAC;QACV,UAAU,CAAC,OAAO,CAAC,GAAG,KAAK,CAAC;IAC9B,CAAC;SAAM,CAAC;QACN,OAAO,UAAU,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IACD,iBAAiB,EAAE,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,0CAA0C;IAC1C,IAAI,SAAS,EAAE,CAAC;QACd,UAAU,CAAC,OAAO,CAAC,GAAG,SAAS,CAAC;IAClC,CAAC;IACD,yBAAyB;IACzB,OAAO,GAAG,GAAG,CAAC;IACd,4EAA4E;IAC5E,SAAS,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;IAClC,iBAAiB,EAAE,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,MAAM,IAAI,GAAG,IAAI,GAAG,CAAS,CAAC,OAAO,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IACpE,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACpC,GAAG;QACH,MAAM,EAAE,GAAG,KAAK,OAAO;QACvB,aAAa,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC;KACjC,CAAC,CAAC,CAAC;AACN,CAAC;AAQD,MAAM,CAAC,KAAK,UAAU,GAAG,CACvB,MAAmD,EACnD,QAAgB,EAChB,IAAc,EACd,MAAoD,EACpD,OAAgC;IAEhC,IAAI,CAAC;QACH,MAAM,WAAW,GAAoC,EAAE,CAAC;QACxD,IAAI,MAAM,EAAE,CAAC;YACX,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC5C,IAAI,CAAC,KAAK,SAAS;oBAAE,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YAC1C,CAAC;QACH,CAAC;QAED,MAAM,aAAa,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QACnD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC;YAC3B,MAAM;YACN,GAAG,EAAE,GAAG,OAAO,IAAI,aAAa,EAAE;YAClC,IAAI;YACJ,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS;YACrE,OAAO,EAAE,KAAK;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,MAAM,EAAE,kBAAkB;gBAC1B,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,UAAU,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC9D,GAAG,OAAO;aACX;SACF,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC,IAAsB,CAAC;IACzC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,UAAU,IAAI,KAAK,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC;YACxD,OAAO,KAAK,CAAC,QAAQ,CAAC,IAAsB,CAAC;QAC/C,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAc;IACxC,IAAI,KAAK,YAAY,UAAU,EAAE,CAAC;QAChC,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;YACnB,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAmB,CAAC;YAChD,MAAM,GAAG,GAAG,IAAI,EAAE,KAAK,EAAE,OAAO,IAAI,QAAQ,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;YACpE,OAAO,UAAU,GAAG,EAAE,CAAC;QACzB,CAAC;QACD,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,EAAE,GAAG,IAAI,OAAO,CAAC;QACzC,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc;YAAE,OAAO,0CAA0C,GAAG,EAAE,CAAC;QAC1F,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;YAClC,OAAO,gCAAgC,GAAG,0FAA0F,CAAC;QACvI,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW;YAAE,OAAO,gCAAgC,GAAG,kCAAkC,CAAC;QAC7G,OAAO,yBAAyB,KAAK,CAAC,IAAI,IAAI,SAAS,MAAM,KAAK,CAAC,OAAO,WAAW,GAAG,EAAE,CAAC;IAC7F,CAAC;IACD,OAAO,UAAU,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;AAC5E,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAa;IACtC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;AACvF,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;AACxD,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAc;IACxC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC3F,CAAC"}
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
- process.on("SIGINT", async () => {
194
+ let shuttingDown = false;
195
+ const shutdownMcp = async () => {
196
+ if (shuttingDown)
197
+ return;
198
+ shuttingDown = true;
169
199
  console.error("Shutting down...");
170
- for (const sid of Object.keys(transports)) {
171
- await transports[sid].close().catch(() => { });
172
- delete transports[sid];
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") {