Si vous avez créé un serveur MCP et souhaitez qu’un assistant s’y connecte depuis un autre ordinateur, il vous faut une adresse publique et un processus qui reste actif. Un VPS vous donne la maîtrise de ce processus, du proxy HTTPS et des mises à jour, mais vous confie aussi l’administration de la machine.
À ne pas confondre avec le serveur MCP du compte Hostbrid : ce service permet de consulter et de gérer les ressources de votre compte ; il n’exécute pas un serveur MCP que vous avez développé. Pour déployer un site créé avec l’IA, consultez Projects. Ce guide utilise un VPS pour héberger durablement un service MCP que vous administrez vous-même.
Choisir le transport avant le déploiement
Le protocole MCP définit stdio et Streamable HTTP. Avec stdio, le client lance le processus localement sur son propre ordinateur. Pour vous connecter à un service distant, il vous faut un endpoint HTTP accessible, généralement à une adresse comme https://mcp.exemple.com/mcp. Le transport Streamable HTTP utilise des requêtes HTTP et peut maintenir des réponses SSE ; un proxy ou un pare-feu qui ne prend pas en charge ce trafic peut interrompre la session même si la page répond.
Vérifiez les transports pris en charge par votre serveur et votre client avant de choisir une offre. Si vous avez seulement besoin d’outils locaux, stdio peut suffire et ne nécessite pas de VPS public.
Créer un serveur simple et protégé
Cet exemple utilise le SDK TypeScript officiel MCP v2, Express et un outil inoffensif nommé ping. Il a été validé le 9 octobre 2026 avec @modelcontextprotocol/server et @modelcontextprotocol/client 2.3.1, @modelcontextprotocol/express 2.0.2, @modelcontextprotocol/node 2.1.1, Express et Zod. Vérifiez les versions en vigueur avant le déploiement : le SDK et la spécification évoluent.
Installez les dépendances et enregistrez les versions exactes dans package-lock.json :
npm install --save-exact @modelcontextprotocol/server@2.3.1 @modelcontextprotocol/express@2.0.2 @modelcontextprotocol/node@2.1.1 express zod
Créez server.mjs :
import { createMcpExpressApp } from '@modelcontextprotocol/express';
import { toNodeHandler } from '@modelcontextprotocol/node';
import { McpServer, createMcpHandler } from '@modelcontextprotocol/server';
import { timingSafeEqual } from 'node:crypto';
import { z } from 'zod';
const port = Number(process.env.PORT || 3000);
const bearer = process.env.MCP_BEARER_TOKEN;
const allowedHost = process.env.MCP_ALLOWED_HOST || '127.0.0.1';
if (!bearer || bearer.length < 32) throw new Error('Configura MCP_BEARER_TOKEN con un secreto aleatorio de al menos 32 caracteres.');
if (!Number.isInteger(port) || port < 1 || port > 65535) throw new Error('PORT no es válido.');
const app = createMcpExpressApp({
host: '0.0.0.0',
allowedHosts: [allowedHost],
allowedOrigins: [allowedHost],
});
const handler = createMcpHandler(() => {
const server = new McpServer({ name: 'mi-servidor-mcp', version: '1.0.0' });
server.registerTool('ping', {
description: 'Devuelve una respuesta fija de estado; no modifica nada.',
inputSchema: z.object({}),
}, async () => ({ content: [{ type: 'text', text: 'pong' }] }));
return server;
});
const nodeHandler = toNodeHandler(handler);
app.all('/mcp', (req, res) => {
const header = req.get('authorization') || '';
const actual = Buffer.from(header.startsWith('Bearer ') ? header.slice(7) : '');
const expected = Buffer.from(bearer);
const valid = actual.length === expected.length && timingSafeEqual(actual, expected);
if (!valid) return res.status(401).json({ error: 'unauthorized' });
return void nodeHandler(req, res, req.body);
});
app.listen(port, '127.0.0.1', () => console.log(`MCP escuchando en 127.0.0.1:${port}/mcp`));
allowedHosts et allowedOrigins doivent contenir le nom public utilisé par le proxy, par exemple mcp.exemple.com. Le processus écoute uniquement sur l’interface loopback ; n’exposez pas directement le port Node sur Internet. Si vos clients envoient une valeur Origin différente — par exemple une extension — ajoutez uniquement l’origine dont vous avez réellement besoin.
L’authentification Bearer de l’exemple convient à un test contrôlé et à un client qui permet de configurer cet en-tête. Pour plusieurs utilisateurs, des jetons avec des autorisations ou un accès OAuth, utilisez un flux d’authentification compatible avec vos clients MCP. Ne stockez aucun secret dans Git, dans un dépôt d’exemples ou dans les journaux.
Garder le processus actif et publier en HTTPS
Lancez l’application avec un compte système sans privilèges d’administration. Un service systemd peut la relancer après une panne ou au démarrage de la machine. Stockez MCP_BEARER_TOKEN dans un fichier d’environnement accessible en lecture uniquement par ce compte, plutôt que dans la ligne de commande ou le dépôt.
Placez Nginx devant le processus, terminez TLS pour le sous-domaine et transférez le chemin /mcp vers 127.0.0.1:3000/mcp. Conservez les en-têtes Host et Origin afin que la validation porte sur le domaine public, autorisez les méthodes HTTP requises par Streamable HTTP et désactivez le buffering des réponses SSE. Adaptez le délai de lecture si votre serveur peut produire des réponses longues. N’ouvrez pas les ports d’administration ni les bases de données vers l’extérieur.
Après avoir obtenu un certificat HTTPS, vérifiez depuis un réseau externe que le DNS pointe vers l’adresse IP du VPS et que le chemin MCP atteint bien le service. Les instructions Nginx exactes dépendent de votre certificat, de votre domaine, de la version du SDK et de l’utilisation éventuelle de sessions ; testez la configuration sur un sous-domaine avant d’y diriger du trafic réel.
Vérifier le protocole, l’accès et la reprise
Connectez un vrai client MCP — par exemple MCP Inspector — à l’endpoint HTTPS. Vérifiez qu’il peut initialiser la session, lister ping et recevoir pong. Recommencez sans jeton puis avec un Origin non autorisé : l’exemple doit refuser ces requêtes. Vérifiez également la méthode GET/SSE si votre serveur la propose, le redémarrage du service et l’absence de jetons dans les journaux.
Le test local de cet exemple a utilisé le client MCP officiel : l’appel sans jeton a reçu HTTP 401, le client autorisé a listé ping et obtenu pong, et une origine non autorisée a reçu HTTP 403. Cela valide l’exemple de protocole et ses contrôles ; cela ne prouve ni les performances, ni la disponibilité, ni la configuration de votre VPS en production.
Quand choisir un VPS et ce que cela implique
Un VPS convient si vous avez besoin d’un processus persistant, d’installer des paquets système, de contrôler le proxy ou d’adapter le réseau. Hostbrid fournit la machine virtuelle ; vous administrez le système d’exploitation, les mises à jour, les autorisations, l’application, les secrets, les sauvegardes et la réponse aux incidents. Consultez les tailles et tarifs VPS et vérifiez le coût total ainsi que les ressources avant de commander.
Une application Node.js sur l’hébergement Sites pourrait convenir à un MCP HTTP simple, mais la documentation publique ne confirme pas la compatibilité avec les sessions, le streaming SSE et les limites de connexion propres à chaque client. Testez ce comportement auprès de votre fournisseur avant de vous y fier. Projects est conçu pour compiler et publier des dépôts web ; ne le considérez pas comme un hébergement persistant de processus MCP sans en avoir vérifié les limites.
Si le service stocke des données, définissez une sauvegarde et testez leur restauration. Si un outil peut supprimer des données, modifier des autorisations ou engager des dépenses, ajoutez des autorisations explicites, des limites et une confirmation humaine. Le format MCP relie des clients à des outils ; il ne rend pas ces outils sûrs par lui-même.