Transformez votre application Rails en serveur MCP et embrassez la révolution AI.


Avec l’avènement de l’intelligence artificielle et de la montée en puissance des LLMs, vous avez peut-être déjà entendu parler du protocole MCP (Model Context Protocol) ? S vous ne comprenez pas ce que c’est et à quoi ça sert vous êtes tombé a bon endroit !

Ensemble, on va explorer ensemble un cas d’usage pratique et un exemple d’implémentation dans Rails. A la fin, vous serez capable de rendre vos applications AI-Native c’est promis !


Pour écrire l’article, je me suis largement inspiré de la superbe présentation de “Paweł Strzałkowski” à la conférence RailsWorld de 2025. Retrouvez un lien vers la vidéo à la fin.

Commençons par comprendre ce qu’est le protocol MCP

Présentation du problème

L’un des problèmes majeurs quand vous souhaitez développer une application moderne tirant profit des LLMs (Large Language Model) est sa connexion avec le monde extérieur. Prenons l’exemple présenté par Pawel :


Un utilisateur demande à une IA de lui réserver un week-end en Espagne avec un cahier des charges très spécifiques : vers la mi-juillet, dans un hôtel 5* avec un cadre romantique et une météo favorable.

L’IA a été entrainé sur des quantités considérables d’informations et il peut probablement faire des hypothèses sur ce que “romantisme” veut dire. Cependant ces informations sont figées dans le temps. Comment sait-il si les hôtels adéquats son disponible sur la période donnée ? Ou si la météo sera favorable ? C’est un système fermé qui ne dispose pas nativement d’information en temps réel !


Il y a un vrai mur entre les LLMS et les applications classiques, par défaut ils n’ont pas accès au monde extérieur.


Une première approche serait de créer un système qui fait le pont entre le LLM et la demande de l’utilisateur via des APIs. Cela peut fonctionner mais on se retrouve très vite confronté à un problème d’échelle. Pour chaque modèle (M) et chaque application (N) il faut créer une connexion manuellement pour envoyer la requête, le système pour traduire entre nos applications et le LLM… et bien entendu maintenir tout ça dans le temps. Très rapidement cela va devenir un enfer !



C’est bien ce qu’on compris les géants du domaine et notamment Anthropic qui a proposé en 2024 une approche qui va simplifier nos vies de développeur. Ils ont introduit le “Model Context Protocol”.

Qu’est-ce que le protocole MCP (Model Context Protocol) ?

Concrètement, ce protocole est une standardisation de la manière de fournir un contexte additionnelle à un LLM. Puisque c’est un standard tout le monde l’utilise. Il suffit de créer un connecteur une fois et tous les LLMs sachant utiliser les serveurs MCPs sauront s’y connecter. On n’a donc plus (N) applications mais une seule. Cela réduit considérablement le coût de développement ET de maintenance. En plus d’améliorer notre santé mentale de développeur (ou en tout cas ne pas participer à sa détérioration !).


Et c’est tellement efficace et pratique que ça a été rapidement adopté par les autres géants du secteur, Google et OpenAI en tête.


Techniquement parlant cela ressemble à une API mais optimisée pour discuter efficacement avec un LLM.

L’architecture se décompose en trois composants.

  1. Il y a d’un côté le HOST : C’est votre application !
  2. Au milieu il y a le serveur MCP qui fourni un contexte supplémentaire à chaque prompt (par HTTP si MCP à distance ou par transfert direct si le MCP fonctionne sur la même machine que le host)
  3. De l’autre côté il y a le LLM. Le host communique avec lui en utilisant des aller retour “prompt réponse”

Zoom au cœur d’un MCP

Les MCP sont constitué de “primitives”. C’est un terme souvent utilisé en programmation pour parler de bloc “élémentaire”.


Dans un MCP il y a trois types de primitives

  1. Les outils (Tools) : Ce sont des fonctions que le serveur peut lancer pour le host.
  2. Les ressources (Resources) : Ce sont les données auquelles à accès le MCP (des logs, des images, etc…)
  3. Les prompts : Ce sont des instructions standardisées que le serveur peut fournir à l’utilisateur comme ça il peut communiquer efficacement avec le serveur.


Exemple sur l’application de réservation de voyage

Pourquoi c’est plus efficace qu’une API ?

Le “Model Context Protocol” est un standard que tous les LLMs modernes comprennent ! Donc si vous créer un serveur MCP pour votre application, par défaut tous les LLMs vont le comprendre il n’y pas besoin d’adaptation supplémentaire.

Plus besoin d’écrire vos connecteurs et prompts parce que les MCPs sont déjà capable de communiquer avec votre application de manière native, par construction.


En ajoutant des MCPs à votre application vous êtes “AI-natif” puisque votre application sait discuter avec tous les LLMs. C’est une fonctionnalité très puissante et dans Rails c’est très simple à mettre en place comme vous allez le voir dans l’exemple.

Implémentation d’une application de blog “AI native” avec Rails et la GEM “ruby-sdk”.


Rails est un écosystème merveilleux si vous souhaitez construire une application moderne qui fonctionne nativement avec l’intelligence artificielle. Pourquoi ?


Parce que

  1. Rails a été construit sur une base solide et dispose “sous le capot” de fonctionnalités clés qui vous permettent de faire des choses incroyables sans devoir gérer une configuration complexe vous même
  2. Rails dispose d’une communauté incroyable de passionnés qui développent des améliorations, et notamment des GEMs, surpuissantes.


Vous pensez que mes superlatifs sont exagérés ? Lisez jusqu’au bout et vous allez voir que ce n’est vraiment pas le cas…

La GEM “ruby-sdk”

Lorsque vous souhaitez ajouter des fonctionnalités supplémentaires dans votre application Rails vous pensez forcément aux GEMs. Et pour ajouter des fonctionnalités MCPs à votre application il existe d’ores et déjà une GEM officielle, nommée “ruby-sdk”, maintenue par la communauté en collaboration avec Shopify. Autant dire que c'est du costaud.


En quelques lignes de code, vous pouvez ajouter un serveur MCP à votre application


server = MCP::Server.new(name: "my_server")
transport = MCP::Server::Transports::StreamableHTTPTransport.new(server)
server.transport = transport
# When tools change, notify clients
server.define_tool(name: "new_tool") { |**args| { result: "ok" } }
server.notify_tools_list_changed

Mise en place de l’application de démonstration

Pour illustrer la mise en place d’un serveur MCP on va s’amuser à créer un projet qui va nous permettre d’automatiser la création d’article de blog. Pour ce faire on va utiliser le template fournit par Pawel


git clone <https://github.com/pstrzalk/mcp-on-rails.git>
rails new blog-mcp -m mcp-on-rails/mcp
cd blog-mcp


Cela va initialiser un nouveau projet “blog-mcp” et configurer plusieurs choses pour vous, dont notamment :

  1. Ajouter plusieurs routes
Rails.application.routes.draw do
resources :comments
resources :posts
# Model Context Protocol
post "/mcp", to: "mcp#handle"
get "/mcp", to: "mcp#handle"
# Define your application routes per the DSL in <https://guides.rubyonrails.org/routing.html>
# Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500.
# Can be used by load balancers and uptime monitors to verify that the app is live.
get "up" => "rails/health#show", as: :rails_health_check
# Render dynamic PWA files from app/views/pwa/* (remember to link manifest in application.html.erb)
# get "manifest" => "rails/pwa#manifest", as: :pwa_manifest
# get "service-worker" => "rails/pwa#service_worker", as: :pwa_service_worker
# Defines the root path route ("/")
# root "posts#index"
end
  1. Créer un controller pour le MCP
class McpController < ActionController::API
def handle
if params[:method] == "notifications/initialized"
head :accepted
else
render(json: mcp_server.handle_json(request.body.read))
end
end
private
def mcp_server
MCP::Server.new(
name: "rails_mcp_server",
version: "1.0.0",
tools: MCP::Tool.descendants
)
end
end
  1. Et un générateur qui va vous aider à créer vos premiers outils
class McpToolGenerator < Rails::Generators::NamedBase
source_root File.expand_path("templates", __dir__)
argument :attributes, type: :array, default: [], banner: "field:type field:type"
def create_tool_file
template "tool.rb.tt", File.join("app", "tools", "#{file_name}.rb")
end
private
def tool_class_name
file_name.classify
end
def map_attribute_type(type)
case type.to_sym
when :references, :belongs_to, :timestamp, :integer
:integer
when :boolean
:boolean
else
:string
end
end
end


Maintenant si vous faites “rails server” vous allez voir votre application démarrer sur “http://localhost:3000/”. Première étape terminée !

Installation de MCP Inspector

En plus de notre application Rails, on va avoir besoin d’un second outil de debug pour développeur qui se nomme “MCP Inspector”. Cet outil n’est pas intégré dans l’environnement ruby, vous allez plutôt le faire tourner sur un environnement Node.js. Vous pouvez l’installer en utilisant la commande :

# Assurez vous d'avoir node installé
# Il vous faudra au moins la version 22.7.5 de node
# Si vous n'avez pas node ou que vous avez besoin de le mettre à jour
# aller sur <https://nodejs.org/en>
> node -v
v22.20.0
> npx -v
10.9.3
# Puis installez l'outil MCP inspector
> npx @modelcontextprotocol/inspector

Au lancement vous devriez voir ça :


Une fois installé :

  1. Rendez-vous sur le lien fourni par l’outil
  2. Choisissez “transport type : streamable http” et renseignez votre serveur local avec le endpoint MCP
  3. Cliquez sur “Connect”


Bien entendu, il faut que votre serveur rails tourne en parallèle pour que la connexion puisse se faire. Si jamais il vous demande un token, renseignez celui crée au lancement de l’outil dans le champ “Proxy Session Token” dans le menu de configuration. Normalement si vous avez ouvert le lien avec le “token pre-filled” il devrait déjà être renseigné mais sait-on jamais. ;)



Félicitations vous êtes connecté et votre application Rails est reconnu comme un serveur MCP. C’était facile hein ? Et attendez, vous n’avez encore rien vu !

Créons nos premier outils

C’est bien beau tout ça mais comment remplir notre blog maintenant ? Toute application Rails n’est en réalité qu’une surcouche d’une application “CRUD” classique. Donc forcément la première étape passe par créer nos modèles, controller et vues pour gérer nos posts.


Dans l’exemple, on va utiliser la méthode “scaffold” de Rails pour créer rapidement tout le nécessaire. N’oubliez pas la migration après ;)


rails g scaffold post title:string body:text
rails db:migrate


Puisqu’on utilise le template MCP, on peut remarquer que la commande génère des fichiers supplémentaires qu’on n’a pas l’habitude de voir.


Pourquoi ? Parce que le template dispose d’un générateur dédié à la tache


# frozen_string_literal: true
require "rails/generators/resource_helpers"
module Rails
module Generators
class McpGenerator < NamedBase
include Rails::Generators::ResourceHelpers
source_root File.expand_path("templates", __dir__)
argument :attributes, type: :array, default: [], banner: "field:type field:type"
def create_mcp_tools
template "show_tool.rb", File.join("app", "tools", controller_file_path, "show_tool.rb")
template "index_tool.rb", File.join("app", "tools", controller_file_path, "index_tool.rb")
template "create_tool.rb", File.join("app", "tools", controller_file_path, "create_tool.rb")
template "update_tool.rb", File.join("app", "tools", controller_file_path, "update_tool.rb")
template "delete_tool.rb", File.join("app", "tools", controller_file_path, "delete_tool.rb")
end
private
def map_attribute_type(type)
case type.to_sym
when :references, :belongs_to, :timestamp, :integer
:integer
when :boolean
:boolean
else
:string
end
end
end
end
end


Et ce générateur va créer automatiquement des outils dédiés pour chaque action du CRUD. Par exemple pour l’action de création d’un post on va disposer d’un outil “post-create-tool”.


module Posts
class CreateTool < MCP::Tool
tool_name "post-create-tool"
description "Create a new Post entity"
input_schema(
properties: {
title: { type: "string" },
body: { type: "string" },
},
required: [ ]
)
def self.call(title: nil, body: nil, server_context:)
post = Post.new(
title: title,
body: body
)
if post.save
MCP::Tool::Response.new([ { type: "text", text: "Created #{post.to_mcp_response}" } ])
else
MCP::Tool::Response.new([ { type: "text", text: "Post was not created due to the following errors: #{post.errors.full_messages.join(', ')}" } ])
end
rescue StandardError => e
MCP::Tool::Response.new([ { type: "text", text: "An error occurred, what happened was #{e.message}" } ])
end
end
end


Est-ce que cela veut dire que nous pourrons créer des post via MCP ? Oui ! Et pas seulement “créer”. On va pouvoir réaliser toutes les actions du CRUD via MCP !

Vous pouvez lister l’ensemble des outils disponibles en lançant la commande “rails mcp:tools”.


Ou en interrogeant votre serveur MCP depuis MCP Inspector. Vous pouvez alors lancer l’outil en question et voir la réponse directement dans l’interface. Ici je lui demande de lancer l’outil “post-index-tool” et il me renvoit la liste des N derniers posts créés.

Bien entendu, j’avais crée un post en naviguant vers “http://localhost:3000/posts/new”. Mais tant qu’à faire essayez avec l’outil “post-create-tool” directement ! 😊

Finaliser la mise en place

On va également ajouter la capacité de laisser un commentaire pour chaque post. Pour ce faire lancer la commande suivante :

rails g scaffold comment post:references content:text
rails db:migrate


Comme pour les posts, la commande va également créer automatiquement les outils pour la création de commentaire

Et nous allons ajouter la capacité de mettre à jour la vue de l’index des posts en temps réel via “turbo stream”.

  1. Modifier l’index pour ajouter turbo_stream
<p style="color: green"><%= notice %></p>
<% content_for :title, "Posts" %>
<h1>Posts</h1>
<%= render "posts" %>
<%= turbo_stream_from "posts" %>
<%= link_to "New post", new_post_path %>
  1. Créer une partial “_posts”
<div id="posts">
<% Post.all.each_with_index do |post, index| %>
<div id="<% dom_id post %>">
<h2><%= post.title %></h2>
<p><%= post.body %></p>
<% if post.comments.any? %>
<div>
<h3>Comments</h3>
<% post.comments.each do |comment| %>
<p>
<strong><%= comment.create_at %></strong> - <%= comment.content %>
</p>
<% end %>
</div>
<% end %>
<% end %>
</div>
  1. Modifier le modèle “Post”
class Post < ApplicationRecord
has_many :comments, dependent: :destroy
broadcasts_to :replace_posts
private
def replace_posts
broadcast_replace_to "posts", target: "posts", partial: "posts/post"
end
end
  1. Modifier le modèle “Comment”
class Comment < ApplicationRecord
belongs_to :post, touch: true
end

Vous pouvez tester le fonctionnement directement !


Testons notre application en live !

Il existe plusieurs solutions possible pour connecter vos serveurs MCP, ou n’importe quel serveur MCP, à un LLMs. Pour des raisons de facilité, on va utiliser l’application Claude Desktop. C’est l’application officiel de Anthropic disponible sur https://www.claude.com/download.


Pour connecter un MCP à Claude il faut un minimum un compte Pro ou être débrouillard. J’ai choisi la seconde option :)


Pour la suite, vous aurez besoin d’un serveur Node.js. Si comme moi vous travaillez sous Windows (WSL2) avec Ubuntu (pas d’insulte merci), vous aurez besoin d’installer Node sur Windows directement. Si vous travaillez sur Linux ou Mac, et que vous avez déjà node d'installé, vous pouvez passer directement à la prochaine partie

Installer Node.js pour Windows

C’est très simple vous allez voir. Allez directement sur le site officiel https://nodejs.org/fr/download et téléchargez l’installateur .msi directement puis installez le.

Lancez l’installation en double cliquant sur le .msi et suivez les consignes jusqu’au bout.

Une fois l’installation terminée, lancez un terminal Windows Powershell. Vous pouvez facilement le trouver via le menu de recherche Windows. Vérifiez que node est bien installé.


> node -v
v22.20.0

Configurer Claude Desktop

Installez et lancez Claude Desktop. Puis rendez-vous dans les paramètres section “Développeur”. Cliquez sur le bouton “Modifier la config”.


Ouvrez le fichier “claude_desktop_config.json” dans votre éditeur de texte favori (VSCode, Notepad++, peu importe) et rajouter la configuration suivante :


{
"mcpServers": {
"blog-mcp": {
"command": "npx",
"args": [
"mcp-remote",
"<http://localhost:3000/mcp>"
]
}
}


Au lancement de Claude Desktop, cela va lancer une commande “mcp-remote” pour se connecter à votre serveur MCP.


npx mcp-remote <http://localhost:3000/mcp>


Quittez Claude Desktop et relancez le. Attention cliquer sur la croix ne ferme pas l’application mais la réduit ! Pour la fermer, il faut aller dans “Fichier > Quitter”. C’est indispensable pour que Claude lancer la connexion au serveur MCP au lancement.


Avant de relancer Claude, assurez vous que votre application est démarrée avec “rails serve”.

Si cela a fonctionné vous devriez voir votre serveur MCP et avoir accès à la liste de tous les outils qu’il propose :

Créons des articles de blog avec Claude

Super ! Maintenant place au fun. Créer une nouvelle conversation avec Claude et demandez lui par exemple de créer trois articles de blog. Demandez lui ensuite de commenter le second article.

Et observez la puissance de l’implémentation ! Grâce aux outils que nous avons mis en place, il peut parfaitement gérer le contexte. C’est presque de la magie à ce stade non ?



Conclusions

Pour ma part je trouve cet exemple incroyable ! J’espère que vous aussi et que les superlatifs utilisés plus tôt vous paraissent maintenant pertinent.

L'avenir d'internet sera probablement un mix entre ce que nous connaissons actuellement et un monde d'application "mcp ready" ou AI-Native. Les utilisateurs n'auront plus besoin d’interagir manuellement mais utiliserons les LLMs pour discuter en langage naturelle, ou via l'audio. Cela va changer complétement la manière de consommer internet ! Donc si vous ne voulez pas être à la traîne, intégrer un serveur MCP à votre application. Si vous utilisez Rails cela tombe bien c'est très simple comme nous avons pu le voir :)


Pour récapituler :

  1. Ne créez pas des APIs pour discuter avec des LLMs mais utilisez le protocole MCP. C’est devenu la norme dans l’industrie.
  2. Vous pouvez facilement connecter votre application aux LLMs modernes et rendre votre application “AI-native” avec l’intégration de MCP.
  3. L’écosystème Rails évolue très rapidement et arrive à suivre les technologies modernes grâce à son incroyable communauté.


N’hésitez pas à partager cet article et à vous abonnez pour ne rien louper.




La vidéo de référence de Pawel peut-être visionnée ici :





Share it: