GitHub Stars
0
User Rating
Not Rated
Favorites
0
Views
11
Forks
0
Issues
0
🧑💻 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
- 📚 Protocole MCP - Concepts de base
- 🏛️ Architecture et Spécifications MCP
- 🚀 Créer un serveur MCP SSE avec Java Spring
- 🧪 Tester un serveur MCP avec Postman
- 🧠 Créer un client Spring AI avec Ollama & Mistral
- 🟢 Déployer un serveur NodeJS MCP (STDIO)
- 🐍 Créer un serveur MCP avec Python (STDIO)
- 🧠 Rendre l’application Agentique
- 📷 Captures d’écran
- 🧪 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
viaspring.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
ouPOST
selon l’implémentation - Utiliser l’onglet Event Stream de Postman Labs pour voir la réponse SSE
📷
🧠 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 :
Installer NodeJS
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 :
- Créer un environnement virtuel avec
uv
:
uv venv .venv
source .venv/bin/activate # Linux/macOS
.\.venv\Scripts\activate # Windows
- Installer les dépendances nécessaires :
uv pip install -r requirements.txt
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"
- Lit depuis
}
```
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
📦 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 |
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