Skip to content

Latest commit

 

History

History
194 lines (158 loc) · 5.34 KB

File metadata and controls

194 lines (158 loc) · 5.34 KB

Projet 01 — Serveur MCP minimal : protocole + 3 tools

Contexte

Tu implémentes ton premier serveur MCP en Rust avec rmcp.
L'objectif est de comprendre le protocole dans ses fondamentaux : comment un LLM découvre les tools, comment il les appelle, comment le serveur répond.
Pas de base de données, pas d'API externe — juste le protocole pur avec 3 tools simples mais complets.

Transport : stdio (Claude Desktop lit stdout, écrit stdin)
Connexion : Claude Desktop + VS Code Copilot Chat
Focus : JSON-RPC 2.0, cycle initialize → list_tools → call_tool


Objectifs du projet

  1. Comprendre le cycle de vie d'une session MCP : initialize, tools/list, tools/call
  2. Implémenter un serveur MCP with rmcp en Rust
  3. Exposer 3 tools avec des signatures JSON Schema typées
  4. Gérer les erreurs MCP (codes standardisés)
  5. Connecter le serveur à Claude Desktop et observer les appels en temps réel

Spécifications techniques

Structure du projet

mcp-hello-tools/
├── Cargo.toml
├── claude_desktop_config.json   ← config à copier dans Claude Desktop
└── src/
    ├── main.rs                  ← setup transport stdio + run server
    ├── server.rs                ← impl ServerHandler (rmcp trait)
    └── tools/
        ├── mod.rs
        ├── echo.rs              ← tool : echo un message
        ├── timestamp.rs         ← tool : heure actuelle, timezone param
        └── calculate.rs         ← tool : expression arithmétique simple

Les 3 tools

echo

{
  "name": "echo",
  "description": "Returns the input message unchanged. Use to verify the MCP connection is working.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "message": { "type": "string", "description": "The message to echo back" }
    },
    "required": ["message"]
  }
}

get_timestamp

{
  "name": "get_timestamp",
  "description": "Returns the current UTC timestamp. Optionally formats it for a given timezone.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "format": {
        "type": "string",
        "enum": ["iso8601", "unix", "human"],
        "description": "Output format (default: iso8601)"
      },
      "timezone": {
        "type": "string",
        "description": "IANA timezone name (e.g. 'Europe/Paris'). Default: UTC"
      }
    }
  }
}

calculate

{
  "name": "calculate",
  "description": "Evaluates a simple arithmetic expression: +, -, *, /. Returns the numeric result.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "expression": {
        "type": "string",
        "description": "Arithmetic expression, e.g. '(12 + 4) * 3'"
      }
    },
    "required": ["expression"]
  }
}

Implémentation rmcp

use rmcp::{ServerHandler, model::*, service::RequestContext, tool};

pub struct HelloServer;

#[rmcp::tool(tool_box)]
impl HelloServer {
    #[tool(description = "Returns the input message unchanged.")]
    async fn echo(&self, #[tool(param)] message: String) -> String {
        message
    }
}

#[rmcp::async_trait]
impl ServerHandler for HelloServer {
    fn get_info(&self) -> ServerInfo {
        ServerInfo {
            name: "mcp-hello-tools".into(),
            version: "0.1.0".into(),
            ..Default::default()
        }
    }
}

Transport stdio (main.rs)

use rmcp::transport::stdio;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // MCP over stdio : Claude Desktop pipe stdin/stdout
    let server = HelloServer;
    stdio::run_server(server).await?;
    Ok(())
}

Gestion d'erreurs MCP

MCP définit des codes d'erreur standardisés dans la spec JSON-RPC :

Code Constante Usage
-32700 PARSE_ERROR JSON invalide
-32600 INVALID_REQUEST Structure JSON-RPC invalide
-32601 METHOD_NOT_FOUND Tool inconnu
-32602 INVALID_PARAMS Paramètres manquants/invalides
-32603 INTERNAL_ERROR Erreur interne du serveur
use rmcp::model::ErrorCode;

fn calculate(expr: &str) -> Result<f64, rmcp::Error> {
    parse_and_eval(expr).map_err(|e| rmcp::Error {
        code: ErrorCode::INVALID_PARAMS,
        message: format!("Invalid expression: {}", e),
        data: None,
    })
}

Livrables attendus

  • Serveur MCP qui démarre via cargo run en mode stdio
  • 3 tools fonctionnels avec JSON Schema précis
  • get_timestamp supporte les 3 formats et les timezones IANA
  • calculate parse et évalue les 4 opérations de base avec parenthèses
  • Erreurs MCP correctement retournées (pas de panic)
  • Connexion à Claude Desktop vérifiée : Claude appelle les tools depuis le chat
  • claude_desktop_config.json documenté dans le README

Critères de qualité

  • Zéro unwrap() hors tests
  • Descriptions des tools rédigées pour le LLM : précises, sans ambiguïté
  • cargo clippy -- -D warnings : zéro warning
  • Les paramètres optionnels ont des valeurs par défaut documentées dans la description
  • Log vers stderr uniquement (stdout est réservé au protocole MCP)

Ressources