aissia/docs/PLAN_MCP_INTEGRATION.md
StillHammer 059709cd0d feat: Implement MCP client and internal tools for agentic LLM
Add complete tool calling infrastructure for Claude Code-like functionality:

Internal Tools (via GroveEngine IIO):
- Scheduler: get_current_task, list_tasks, start_task, complete_task, start_break
- Monitoring: get_focus_stats, get_current_app
- Storage: save_note, query_notes, get_session_history
- Voice: speak

MCP Client (for external servers):
- StdioTransport for fork/exec JSON-RPC communication
- MCPClient for multi-server orchestration
- Support for filesystem, brave-search, fetch servers

Architecture:
- IOBridge for sync request/response over async IIO pub/sub
- Tool handlers added to all modules (SchedulerModule, MonitoringModule, StorageModule, VoiceModule)
- LLMService unifies internal tools + MCP tools in ToolRegistry

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 16:50:30 +08:00

16 KiB

Plan d'Intégration MCP + Agent Vocal

Objectif

Transformer AISSIA en "Claude Code vocal" : un assistant qui peut utiliser des tools (internes + MCP) pour accomplir des tâches, piloté par la voix.

Architecture Cible

┌─────────────────────────────────────────────────────────────────────────────┐
│                              AISSIA - Agent Vocal                            │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│  ┌──────────┐    ┌──────────┐    ┌─────────────────────────────────────┐    │
│  │  Micro   │───►│   STT    │───►│           LLMService                │    │
│  └──────────┘    │ (Whisper)│    │         (Agentic Loop)              │    │
│                  └──────────┘    │                                     │    │
│                                  │  ┌─────────────────────────────┐    │    │
│                                  │  │      ToolRegistry           │    │    │
│                                  │  │                             │    │    │
│                                  │  │  ┌───────────────────────┐  │    │    │
│                                  │  │  │   Internal Tools      │  │    │    │
│                                  │  │  │   (via GroveEngine)   │  │    │    │
│                                  │  │  │                       │  │    │    │
│                                  │  │  │  • get_schedule       │  │    │    │
│                                  │  │  │  • start_break        │  │    │    │
│                                  │  │  │  • get_focus_stats    │  │    │    │
│                                  │  │  │  • save_note          │  │    │    │
│                                  │  │  │  • query_history      │  │    │    │
│                                  │  │  └───────────────────────┘  │    │    │
│                                  │  │                             │    │    │
│                                  │  │  ┌───────────────────────┐  │    │    │
│                                  │  │  │     MCP Tools         │  │    │    │
│                                  │  │  │   (via MCPClient)     │  │    │    │
│                                  │  │  │                       │  │    │    │
│                                  │  │  │  • read_file          │  │    │    │
│                                  │  │  │  • write_file         │  │    │    │
│                                  │  │  │  • list_directory     │  │    │    │
│                                  │  │  │  • web_search         │  │    │    │
│                                  │  │  │  • fetch_url          │  │    │    │
│                                  │  │  └───────────────────────┘  │    │    │
│                                  │  └─────────────────────────────┘    │    │
│                                  │                                     │    │
│                                  └──────────────────┬──────────────────┘    │
│                                                     │                       │
│                                                     ▼                       │
│  ┌──────────┐    ┌──────────┐    ┌─────────────────────────────────────┐    │
│  │ Speaker  │◄───│   TTS    │◄───│         Response Text               │    │
│  └──────────┘    │ (espeak) │    └─────────────────────────────────────┘    │
│                  └──────────┘                                               │
│                                                                              │
└─────────────────────────────────────────────────────────────────────────────┘


                    COMMUNICATION INTERNE (GroveEngine IIO)

┌──────────────┐     ┌──────────────┐     ┌──────────────┐     ┌──────────────┐
│  Scheduler   │     │  Monitoring  │     │   Storage    │     │    Voice     │
│   Module     │     │    Module    │     │   Module     │     │   Module     │
├──────────────┤     ├──────────────┤     ├──────────────┤     ├──────────────┤
│              │     │              │     │              │     │              │
│ • tasks      │     │ • app usage  │     │ • sessions   │     │ • TTS queue  │
│ • breaks     │     │ • focus time │     │ • notes      │     │ • STT events │
│ • hyperfocus │     │ • idle       │     │ • history    │     │              │
│              │     │              │     │              │     │              │
└──────┬───────┘     └──────┬───────┘     └──────┬───────┘     └──────┬───────┘
       │                    │                    │                    │
       └────────────────────┴────────────────────┴────────────────────┘
                                    │
                              IIO Pub/Sub
                                    │
                    ┌───────────────┴───────────────┐
                    │         LLMService            │
                    │   (écoute les tool:* topics)  │
                    └───────────────────────────────┘

Phases d'Implémentation

Phase 1 : Tools Internes via IIO

Objectif : Les modules GroveEngine exposent leurs fonctionnalités comme tools LLM.

Fichiers à créer/modifier :

  • src/shared/tools/InternalTools.hpp - Définitions des tools internes
  • src/shared/tools/InternalTools.cpp - Implémentation
  • src/services/LLMService.cpp - Enregistrement des tools

Tools à implémenter :

Tool Module Source Description
get_current_task SchedulerModule Retourne la tâche en cours
list_tasks SchedulerModule Liste toutes les tâches planifiées
start_task SchedulerModule Démarre une tâche par ID
complete_task SchedulerModule Marque une tâche comme terminée
start_break SchedulerModule Déclenche une pause
get_focus_stats MonitoringModule Stats de focus (temps, apps)
get_current_app MonitoringModule App actuellement active
save_note StorageModule Sauvegarde une note
query_notes StorageModule Recherche dans les notes
get_session_history StorageModule Historique des sessions
speak VoiceModule Fait parler l'assistant

Pattern d'implémentation :

// Le tool envoie une requête via IIO et attend la réponse
json InternalTools::executeGetCurrentTask(const json& input) {
    // 1. Créer la requête
    auto request = std::make_unique<grove::JsonDataNode>("request");
    request->setString("action", "get_current_task");

    // 2. Publier et attendre réponse (sync via promise/future)
    auto response = m_ioBridge->requestAndWait("scheduler:query", std::move(request), 1000);

    // 3. Convertir en JSON pour le LLM
    return {
        {"task_id", response->getString("task_id", "")},
        {"task_name", response->getString("task_name", "")},
        {"duration_minutes", response->getInt("duration_minutes", 0)}
    };
}

Phase 2 : Client MCP

Objectif : Se connecter à des serveurs MCP externes (filesystem, brave-search, etc.)

Fichiers à créer :

  • src/shared/mcp/MCPClient.hpp - Interface client MCP
  • src/shared/mcp/MCPClient.cpp - Implémentation
  • src/shared/mcp/MCPTransport.hpp - Transport stdio/SSE
  • src/shared/mcp/MCPTypes.hpp - Types MCP (Tool, Resource, etc.)

Protocole MCP simplifié :

Client                          Server (ex: filesystem)
   │                                  │
   │──── initialize ─────────────────►│
   │◄─── initialized (capabilities) ──│
   │                                  │
   │──── tools/list ─────────────────►│
   │◄─── tools (read_file, etc.) ─────│
   │                                  │
   │──── tools/call ─────────────────►│
   │     {name: "read_file",          │
   │      arguments: {path: "..."}}   │
   │◄─── result ──────────────────────│
   │     {content: "..."}             │
   │                                  │

Transport stdio :

class StdioTransport : public IMCPTransport {
public:
    StdioTransport(const std::string& command, const std::vector<std::string>& args) {
        // Fork + exec le serveur MCP
        // Rediriger stdin/stdout pour JSON-RPC
    }

    json sendRequest(const std::string& method, const json& params) {
        json request = {
            {"jsonrpc", "2.0"},
            {"id", m_nextId++},
            {"method", method},
            {"params", params}
        };

        // Écrire sur stdin du process
        write(request.dump() + "\n");

        // Lire la réponse sur stdout
        return json::parse(readLine());
    }
};

Configuration MCP :

// config/mcp.json
{
    "servers": {
        "filesystem": {
            "command": "npx",
            "args": ["-y", "@anthropic-ai/mcp-server-filesystem", "/home/user/documents"],
            "enabled": true
        },
        "brave-search": {
            "command": "npx",
            "args": ["-y", "@anthropic-ai/mcp-server-brave-search"],
            "env": {
                "BRAVE_API_KEY": "${BRAVE_API_KEY}"
            },
            "enabled": true
        },
        "fetch": {
            "command": "npx",
            "args": ["-y", "@anthropic-ai/mcp-server-fetch"],
            "enabled": true
        }
    }
}

Phase 3 : Unification ToolRegistry

Objectif : Le ToolRegistry agrège tools internes + MCP de façon transparente.

Modification de LLMService :

void LLMService::initializeTools() {
    // 1. Tools internes (via IIO)
    m_internalTools = std::make_unique<InternalTools>(m_io);
    for (const auto& tool : m_internalTools->getTools()) {
        m_toolRegistry.registerTool(tool);
    }

    // 2. Tools MCP (via MCPClient)
    m_mcpClient = std::make_unique<MCPClient>();
    m_mcpClient->loadConfig("config/mcp.json");
    m_mcpClient->connectAll();

    for (const auto& tool : m_mcpClient->listAllTools()) {
        m_toolRegistry.registerTool(
            tool.name,
            tool.description,
            tool.inputSchema,
            [this, name = tool.name](const json& input) {
                return m_mcpClient->callTool(name, input);
            }
        );
    }

    m_logger->info("Tools loaded: {} internal, {} MCP",
                   m_internalTools->size(), m_mcpClient->toolCount());
}

Phase 4 : Tests

Tests unitaires :

  • tests/test_internal_tools.cpp - Mock IIO, vérifier tool execution
  • tests/test_mcp_client.cpp - Mock server, vérifier protocole
  • tests/test_tool_registry.cpp - Vérifier aggregation

Test d'intégration :

// tests/integration/test_agentic_loop.cpp
TEST_CASE("Agentic loop with tools") {
    LLMService service;
    service.initialize(io);
    service.loadConfig("config/llm.json");

    // Simuler une query qui nécessite des tools
    auto result = service.query("Quelle tâche je fais en ce moment ?");

    // Vérifier que le tool get_current_task a été appelé
    REQUIRE(result.contains("task"));
}

Fichiers à Créer

src/
├── shared/
│   ├── tools/
│   │   ├── InternalTools.hpp      # Tools internes (IIO)
│   │   ├── InternalTools.cpp
│   │   └── IOBridge.hpp           # Request/response sync via IIO
│   └── mcp/
│       ├── MCPClient.hpp          # Client MCP principal
│       ├── MCPClient.cpp
│       ├── MCPTransport.hpp       # Interface transport
│       ├── StdioTransport.hpp     # Transport stdio (fork/exec)
│       ├── StdioTransport.cpp
│       └── MCPTypes.hpp           # Tool, Resource, etc.
├── services/
│   └── LLMService.cpp             # Modifier pour init tools
└── modules/
    ├── SchedulerModule.cpp        # Ajouter handlers pour tools
    ├── MonitoringModule.cpp
    └── StorageModule.cpp

config/
└── mcp.json                       # Configuration serveurs MCP

tests/
├── test_internal_tools.cpp
├── test_mcp_client.cpp
└── integration/
    └── test_agentic_loop.cpp

Ordre d'Implémentation

  1. IOBridge - Request/response synchrone via IIO
  2. InternalTools - Définition et implémentation des tools
  3. Modules handlers - Ajouter la gestion des requêtes tools dans chaque module
  4. Test internal tools - Vérifier que ça marche
  5. MCPTypes - Types de base MCP
  6. StdioTransport - Fork/exec + communication JSON-RPC
  7. MCPClient - Orchestration des serveurs
  8. Test MCP - Vérifier avec un vrai serveur (filesystem)
  9. Unification - Merger dans LLMService
  10. Test intégration - End-to-end

Estimation Temps

Phase Temps estimé
Phase 1 : Tools Internes 2-3h
Phase 2 : Client MCP 2-3h
Phase 3 : Unification 1h
Phase 4 : Tests 1-2h
Total 6-9h

Dépendances

  • nlohmann/json - Déjà présent
  • spdlog - Déjà présent
  • Node.js/npx - Pour les serveurs MCP (optionnel, on peut aussi implémenter nos propres serveurs en C++)

Risques et Mitigations

Risque Mitigation
Fork/exec complexe sur Windows Utiliser _popen ou process lib cross-platform
Timeout sur tools lents Configurable per-tool, default 30s
Serveur MCP crash Reconnect automatique, fallback graceful
Trop de tools = confusion LLM Grouper par namespace, limiter à ~20 tools