morpheus-cli 0.2.6 → 0.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -209,7 +209,8 @@ The Morpheus Telegram bot supports several commands for interacting with the age
|
|
|
209
209
|
- `/help` - Show available commands
|
|
210
210
|
- `/zaion` - Show system configurations
|
|
211
211
|
- `/sati <qnt>` - Show specific memories
|
|
212
|
-
- `/restart` -
|
|
212
|
+
- `/restart` - Restart the Morpheus agent
|
|
213
|
+
- `/mcp` or `/mcps` - List registered MCP servers
|
|
213
214
|
|
|
214
215
|
## Development Setup
|
|
215
216
|
|
|
@@ -316,6 +317,230 @@ Morpheus supports external tools via **MCP (Model Context Protocol)**. Configure
|
|
|
316
317
|
|
|
317
318
|
Morpheus exposes several API endpoints for programmatic access to its features:
|
|
318
319
|
|
|
320
|
+
### Health Check Endpoints
|
|
321
|
+
|
|
322
|
+
#### GET `/health`
|
|
323
|
+
Public health check endpoint without authentication.
|
|
324
|
+
|
|
325
|
+
* **Response:**
|
|
326
|
+
```json
|
|
327
|
+
{
|
|
328
|
+
"status": "healthy",
|
|
329
|
+
"timestamp": "2026-02-05T21:30:00.000Z",
|
|
330
|
+
"uptime": 123.45
|
|
331
|
+
}
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
#### GET `/api/health`
|
|
335
|
+
Health check endpoint for the API (requires authentication).
|
|
336
|
+
|
|
337
|
+
* **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
|
|
338
|
+
* **Response:**
|
|
339
|
+
```json
|
|
340
|
+
{
|
|
341
|
+
"status": "healthy",
|
|
342
|
+
"timestamp": "2026-02-05T21:30:00.000Z",
|
|
343
|
+
"uptime": 123.45
|
|
344
|
+
}
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### Status Endpoint
|
|
348
|
+
|
|
349
|
+
#### GET `/api/status`
|
|
350
|
+
Get the current status of the Morpheus agent.
|
|
351
|
+
|
|
352
|
+
* **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
|
|
353
|
+
* **Response:**
|
|
354
|
+
```json
|
|
355
|
+
{
|
|
356
|
+
"status": "online",
|
|
357
|
+
"uptimeSeconds": 1234.56,
|
|
358
|
+
"pid": 12345,
|
|
359
|
+
"projectVersion": "1.0.0",
|
|
360
|
+
"nodeVersion": "v18.17.0",
|
|
361
|
+
"agentName": "Morpheus",
|
|
362
|
+
"llmProvider": "openai",
|
|
363
|
+
"llmModel": "gpt-4-turbo"
|
|
364
|
+
}
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
### Configuration Endpoints
|
|
368
|
+
|
|
369
|
+
#### GET `/api/config`
|
|
370
|
+
Retrieve the current configuration.
|
|
371
|
+
|
|
372
|
+
* **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
|
|
373
|
+
* **Response:**
|
|
374
|
+
```json
|
|
375
|
+
{
|
|
376
|
+
"agent": {
|
|
377
|
+
"name": "Morpheus",
|
|
378
|
+
"personality": "stoic, wise, and helpful"
|
|
379
|
+
},
|
|
380
|
+
"llm": {
|
|
381
|
+
"provider": "openai",
|
|
382
|
+
"model": "gpt-4-turbo",
|
|
383
|
+
"temperature": 0.7,
|
|
384
|
+
"context_window": 100,
|
|
385
|
+
"api_key": "***"
|
|
386
|
+
},
|
|
387
|
+
"santi": {
|
|
388
|
+
"provider": "openai",
|
|
389
|
+
"model": "gpt-4o",
|
|
390
|
+
"memory_limit": 1000
|
|
391
|
+
},
|
|
392
|
+
"channels": {
|
|
393
|
+
"telegram": {
|
|
394
|
+
"enabled": true,
|
|
395
|
+
"token": "***",
|
|
396
|
+
"allowedUsers": ["123456789"]
|
|
397
|
+
},
|
|
398
|
+
"discord": {
|
|
399
|
+
"enabled": false
|
|
400
|
+
}
|
|
401
|
+
},
|
|
402
|
+
"ui": {
|
|
403
|
+
"enabled": true,
|
|
404
|
+
"port": 3333
|
|
405
|
+
},
|
|
406
|
+
"audio": {
|
|
407
|
+
"enabled": true,
|
|
408
|
+
"apiKey": "***",
|
|
409
|
+
"maxDurationSeconds": 300
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
#### POST `/api/config`
|
|
415
|
+
Update the configuration.
|
|
416
|
+
|
|
417
|
+
* **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
|
|
418
|
+
* **Body:** Complete configuration object (same structure as GET response).
|
|
419
|
+
* **Response:**
|
|
420
|
+
```json
|
|
421
|
+
{
|
|
422
|
+
"agent": {
|
|
423
|
+
"name": "Morpheus",
|
|
424
|
+
"personality": "stoic, wise, and helpful"
|
|
425
|
+
},
|
|
426
|
+
"llm": {
|
|
427
|
+
"provider": "openai",
|
|
428
|
+
"model": "gpt-4-turbo",
|
|
429
|
+
"temperature": 0.7,
|
|
430
|
+
"context_window": 100,
|
|
431
|
+
"api_key": "***"
|
|
432
|
+
},
|
|
433
|
+
"santi": {
|
|
434
|
+
"provider": "openai",
|
|
435
|
+
"model": "gpt-4o",
|
|
436
|
+
"memory_limit": 1000
|
|
437
|
+
},
|
|
438
|
+
"channels": {
|
|
439
|
+
"telegram": {
|
|
440
|
+
"enabled": true,
|
|
441
|
+
"token": "***",
|
|
442
|
+
"allowedUsers": ["123456789"]
|
|
443
|
+
},
|
|
444
|
+
"discord": {
|
|
445
|
+
"enabled": false
|
|
446
|
+
}
|
|
447
|
+
},
|
|
448
|
+
"ui": {
|
|
449
|
+
"enabled": true,
|
|
450
|
+
"port": 3333
|
|
451
|
+
},
|
|
452
|
+
"audio": {
|
|
453
|
+
"enabled": true,
|
|
454
|
+
"apiKey": "***",
|
|
455
|
+
"maxDurationSeconds": 300
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
#### GET `/api/config/sati`
|
|
461
|
+
Retrieve the Sati (long-term memory) configuration.
|
|
462
|
+
|
|
463
|
+
* **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
|
|
464
|
+
* **Response:**
|
|
465
|
+
```json
|
|
466
|
+
{
|
|
467
|
+
"provider": "openai",
|
|
468
|
+
"model": "gpt-4o",
|
|
469
|
+
"memory_limit": 1000
|
|
470
|
+
}
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
#### POST `/api/config/sati`
|
|
474
|
+
Update the Sati (long-term memory) configuration.
|
|
475
|
+
|
|
476
|
+
* **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
|
|
477
|
+
* **Body:**
|
|
478
|
+
```json
|
|
479
|
+
{
|
|
480
|
+
"provider": "openai",
|
|
481
|
+
"model": "gpt-4o",
|
|
482
|
+
"memory_limit": 1000
|
|
483
|
+
}
|
|
484
|
+
```
|
|
485
|
+
* **Response:**
|
|
486
|
+
```json
|
|
487
|
+
{
|
|
488
|
+
"success": true
|
|
489
|
+
}
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
#### DELETE `/api/config/sati`
|
|
493
|
+
Remove the Sati (long-term memory) configuration (falls back to Oracle config).
|
|
494
|
+
|
|
495
|
+
* **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
|
|
496
|
+
* **Response:**
|
|
497
|
+
```json
|
|
498
|
+
{
|
|
499
|
+
"success": true
|
|
500
|
+
}
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
### Statistics Endpoints
|
|
504
|
+
|
|
505
|
+
#### GET `/api/stats/usage`
|
|
506
|
+
Get global token usage statistics.
|
|
507
|
+
|
|
508
|
+
* **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
|
|
509
|
+
* **Response:**
|
|
510
|
+
```json
|
|
511
|
+
{
|
|
512
|
+
"totalInputTokens": 12345,
|
|
513
|
+
"totalOutputTokens": 6789,
|
|
514
|
+
"totalTokens": 19134
|
|
515
|
+
}
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
#### GET `/api/stats/usage/grouped`
|
|
519
|
+
Get token usage statistics grouped by provider and model.
|
|
520
|
+
|
|
521
|
+
* **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
|
|
522
|
+
* **Response:**
|
|
523
|
+
```json
|
|
524
|
+
[
|
|
525
|
+
{
|
|
526
|
+
"provider": "openai",
|
|
527
|
+
"model": "gpt-4-turbo",
|
|
528
|
+
"totalTokens": 12345,
|
|
529
|
+
"inputTokens": 10000,
|
|
530
|
+
"outputTokens": 2345,
|
|
531
|
+
"messageCount": 100
|
|
532
|
+
},
|
|
533
|
+
{
|
|
534
|
+
"provider": "anthropic",
|
|
535
|
+
"model": "claude-3-opus",
|
|
536
|
+
"totalTokens": 6789,
|
|
537
|
+
"inputTokens": 5000,
|
|
538
|
+
"outputTokens": 1789,
|
|
539
|
+
"messageCount": 50
|
|
540
|
+
}
|
|
541
|
+
]
|
|
542
|
+
```
|
|
543
|
+
|
|
319
544
|
### Sati Memories Endpoints
|
|
320
545
|
|
|
321
546
|
#### GET `/api/sati/memories`
|
|
@@ -375,6 +600,174 @@ Archive (soft delete) multiple memories from the Sati agent at once.
|
|
|
375
600
|
}
|
|
376
601
|
```
|
|
377
602
|
|
|
603
|
+
### MCP Server Endpoints
|
|
604
|
+
|
|
605
|
+
#### GET `/api/mcp/servers`
|
|
606
|
+
List all registered MCP servers.
|
|
607
|
+
|
|
608
|
+
* **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
|
|
609
|
+
* **Response:**
|
|
610
|
+
```json
|
|
611
|
+
{
|
|
612
|
+
"servers": [
|
|
613
|
+
{
|
|
614
|
+
"name": "coolify",
|
|
615
|
+
"config": {
|
|
616
|
+
"transport": "stdio",
|
|
617
|
+
"command": "npx",
|
|
618
|
+
"args": ["-y", "@coolify/mcp-server"],
|
|
619
|
+
"env": {
|
|
620
|
+
"COOLIFY_URL": "https://app.coolify.io",
|
|
621
|
+
"COOLIFY_TOKEN": "your-token"
|
|
622
|
+
}
|
|
623
|
+
},
|
|
624
|
+
"enabled": true
|
|
625
|
+
},
|
|
626
|
+
{
|
|
627
|
+
"name": "coingecko",
|
|
628
|
+
"config": {
|
|
629
|
+
"transport": "http",
|
|
630
|
+
"url": "https://mcps.mnunes.xyz/coingecko/mcp"
|
|
631
|
+
},
|
|
632
|
+
"enabled": false
|
|
633
|
+
}
|
|
634
|
+
]
|
|
635
|
+
}
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
#### POST `/api/mcp/servers`
|
|
639
|
+
Add a new MCP server.
|
|
640
|
+
|
|
641
|
+
* **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
|
|
642
|
+
* **Body:**
|
|
643
|
+
```json
|
|
644
|
+
{
|
|
645
|
+
"name": "new-server",
|
|
646
|
+
"config": {
|
|
647
|
+
"transport": "stdio",
|
|
648
|
+
"command": "npx",
|
|
649
|
+
"args": ["-y", "@new-mcp-server"],
|
|
650
|
+
"env": {
|
|
651
|
+
"NEW_SERVER_URL": "https://example.com",
|
|
652
|
+
"NEW_SERVER_TOKEN": "your-token"
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
```
|
|
657
|
+
* **Response:**
|
|
658
|
+
```json
|
|
659
|
+
{
|
|
660
|
+
"ok": true
|
|
661
|
+
}
|
|
662
|
+
```
|
|
663
|
+
|
|
664
|
+
#### PUT `/api/mcp/servers/:name`
|
|
665
|
+
Update an existing MCP server.
|
|
666
|
+
|
|
667
|
+
* **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
|
|
668
|
+
* **Parameters:** `name` - Name of the server to update.
|
|
669
|
+
* **Body:**
|
|
670
|
+
```json
|
|
671
|
+
{
|
|
672
|
+
"transport": "stdio",
|
|
673
|
+
"command": "npx",
|
|
674
|
+
"args": ["-y", "@updated-mcp-server"],
|
|
675
|
+
"env": {
|
|
676
|
+
"UPDATED_SERVER_URL": "https://example.com",
|
|
677
|
+
"UPDATED_SERVER_TOKEN": "your-updated-token"
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
```
|
|
681
|
+
* **Response:**
|
|
682
|
+
```json
|
|
683
|
+
{
|
|
684
|
+
"ok": true
|
|
685
|
+
}
|
|
686
|
+
```
|
|
687
|
+
|
|
688
|
+
#### DELETE `/api/mcp/servers/:name`
|
|
689
|
+
Delete an MCP server.
|
|
690
|
+
|
|
691
|
+
* **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
|
|
692
|
+
* **Parameters:** `name` - Name of the server to delete.
|
|
693
|
+
* **Response:**
|
|
694
|
+
```json
|
|
695
|
+
{
|
|
696
|
+
"ok": true
|
|
697
|
+
}
|
|
698
|
+
```
|
|
699
|
+
|
|
700
|
+
#### PATCH `/api/mcp/servers/:name/toggle`
|
|
701
|
+
Enable or disable an MCP server.
|
|
702
|
+
|
|
703
|
+
* **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
|
|
704
|
+
* **Parameters:** `name` - Name of the server to toggle.
|
|
705
|
+
* **Body:**
|
|
706
|
+
```json
|
|
707
|
+
{
|
|
708
|
+
"enabled": true
|
|
709
|
+
}
|
|
710
|
+
```
|
|
711
|
+
* **Response:**
|
|
712
|
+
```json
|
|
713
|
+
{
|
|
714
|
+
"ok": true
|
|
715
|
+
}
|
|
716
|
+
```
|
|
717
|
+
|
|
718
|
+
### Logging Endpoints
|
|
719
|
+
|
|
720
|
+
#### GET `/api/logs`
|
|
721
|
+
List all log files.
|
|
722
|
+
|
|
723
|
+
* **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
|
|
724
|
+
* **Response:**
|
|
725
|
+
```json
|
|
726
|
+
[
|
|
727
|
+
{
|
|
728
|
+
"name": "morpheus.log",
|
|
729
|
+
"size": 10240,
|
|
730
|
+
"modified": "2026-02-05T21:30:00.000Z"
|
|
731
|
+
},
|
|
732
|
+
{
|
|
733
|
+
"name": "morpheus-2026-02-04.log",
|
|
734
|
+
"size": 20480,
|
|
735
|
+
"modified": "2026-02-04T21:30:00.000Z"
|
|
736
|
+
}
|
|
737
|
+
]
|
|
738
|
+
```
|
|
739
|
+
|
|
740
|
+
#### GET `/api/logs/:filename`
|
|
741
|
+
Get the last lines of a specific log file.
|
|
742
|
+
|
|
743
|
+
* **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
|
|
744
|
+
* **Parameters:** `filename` - Name of the log file to read.
|
|
745
|
+
* **Query Parameters:** `limit` - Number of lines to return (default: 50).
|
|
746
|
+
* **Response:**
|
|
747
|
+
```json
|
|
748
|
+
{
|
|
749
|
+
"lines": [
|
|
750
|
+
"2026-02-05T21:30:00.000Z INFO: Starting Morpheus agent...",
|
|
751
|
+
"2026-02-05T21:30:01.000Z DEBUG: Connected to OpenAI API",
|
|
752
|
+
"2026-02-05T21:30:02.000Z INFO: Telegram bot initialized"
|
|
753
|
+
]
|
|
754
|
+
}
|
|
755
|
+
```
|
|
756
|
+
|
|
757
|
+
### Control Endpoints
|
|
758
|
+
|
|
759
|
+
#### POST `/api/restart`
|
|
760
|
+
Restart the Morpheus agent.
|
|
761
|
+
|
|
762
|
+
* **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
|
|
763
|
+
* **Response:**
|
|
764
|
+
```json
|
|
765
|
+
{
|
|
766
|
+
"success": true,
|
|
767
|
+
"message": "Restart initiated. Process will shut down and restart shortly."
|
|
768
|
+
}
|
|
769
|
+
```
|
|
770
|
+
|
|
378
771
|
## Testing
|
|
379
772
|
|
|
380
773
|
We use **Vitest** for testing.
|
|
@@ -11,6 +11,7 @@ import { Telephonist } from '../runtime/telephonist.js';
|
|
|
11
11
|
import { readPid, isProcessRunning, checkStalePid } from '../runtime/lifecycle.js';
|
|
12
12
|
import { SQLiteChatMessageHistory } from '../runtime/memory/sqlite.js';
|
|
13
13
|
import { SatiRepository } from '../runtime/memory/sati/repository.js';
|
|
14
|
+
import { MCPManager } from '../config/mcp-manager.js';
|
|
14
15
|
export class TelegramAdapter {
|
|
15
16
|
bot = null;
|
|
16
17
|
isConnected = false;
|
|
@@ -215,6 +216,10 @@ export class TelegramAdapter {
|
|
|
215
216
|
case '/restart':
|
|
216
217
|
await this.handleRestartCommand(ctx, user);
|
|
217
218
|
break;
|
|
219
|
+
case '/mcp':
|
|
220
|
+
case '/mcps':
|
|
221
|
+
await this.handleMcpListCommand(ctx, user);
|
|
222
|
+
break;
|
|
218
223
|
default:
|
|
219
224
|
await this.handleDefaultCommand(ctx, user, command);
|
|
220
225
|
}
|
|
@@ -333,7 +338,7 @@ How can I assist you today?`;
|
|
|
333
338
|
async handleDefaultCommand(ctx, user, command) {
|
|
334
339
|
const prompt = `O usuário envio o comando: ${command},
|
|
335
340
|
Não entendemos o comando
|
|
336
|
-
temos os seguintes comandos disponíveis: /start, /status, /doctor, /stats, /help, /zaion, /sati <qnt>, /restart
|
|
341
|
+
temos os seguintes comandos disponíveis: /start, /status, /doctor, /stats, /help, /zaion, /sati <qnt>, /restart, /mcp, /mcps
|
|
337
342
|
Identifique se ele talvez tenha errado o comando e pergunte se ele não quis executar outro comando.
|
|
338
343
|
Só faça isso agora.`;
|
|
339
344
|
let response = await this.oracle.chat(prompt);
|
|
@@ -354,8 +359,9 @@ How can I assist you today?`;
|
|
|
354
359
|
/zaion - Show system configurations
|
|
355
360
|
/sati <qnt> - Show specific memories
|
|
356
361
|
/restart - Restart the Morpheus agent
|
|
362
|
+
/mcp or /mcps - List registered MCP servers
|
|
357
363
|
|
|
358
|
-
How can I assist you today
|
|
364
|
+
How can I assist you today? `;
|
|
359
365
|
await ctx.reply(helpMessage, { parse_mode: 'Markdown' });
|
|
360
366
|
}
|
|
361
367
|
async handleZaionCommand(ctx, user) {
|
|
@@ -473,4 +479,36 @@ How can I assist you today?`;
|
|
|
473
479
|
this.display.log(`Error checking restart notification: ${error.message}`, { source: 'Telegram', level: 'error' });
|
|
474
480
|
}
|
|
475
481
|
}
|
|
482
|
+
async handleMcpListCommand(ctx, user) {
|
|
483
|
+
try {
|
|
484
|
+
const servers = await MCPManager.listServers();
|
|
485
|
+
if (servers.length === 0) {
|
|
486
|
+
await ctx.reply('*No MCP Servers Configured*\n\nThere are currently no MCP servers configured in the system.', { parse_mode: 'Markdown' });
|
|
487
|
+
return;
|
|
488
|
+
}
|
|
489
|
+
let response = `*MCP Servers (${servers.length})*\n\n`;
|
|
490
|
+
servers.forEach((server, index) => {
|
|
491
|
+
const status = server.enabled ? '✅ Enabled' : '❌ Disabled';
|
|
492
|
+
const transport = server.config.transport.toUpperCase();
|
|
493
|
+
response += `*${index + 1}. ${server.name}*\n`;
|
|
494
|
+
response += `Status: ${status}\n`;
|
|
495
|
+
response += `Transport: ${transport}\n`;
|
|
496
|
+
if (server.config.transport === 'stdio') {
|
|
497
|
+
response += `Command: \`${server.config.command}\`\n`;
|
|
498
|
+
if (server.config.args && server.config.args.length > 0) {
|
|
499
|
+
response += `Args: \`${server.config.args.join(' ')}\`\n`;
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
else if (server.config.transport === 'http') {
|
|
503
|
+
response += `URL: \`${server.config.url}\`\n`;
|
|
504
|
+
}
|
|
505
|
+
response += '\n';
|
|
506
|
+
});
|
|
507
|
+
await ctx.reply(response, { parse_mode: 'Markdown' });
|
|
508
|
+
}
|
|
509
|
+
catch (error) {
|
|
510
|
+
this.display.log('Error listing MCP servers: ' + (error instanceof Error ? error.message : String(error)), { source: 'Telegram', level: 'error' });
|
|
511
|
+
await ctx.reply('An error occurred while retrieving the list of MCP servers. Please check the logs for more details.', { parse_mode: 'Markdown' });
|
|
512
|
+
}
|
|
513
|
+
}
|
|
476
514
|
}
|