overmind-mcp 2.8.0 → 2.8.1

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/.mcp.json.example CHANGED
@@ -14,27 +14,7 @@
14
14
  "transport": "httpStream",
15
15
  "url": "http://localhost:3141/mcp",
16
16
  "description": "Discord MCP - 88 outils sur port 3141"
17
- },
18
- "x-mcp-server": {
19
- "transport": "httpStream",
20
- "url": "http://localhost:3142/mcp",
21
- "description": "X/Twitter MCP - scraping/publish sur port 3142"
22
- },
23
- "debats-mcp-server": {
24
- "transport": "httpStream",
25
- "url": "http://localhost:3100/mcp",
26
- "description": "Débats MCP - analyse/arguments sur port 3100"
27
- },
28
- "news-btc-mcp": {
29
- "transport": "httpStream",
30
- "url": "http://localhost:3143/mcp",
31
- "description": "News BTC MCP - actualité crypto sur port 3143"
32
- },
33
- "news-core-mcp": {
34
- "transport": "httpStream",
35
- "url": "http://localhost:3144/mcp",
36
- "description": "News Core MCP - scraped news sur port 3144"
37
- }
17
+ }
38
18
  },
39
19
  "description": "Configuration MCP HTTP Singleton - Anti-Zombie. Tous les serveurs doivent être démarrés.",
40
20
  "version": "2.4.0"
@@ -121,57 +121,57 @@ netstat -an | findstr ":3000 " >nul && echo %ESC%[93m[WARN] Port 3000 utilise%ES
121
121
 
122
122
  echo.
123
123
 
124
- REM ============================================================
125
- REM STEP 5: Configuration MCP HTTP
126
- REM ============================================================
127
- echo %ESC%[36m=======================================================%ESC%
128
- echo %ESC%[36m[ STEP 5/8 ] CONFIGURATION MCP HTTP%ESC%
129
- echo %ESC%[36m=======================================================%ESC%
130
- echo.
131
- echo [INFO] Creation configuration MCP HTTP singleton...
132
- if not exist "%USERPROFILE%\.overmind\config" mkdir "%USERPROFILE%\.overmind\config"
133
-
134
- (
135
- echo {
136
- echo "mcpServers": {
137
- echo "overmind": {
138
- echo "transport": "http-stream",
139
- echo "url": "http://localhost:3099"
140
- echo },
141
- echo "memory": {
142
- echo "transport": "http-stream",
143
- echo "url": "http://localhost:3099"
144
- echo },
145
- echo "postgresql": {
146
- echo "transport": "http-stream",
147
- echo "url": "http://localhost:5433"
148
- echo },
149
- echo "discord": {
150
- echo "transport": "http-stream",
151
- echo "url": "http://localhost:3141"
152
- echo },
153
- echo "x": {
154
- echo "transport": "http-stream",
155
- echo "url": "http://localhost:3142"
156
- echo }
157
- echo }
158
- echo }
159
- ) > "%USERPROFILE%\.overmind\config\mcp-servers.json"
160
-
161
- echo %ESC%[92m[OK] Configuration MCP creee: %USERPROFILE%\.overmind\config\mcp-servers.json%ESC%
162
- echo.
163
- echo [INFO] Ports a lancer manuellement apres installation:
164
- echo Overmind: node cli.js --transport http-stream --port 3099
165
- echo PostgreSQL: node dist/index.js (FASTMCP_TRANSPORT=httpStream FASTMCP_PORT=5433)
166
- echo Discord: node dist/index.js (FASTMCP_TRANSPORT=httpStream FASTMCP_PORT=3141)
167
- echo X: node dist/src/server.js (FASTMCP_TRANSPORT=httpStream FASTMCP_PORT=3142)
168
- echo.
169
-
170
- REM STEP 6: PostgreSQL intelligent
171
- echo %ESC%[36m=======================================================%ESC%
172
- echo %ESC%[36m[ STEP 6/8 ] POSTGRESQL INTELLIGENT%ESC%
173
- echo %ESC%[36m=======================================================%ESC%
174
- echo.
124
+ REM ============================================================
125
+ REM STEP 5: Configuration MCP HTTP
126
+ REM ============================================================
127
+ echo %ESC%[36m=======================================================%ESC%
128
+ echo %ESC%[36m[ STEP 5/8 ] CONFIGURATION MCP HTTP%ESC%
129
+ echo %ESC%[36m=======================================================%ESC%
130
+ echo.
131
+ echo [INFO] Creation configuration MCP HTTP singleton...
132
+ if not exist "%USERPROFILE%\.overmind\config" mkdir "%USERPROFILE%\.overmind\config"
133
+
134
+ (
135
+ echo {
136
+ echo "mcpServers": {
137
+ echo "overmind": {
138
+ echo "transport": "http-stream",
139
+ echo "url": "http://localhost:3099"
140
+ echo },
141
+ echo "memory": {
142
+ echo "transport": "http-stream",
143
+ echo "url": "http://localhost:3099"
144
+ echo },
145
+ echo "postgresql": {
146
+ echo "transport": "http-stream",
147
+ echo "url": "http://localhost:5433"
148
+ echo },
149
+ echo "discord": {
150
+ echo "transport": "http-stream",
151
+ echo "url": "http://localhost:3141"
152
+ echo },
153
+ echo "x": {
154
+ echo "transport": "http-stream",
155
+ echo "url": "http://localhost:3142"
156
+ echo }
157
+ echo }
158
+ echo }
159
+ ) > "%USERPROFILE%\.overmind\config\mcp-servers.json"
160
+
161
+ echo %ESC%[92m[OK] Configuration MCP creee: %USERPROFILE%\.overmind\config\mcp-servers.json%ESC%
162
+ echo.
163
+ echo [INFO] Ports a lancer manuellement apres installation:
164
+ echo Overmind: node cli.js --transport http-stream --port 3099
165
+ echo PostgreSQL: node dist/index.js (FASTMCP_TRANSPORT=httpStream FASTMCP_PORT=5433)
166
+ echo Discord: node dist/index.js (FASTMCP_TRANSPORT=httpStream FASTMCP_PORT=3141)
167
+ echo X: node dist/src/server.js (FASTMCP_TRANSPORT=httpStream FASTMCP_PORT=3142)
168
+ echo.
169
+
170
+ REM STEP 6: PostgreSQL intelligent
171
+ echo %ESC%[36m=======================================================%ESC%
172
+ echo %ESC%[36m[ STEP 6/8 ] POSTGRESQL INTELLIGENT%ESC%
173
+ echo %ESC%[36m=======================================================%ESC%
174
+ echo.
175
175
 
176
176
  if "%USE_EXTERNAL_POSTGRES%"=="1" (
177
177
  echo %ESC%[92m[OK] Utilisation PostgreSQL existant: %POSTGRES_CONTAINER%%ESC%
@@ -0,0 +1,248 @@
1
+ /**
2
+ * overmind-pool.mjs — Lightweight Node.js client for Overmind HTTP MCP
3
+ * ═══════════════════════════════════════════════════════════════════════
4
+ *
5
+ * Pure ESM — no compile step needed. Requires Node 18+.
6
+ *
7
+ * CLI usage:
8
+ * node overmind-pool.mjs --status
9
+ * node overmind-pool.mjs --agents
10
+ * node overmind-pool.mjs --pool
11
+ * node overmind-pool.mjs --run <name> <runner> <prompt>
12
+ * node overmind-pool.mjs --create <name> <runner> <prompt>
13
+ * node overmind-pool.mjs --kill <name>
14
+ *
15
+ * As module:
16
+ * import { OvermindPool } from './overmind-pool.mjs';
17
+ */
18
+
19
+ const BASE = 'http://localhost:3099/mcp';
20
+ const HEALTH = 'http://localhost:3099/health';
21
+ const AUTH = process.env.OVERMIND_AUTH || 'changeme';
22
+
23
+ // ─── HTTP ──────────────────────────────────────────────────────────────────────
24
+
25
+ async function mcpCall(method, params = {}, timeoutMs = 90_000) {
26
+ const res = await fetch(BASE, {
27
+ method: 'POST',
28
+ headers: {
29
+ 'Content-Type': 'application/json',
30
+ 'Accept': 'application/json, text/event-stream',
31
+ 'Authorization': `Bearer ${AUTH}`,
32
+ },
33
+ body: JSON.stringify({ jsonrpc: '2.0', id: Date.now(), method, params }),
34
+ signal: AbortSignal.timeout(timeoutMs),
35
+ });
36
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
37
+ const text = await res.text();
38
+ for (const line of text.split('\n')) {
39
+ const t = line.trim();
40
+ if (t.startsWith('data: ')) {
41
+ const d = JSON.parse(t.slice(6));
42
+ if (d.result) return d.result;
43
+ if (d.error) throw new Error(d.error.message);
44
+ }
45
+ }
46
+ throw new Error('No result in SSE response');
47
+ }
48
+
49
+ async function mcpTool(name, args = {}, timeoutMs = 90_000) {
50
+ return mcpCall('tools/call', { name, arguments: args }, timeoutMs);
51
+ }
52
+
53
+ // ─── OvermindPool ─────────────────────────────────────────────────────────────
54
+
55
+ export class OvermindPool {
56
+ /** Check if MCP server is alive */
57
+ async health() {
58
+ try {
59
+ const r = await fetch(HEALTH, {
60
+ headers: { 'Authorization': `Bearer ${AUTH}` },
61
+ signal: AbortSignal.timeout(3000),
62
+ });
63
+ return r.ok;
64
+ } catch { return false; }
65
+ }
66
+
67
+ /** List all registered agent names */
68
+ async listAgents() {
69
+ const r = await mcpTool('list_agents');
70
+ const text = r.content?.[0]?.text ?? '';
71
+ return text.split('\n').filter(l => l.trim().startsWith('- ')).map(l => l.trim().slice(2));
72
+ }
73
+
74
+ /** Create an agent definition in the registry */
75
+ async createAgent({ name, runner = 'claude', prompt }) {
76
+ return mcpTool('create_agent', { name, runner, prompt });
77
+ }
78
+
79
+ /** Delete an agent from the registry */
80
+ async deleteAgent(name) {
81
+ return mcpTool('delete_agent', { agentName: name });
82
+ }
83
+
84
+ /**
85
+ * Ensure agents exist (create missing ones).
86
+ * Returns names of agents that were created.
87
+ */
88
+ async ensureAgents(agents) {
89
+ const existing = await this.listAgents();
90
+ const created = [];
91
+ for (const a of agents) {
92
+ if (!existing.includes(a.agentName)) {
93
+ await this.createAgent({ name: a.agentName, runner: a.runner, prompt: a.prompt });
94
+ created.push(a.agentName);
95
+ await new Promise(r => setTimeout(r, 300));
96
+ }
97
+ }
98
+ return created;
99
+ }
100
+
101
+ /**
102
+ * Run a single agent. runner is REQUIRED.
103
+ * Valid runners: claude | gemini | kilo | qwencli | openclaw | cline | opencode | hermes
104
+ */
105
+ async runAgent({ agentName, runner, prompt, timeoutMs = 90_000 }) {
106
+ if (!runner) throw new Error('runner is required (claude|gemini|kilo|qwencli|openclaw|cline|opencode|hermes)');
107
+ const t0 = Date.now();
108
+ const args = { runner, agentName, prompt, timeoutMs };
109
+ const r = await mcpTool('run_agent', args, timeoutMs + 15_000);
110
+ return {
111
+ agentName,
112
+ output: r.content?.[0]?.text ?? '',
113
+ sessionId: r.sessionId,
114
+ durationMs: Date.now() - t0,
115
+ };
116
+ }
117
+
118
+ /** Run N agents in parallel; errors are captured in the result object */
119
+ async runPool(agents) {
120
+ const settled = await Promise.allSettled(
121
+ agents.map(a => this.runAgent(a))
122
+ );
123
+ return settled.map((r, i) =>
124
+ r.status === 'fulfilled'
125
+ ? r.value
126
+ : { agentName: agents[i].agentName, output: `Error: ${r.reason?.message ?? String(r.reason)}`, durationMs: 0 }
127
+ );
128
+ }
129
+
130
+ /** Lifecycle: status of an agent */
131
+ async status(agentName, runner) {
132
+ const r = await mcpTool('agent_control', { agentName, runner, action: 'status' });
133
+ return r.content?.[0]?.text ?? '';
134
+ }
135
+
136
+ /** Lifecycle: non-blocking output stream */
137
+ async stream(agentName, runner) {
138
+ const r = await mcpTool('agent_control', { agentName, runner, action: 'stream' });
139
+ const text = r.content?.[0]?.text ?? '';
140
+ return { text, isComplete: text.includes('**isComplete:** true') };
141
+ }
142
+
143
+ /** Lifecycle: block until agent finishes */
144
+ async wait(agentName, timeoutMs = 900_000, runner) {
145
+ const r = await mcpTool('agent_control', { agentName, runner, action: 'wait', timeoutMs }, timeoutMs + 10_000);
146
+ return r.content?.[0]?.text ?? '';
147
+ }
148
+
149
+ /** Lifecycle: force-kill a running agent */
150
+ async kill(agentName, runner) {
151
+ const r = await mcpTool('agent_control', { agentName, runner, action: 'kill' });
152
+ return r.content?.[0]?.text ?? '';
153
+ }
154
+ }
155
+
156
+ // ─── Demo pool ────────────────────────────────────────────────────────────────
157
+
158
+ export const DEMO_POOL = [
159
+ { agentName: 'pool_dev', runner: 'claude', prompt: 'Réponds en 1 phrase: quelle est la couleur du ciel ?' },
160
+ { agentName: 'pool_archi', runner: 'kilo', prompt: "Décris l'architecture microservices en 2 points." },
161
+ { agentName: 'pool_probe', runner: 'gemini', prompt: 'Réponds exactement: PONG' },
162
+ { agentName: 'pool_guard', runner: 'hermes', prompt: "Rapporte l'état du système en 1 phrase." },
163
+ { agentName: 'pool_sentinel', runner: 'hermes', prompt: 'Liste 2 métriques serveur importantes.' },
164
+ ];
165
+
166
+ // ─── CLI ──────────────────────────────────────────────────────────────────────
167
+
168
+ async function cli() {
169
+ const pool = new OvermindPool();
170
+ const args = process.argv.slice(2);
171
+
172
+ if (args.includes('--status')) {
173
+ const ok = await pool.health();
174
+ console.log(ok ? '✓ Overmind MCP online' : '✗ Overmind MCP offline');
175
+ process.exit(ok ? 0 : 1);
176
+ }
177
+
178
+ if (args.includes('--agents')) {
179
+ const list = await pool.listAgents();
180
+ console.log(`\n${list.length} agents:\n`);
181
+ list.forEach(a => console.log(' ', a));
182
+ process.exit(0);
183
+ }
184
+
185
+ if (args.includes('--pool')) {
186
+ console.log('\n═══ Overmind Pool Demo ═══\n');
187
+ const ok = await pool.health();
188
+ console.log(`[health] ${ok ? '✓' : '✗'} MCP server\n`);
189
+ if (!ok) { console.error('MCP offline'); process.exit(1); }
190
+
191
+ const existing = await pool.listAgents();
192
+ const toCreate = DEMO_POOL.filter(a => !existing.includes(a.agentName));
193
+ if (toCreate.length) {
194
+ const created = await pool.ensureAgents(toCreate);
195
+ console.log(`[created] ${created.join(', ')}\n`);
196
+ }
197
+
198
+ console.log('[run] Lancement parallèle...\n');
199
+ const results = await pool.runPool(DEMO_POOL);
200
+
201
+ for (const r of results) {
202
+ const raw = r.output.trim();
203
+ // Gemini returns structured JSON, Hermes often returns empty
204
+ const isGeminiJson = raw.startsWith('{') && raw.includes('"response"');
205
+ const isHermesEmpty = raw === '' || raw === '{"result":null}' || raw === '{}';
206
+ const isRealError = !isGeminiJson && !isHermesEmpty && raw.includes('Error');
207
+ const hasContent = raw.length > 0 && !isHermesEmpty;
208
+ console.log(`${isRealError ? '✗' : hasContent ? '✓' : '·'} [${r.agentName}] (${r.durationMs}ms): ${raw.slice(0, 100).trim() || '(empty)'}`);
209
+ }
210
+ process.exit(0);
211
+ }
212
+
213
+ if (args.includes('--run')) {
214
+ const idx = args.indexOf('--run');
215
+ const name = args[idx + 1];
216
+ const runner = args[idx + 2];
217
+ const prompt = args[idx + 3] ?? 'PING';
218
+ if (!name || !runner) { console.error('Usage: --run <name> <runner> <prompt>'); process.exit(1); }
219
+ const r = await pool.runAgent({ agentName: name, runner, prompt, timeoutMs: 60_000 });
220
+ console.log(`[${name}] (${r.durationMs}ms): ${r.output.slice(0, 200).trim()}`);
221
+ process.exit(0);
222
+ }
223
+
224
+ if (args.includes('--create')) {
225
+ const idx = args.indexOf('--create');
226
+ const name = args[idx + 1];
227
+ const runner = args[idx + 2] ?? 'claude';
228
+ const prompt = args[idx + 3] ?? 'Tu es un agent de test.';
229
+ if (!name) { console.error('Usage: --create <name> <runner> <prompt>'); process.exit(1); }
230
+ await pool.createAgent({ name, runner, prompt });
231
+ console.log(`✓ Agent '${name}' créé (runner: ${runner})`);
232
+ process.exit(0);
233
+ }
234
+
235
+ if (args.includes('--kill')) {
236
+ const idx = args.indexOf('--kill');
237
+ const name = args[idx + 1];
238
+ if (!name) { console.error('Usage: --kill <agentName>'); process.exit(1); }
239
+ console.log(await pool.kill(name));
240
+ process.exit(0);
241
+ }
242
+
243
+ // Default: info
244
+ console.log(`OvermindPool — ${BASE}`);
245
+ console.log('Usage: --status | --agents | --pool | --run <name> <runner> <prompt> | --create <name> <runner> <prompt> | --kill <name>');
246
+ }
247
+
248
+ cli().catch(e => { console.error(e.message); process.exit(1); });
@@ -459,34 +459,31 @@ console.log('Résultat:', result.error ?? result.result);
459
459
 
460
460
  ---
461
461
 
462
- ## Outil : overmind-serve.bat
462
+ ## Outil : bin/install-overmind-windows.bat
463
463
 
464
464
  ```batch
465
- :: Lancer le serveur Overmind MCP
466
- overmind-serve.bat Start (ou restart si déjà lancé)
467
- overmind-serve.bat stop Arrêt propre
468
- overmind-serve.bat restart Restart
469
- overmind-serve.bat status Voir si ça tourne
470
- overmind-serve.bat tail 20 dernières lignes du log
471
- overmind-serve.bat kill Kill forcé
472
-
473
- :: Fonctionne même si le script est lancé depuis un autre répertoire
474
- cd C:\ && overmind-serve.bat status
465
+ :: Lancer le serveur Overmind MCP (via le script d'installation)
466
+ bin\install-overmind-windows.bat Start (ou restart si déjà lancé)
467
+ bin\install-overmind-windows.bat stop Arrêt propre
468
+ bin\install-overmind-windows.bat restart Restart
469
+ bin\install-overmind-windows.bat status Voir si ça tourne
470
+ bin\install-overmind-windows.bat tail 20 dernières lignes du log
471
+ bin\install-overmind-windows.bat kill Kill forcé
475
472
  ```
476
473
 
477
- Log : `Workflow/logs/overmind.log`
478
- PID file : `Workflow/overmind.pid`
474
+ Log : `Workflow/logs/overmind.log`
475
+ PID file : `Workflow/overmind.pid`
479
476
  Health : `curl http://localhost:3099/health`
480
477
 
481
478
  ## Outil : overmind-pool.mjs (client CLI)
482
479
 
483
480
  ```bash
484
- node overmind-pool.mjs --status # health check
485
- node overmind-pool.mjs --agents # lister agents
486
- node overmind-pool.mjs --pool # demo 5 agents
487
- node overmind-pool.mjs --run <n> <r> <p> # run un agent
488
- node overmind-pool.mjs --create <n> <r> <p> # créer un agent
489
- node overmind-pool.mjs --kill <name> # tuer un agent
481
+ node bin/overmind-pool.mjs --status # health check
482
+ node bin/overmind-pool.mjs --agents # lister agents
483
+ node bin/overmind-pool.mjs --pool # demo 5 agents
484
+ node bin/overmind-pool.mjs --run <n> <r> <p> # run un agent
485
+ node bin/overmind-pool.mjs --create <n> <r> <p> # créer un agent
486
+ node bin/overmind-pool.mjs --kill <name> # tuer un agent
490
487
  ```
491
488
 
492
489
  ## Comparatif rapide
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "overmind-mcp",
3
- "version": "2.8.0",
3
+ "version": "2.8.1",
4
4
  "preferGlobal": true,
5
5
  "description": "Orchestrateur universel agents IA multi-modeles via MCP. Inclut le protocole 'Custom-Nickname' pour identifier vos agents avec des surnoms originaux (The Chaos Prophet, Shadow Sniper, etc.), l'isolation mémoire (Private Memory Context) et le support pour QwenCli et Nous Hermes. Installation automatique des dépendances Docker (PostgreSQL, pgvector) inclus.",
6
6
  "type": "module",