Practical-Activity-No.6_Model-Context-Protocol

No description

GitHub Stars

0

User Rating

Not Rated

Favorites

0

Views

11

Forks

0

Issues

0

README
🧑‍💻 Nom et Prénom : Anass Zbir
‍💻 Filière : Master SDIA

TP N°6 Chatbot Agentique avec Spring AI, MCP, Python & NodeJS
🧠 Objectif

Ce mini-projet a pour but de créer une application agentique sous forme de chatbot, en intégrant plusieurs technologies :

  • Spring AI pour la couche frontale et la gestion de l'agent
  • Protocole MCP pour la communication inter-processus
  • NodeJS et Python pour les serveurs MCP (en STDIO ou SSE)
  • Intégration avec Ollama et le modèle Mistral

📐 Sommaire
  1. 📚 Protocole MCP - Concepts de base
  2. 🏛️ Architecture et Spécifications MCP
  3. 🚀 Créer un serveur MCP SSE avec Java Spring
  4. 🧪 Tester un serveur MCP avec Postman
  5. 🧠 Créer un client Spring AI avec Ollama & Mistral
  6. 🟢 Déployer un serveur NodeJS MCP (STDIO)
  7. 🐍 Créer un serveur MCP avec Python (STDIO)
  8. 🧠 Rendre l’application Agentique
  9. 📷 Captures d’écran
  10. 🧪 Tester avec Swagger UI

📚 Protocole MCP - Concepts de base

Le protocole MCP (Model Context Protocol) permet à une application LLM d’interagir avec des serveurs externes (out-of-process tools) pour enrichir ses capacités.

  • Mode STDIO (command line)
  • Mode SSE (Server-Sent Events)

📌 Exemple de message MCP au format JSON :

{
  "mcp": "1.0",
  "type": "request",
  "body": { "input": "Bonjour, qui es-tu ?" }
}

🏛️ Architecture et Spécifications MCP
[ Client Spring AI ] ---> [ MCP Server (Python / NodeJS / Java SSE) ] 
                        ↘︎      ↖︎
                       [ Ollama Mistral ]
  • Spécification : mcp-server.json
  • Déclaration dans application.properties via spring.ai.mcp.client.*

🚀 Créer un serveur MCP SSE avec Java Spring
  • Créez un contrôleur Spring exposant un endpoint /sse

📁 tools/StockTools.java


public class StockTools {
    private List<Company> companies = List.of(
            new Company("Maroc Telecom","Telecom",5.3,32000,"Maroc"),
            new Company("OCP Group", "Mining", 9.7, 21000, "Maroc"),
            new Company("Royal Air Maroc", "Aviation", 1.4, 4000, "Maroc"),
            new Company("Attijariwafa Bank", "Banking", 6.5, 10000, "Maroc")
    );
    @Tool(description = "Get all companies")
    public List<Company> getCompanies() {
        return companies;
    }
    @Tool
    public Company getCompanyByName(String name){
        return companies.stream().filter(company -> company.name().equals(name)).findFirst()
                .orElseThrow(() -> new RuntimeException("Company not found"));
    }
    @Tool
    public Stock getStockByCompanyName(String name){
        return new Stock(name,LocalDate.now(),300+Math.random()*300);
    }}
record Company(
        String name,
        String activity,
        @Description("The turnover in Milliard MAD") double turnover,
        int employeeCount,
        String Country
){
}
record Stock(String companyName,
             LocalDate date,
             double stock){}

📁 McpServerApplication.java

@SpringBootApplication
public class McpServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(McpServerApplication.class, args);
    }
    @Bean
    public MethodToolCallbackProvider getMethodToolCallbackProvider() {
        return MethodToolCallbackProvider.builder()
                .toolObjects(new StockTools())
                .build();
    }}

🧪 Tester un serveur MCP avec Postman
  • Définir l’URL du serveur (http://localhost:8899/sse)
  • Choisir GET ou POST selon l’implémentation
  • Utiliser l’onglet Event Stream de Postman Labs pour voir la réponse SSE

📷

image


🧠 Créer un client Spring AI avec Ollama & Mistral
  • Configurer spring.ai.ollama.base-url
  • Ajouter une configuration mcp-server.json avec les chemins vers les serveurs STDIO / SSE
  • Annoter l'agent avec @Assistant
  • Démarrer Ollama mistral
ollama run mistral

📁 application.properties

spring.application.name=mcp_client
spring.ai.mcp.client.type=sync
spring.ai.mcp.client.sse.connections.server1.url = http://localhost:8899
spring.ai.mcp.client.sse.connections.server1.sse-endpoint = /sse
spring.ai.mcp.client.stdio.servers-configuration=classpath:mcp-server.json
server.port=8066
spring.ai.ollama.base-url=http://localhost:11434
spring.ai.ollama.chat.model=mistral

📁 AiAgent.java

package org.example.mcp_client.agents;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.memory.MessageWindowChatMemory;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.stereotype.Service;

@Service
public class AiAgent {
private ChatClient  chatClient;

    public AiAgent(ChatClient.Builder chatClient, ToolCallbackProvider toolCallbackProvider) {
        this.chatClient = chatClient
                .defaultToolCallbacks(toolCallbackProvider)
                .defaultSystem("Answer the user questions using provided tools")
                .defaultAdvisors(MessageChatMemoryAdvisor.builder(
                        MessageWindowChatMemory.builder().maxMessages(10).build()
                ).build())
                .build();
    }
    public String askLLM(String query){
        return chatClient.prompt()
                .user(query)
                .call()
                .content();
    }

}

📁 McpClientApplication.java

@Bean
    public CommandLineRunner run(List<McpSyncClient> clients) {
        return args -> {
            clients.forEach(client -> {
                client.listTools().tools().forEach(tool -> {
                    System.out.println("------------------------------------");
                    System.out.println(tool.name());
                    System.out.println(tool.description());
                    System.out.println(tool.inputSchema());
                    System.out.println("-------------------------------------");
                });
                System.out.println("*****************************************");
                String params = """
                        {
                        "name": "Maroc Telecom"
                        }
                        """;
                McpSchema.CallToolResult result = clients.get(0).callTool(new McpSchema.CallToolRequest("getCompanyByName", params));
                McpSchema.Content content = result.content().get(0);
                System.out.println(content);
                if (content.type().equals("text")) {
                    McpSchema.TextContent textContent = (McpSchema.TextContent) content;
                    System.out.println(textContent.text());
                }
            });
        };
    }

📷 Resultat d'excecution


-------------------------------------
*****************************************
TextContent[audience=null, priority=null, text={"name":"Attijariwafa Bank","activity":"Banking","turnover":6.5,"employeeCount":10000,"Country":"Maroc"}]
{"name":"Attijariwafa Bank","activity":"Banking","turnover":6.5,"employeeCount":10000,"Country":"Maroc"}

🟢 Déployer un serveur NodeJS MCP en STDIO
Étapes :
  1. Installer NodeJS

  2. Ajouter cette configuration dans le mcp-server.json :

{
  "mcpServers": {
    "filesystem": {
      "command": "C:\\Program Files\\nodejs\\npx.cmd",
      "args": [
        "-y",
        "@modelcontextprotocol/server-filesystem",
        "C:\\Users\\ifran\\IdeaProjects\\mcp_demo_spring_python"
      ]
    }
  }
}

🐍 Créer un serveur MCP avec Python (STDIO)
🧪 Étapes :
  1. Créer un environnement virtuel avec uv :
   uv venv .venv
   source .venv/bin/activate  # Linux/macOS
   .\.venv\Scripts\activate   # Windows
  1. Installer les dépendances nécessaires :
   uv pip install -r requirements.txt
  1. Créer un script Python MCP (server.py) qui :

    • Lit depuis stdin un message JSON MCP
    • Traite la requête
    • Écrit une réponse MCP sur stdout

    Exemple minimal :

         from mcp.server.fastmcp import FastMCP
         mcp = FastMCP('Python-MCP-Server')
         @mcp.tool()
         def get_info_about(name : str) -> str:
         """
         Get Information about a given employee name:
         - First Name
           - Last Name
           - Salary
           - Email
           """
           return {
           "first_name" : name,
           "last_name" : "Mohamed",
           "salary":8377,
           "email":"employee@gmail.com"
    

}
```

  1. Déclarer le serveur dans mcp-server.json pour l'exécuter en mode STDIO :

    {
         "Python-MCP-Server": {
             "command": "uv",
             "args": [
                 "run",
                 "--with",
                 "mcp[cli]",
                 "mcp",
                 "run",
                 "C:\\Users\\ifran\\IdeaProjects\\mcp_demo_spring_python\\python_mcp_server\\server.py"
             ]
         }
    }
    

🧪 Tester avec Swagger UI
  • Ajouter la dépendance Springdoc OpenAPI
  • Lancer l'application
  • Accéder à http://localhost:8080/swagger-ui.html

img.png



📦 Technologies utilisées
Outil Rôle
Spring AI Backend du chatbot
MCP Communication inter-agents
NodeJS Serveur MCP STDIO
Python Serveur MCP STDIO
Ollama + Mistral LLM pour réponse du bot
Swagger Interface de test
Postman Test serveur MCP

Author Information
Anass ZBIR

I’m Anass a dedicated Master’s student in Data Science and AI at the Faculty of Sciences in Meknès.I’m on a journey to carve out my path in the tech world

0

Followers

11

Repositories

0

Gists

0

Total Contributions