Construire et auto-heberger un serveur MCP sur un VPS
Construisez un serveur MCP en TypeScript, deployez-le sur un VPS avec systemd derriere Nginx et TLS. Connectez Claude Desktop, Claude Code et Cursor a votre serveur auto-heberge.
Tous les tutoriels MCP s'arretent a « lancer en local avec stdio ». Celui-ci couvre le parcours complet : construire un serveur MCP en TypeScript, le deployer sur un VPS derriere Nginx avec TLS, le securiser avec authentification et regles de pare-feu, et connecter des clients MCP via internet.
A la fin, vous aurez un serveur MCP en production accessible depuis Claude Desktop, Claude Code, Cursor ou tout client compatible MCP.
Que construisez-vous ?
Les clients MCP envoient des requetes JSON-RPC via HTTPS. Nginx termine le TLS et proxifie les requetes vers le processus MCP qui tourne sur un port local. Le serveur MCP valide un bearer token, traite la requete et renvoie le resultat.
MCP Client (Claude, Cursor, ...)
|
| HTTPS (port 443)
v
Nginx (TLS termination + reverse proxy)
|
| HTTP (port 3000, localhost only)
v
MCP Server (Node.js + Express)
|
v
SQLite database
L'exemple est un serveur de notes. Il expose deux tools (rechercher des notes, creer une note) et une resource (lister toutes les notes). Assez simple pour suivre, assez utile pour etre etendu.
Quel transport utiliser pour un serveur MCP distant ?
Streamable HTTP est le standard actuel de la specification MCP pour les deploiements distants. Il remplace le transport SSE deprecie et fonctionne avec des requetes HTTP POST classiques. Stdio reste le transport pour les serveurs locaux ou le client lance le serveur en sous-processus.
| Transport | Cas d'usage | Compatible distant | Support client |
|---|---|---|---|
| stdio | Outils locaux, integrations CLI | Non | Tous les clients |
| SSE (deprecie) | Serveurs distants legacy | Oui | La plupart (en cours d'abandon) |
| Streamable HTTP | Serveurs distants, production | Oui | Claude Desktop, Claude Code, Cursor |
Streamable HTTP envoie chaque message client en HTTP POST vers un endpoint unique (ex : /mcp). Le serveur repond en application/json pour les reponses simples ou en text/event-stream quand il doit streamer plusieurs messages. Cela fonctionne avec l'infrastructure HTTP standard, y compris les reverse proxies et les load balancers.
Prerequis
- Un VPS sous Debian 12 ou Ubuntu 24.04 (ce guide utilise Debian 12)
- Un nom de domaine avec un enregistrement DNS pointant vers votre VPS (ex :
mcp.example.com) - Node.js 20+ installe sur le VPS
- Connaissance de base de TypeScript et Linux
Comment configurer un projet de serveur MCP en TypeScript ?
Commencez sur votre machine locale ou directement sur le VPS. Initialisez le projet, installez le SDK MCP et configurez TypeScript.
mkdir mcp-notes-server && cd mcp-notes-server
npm init -y
npm install @modelcontextprotocol/sdk zod express better-sqlite3
npm install -D typescript @types/node @types/express @types/better-sqlite3
Creez la configuration TypeScript :
{
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"outDir": "./build",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true
},
"include": ["src/**/*"]
}
Enregistrez ce fichier sous tsconfig.json a la racine du projet.
Mettez a jour package.json pour ajouter les scripts de build et de demarrage et definir le type de module :
{
"type": "module",
"scripts": {
"build": "tsc",
"start": "node build/index.js"
}
}
Creez le repertoire source :
mkdir src
Comment implementer des tools MCP avec validation des entrees ?
Un serveur MCP expose des tools, des resources et des prompts aux clients IA. Les tools sont des fonctions que l'IA peut appeler. Les resources sont des donnees en lecture seule que l'IA peut consulter. Nous allons implementer les deux.
Creez src/index.ts avec la configuration de la base de donnees et une fonction factory qui construit un nouveau serveur MCP pour chaque requete. Le Streamable HTTP stateless necessite une nouvelle instance McpServer par requete car le SDK ne permet pas de reconnecter le meme serveur a un transport different.
import express from "express";
import { randomUUID } from "crypto";
import Database from "better-sqlite3";
import { z } from "zod";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
// --- Database setup ---
const db = new Database("notes.db");
db.pragma("journal_mode = WAL");
db.exec(`
CREATE TABLE IF NOT EXISTS notes (
id TEXT PRIMARY KEY,
title TEXT NOT NULL,
content TEXT NOT NULL,
created_at TEXT DEFAULT (datetime('now'))
)
`);
// --- MCP Server factory ---
// Each stateless request needs its own McpServer + transport pair.
// The SDK binds a server to a single transport on connect() and
// throws if you try to reuse it. A factory function keeps it clean.
function createServer(): McpServer {
const server = new McpServer({
name: "notes-server",
version: "1.0.0",
});
Enregistrez maintenant les tools dans la factory. Chaque tool utilise Zod pour la validation des entrees. Le SDK valide automatiquement les inputs avant l'execution du handler.
// --- Tools ---
server.tool(
"search_notes",
"Search notes by keyword in title or content",
{
query: z.string().min(1).describe("Search keyword"),
},
async ({ query }) => {
const stmt = db.prepare(
"SELECT id, title, content, created_at FROM notes WHERE title LIKE ? OR content LIKE ? ORDER BY created_at DESC LIMIT 20"
);
const rows = stmt.all(`%${query}%`, `%${query}%`);
return {
content: [
{
type: "text" as const,
text: JSON.stringify(rows, null, 2),
},
],
};
}
);
server.tool(
"create_note",
"Create a new note with a title and content",
{
title: z.string().min(1).max(200).describe("Note title"),
content: z.string().min(1).describe("Note content"),
},
async ({ title, content }) => {
const id = randomUUID();
const stmt = db.prepare(
"INSERT INTO notes (id, title, content) VALUES (?, ?, ?)"
);
stmt.run(id, title, content);
return {
content: [
{
type: "text" as const,
text: `Note created with id: ${id}`,
},
],
};
}
);
Chaque entree est validee par Zod avant d'atteindre le handler. Si un client envoie { query: "" }, le SDK retourne automatiquement une erreur de validation. Pas besoin de parsing manuel.
Comment ajouter des resources a un serveur MCP ?
Les resources donnent aux clients IA un acces en lecture seule aux donnees. Elles sont referencees par URI. Ajoutez une resource qui liste toutes les notes, toujours dans la factory createServer :
// --- Resources ---
server.resource(
"all-notes",
"notes://all",
{
description: "List all notes in the database",
mimeType: "application/json",
},
async (uri) => {
const rows = db.prepare(
"SELECT id, title, created_at FROM notes ORDER BY created_at DESC LIMIT 100"
).all();
return {
contents: [
{
uri: uri.href,
mimeType: "application/json",
text: JSON.stringify(rows, null, 2),
},
],
};
}
);
return server;
}
Les clients MCP peuvent decouvrir cette resource et la lire sans appeler un tool. Claude Desktop affiche les resources dans le menu des pieces jointes. Claude Code les expose via les mentions @.
Comment securiser un serveur MCP avec un token d'authentification ?
Un serveur MCP en production necessite une authentification. Sans elle, quiconque decouvre votre endpoint peut appeler vos tools. Utilisez un bearer token verifie dans un middleware Express avant que les requetes n'atteignent le transport MCP.
Generez un token solide :
openssl rand -base64 32
Conservez le resultat. Vous en aurez besoin pour la configuration du serveur et des clients.
Ajoutez le middleware d'authentification et les routes Express dans src/index.ts :
// --- Auth middleware ---
const AUTH_TOKEN = process.env.MCP_AUTH_TOKEN;
if (!AUTH_TOKEN) {
console.error("MCP_AUTH_TOKEN environment variable is required");
process.exit(1);
}
function authenticateRequest(
req: express.Request,
res: express.Response,
next: express.NextFunction
): void {
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith("Bearer ")) {
res.status(401).json({
jsonrpc: "2.0",
error: { code: -32001, message: "Missing or invalid authorization" },
id: null,
});
return;
}
const token = authHeader.slice(7);
if (token !== AUTH_TOKEN) {
res.status(403).json({
jsonrpc: "2.0",
error: { code: -32001, message: "Invalid token" },
id: null,
});
return;
}
next();
}
// --- Express app ---
const app = express();
app.use(express.json());
app.use("/mcp", authenticateRequest);
Le middleware s'execute avant chaque requete vers /mcp. Il verifie la presence d'un token Bearer dans le header Authorization et rejette les requetes non autorisees avec une erreur JSON-RPC.
Comment configurer le transport Streamable HTTP ?
Ajoutez la configuration du transport et les handlers de routes. Chaque requete cree un nouveau McpServer depuis la factory et une nouvelle instance de transport :
// --- Streamable HTTP transport ---
app.post("/mcp", async (req, res) => {
const server = createServer();
const transport = new StreamableHTTPServerTransport({
sessionIdGenerator: undefined,
});
await server.connect(transport);
try {
await transport.handleRequest(req, res, req.body);
} catch (error) {
console.error("MCP request error:", error);
if (!res.headersSent) {
res.status(500).json({
jsonrpc: "2.0",
error: { code: -32603, message: "Internal server error" },
id: null,
});
}
}
});
app.get("/mcp", (_req, res) => {
res.status(405).json({
jsonrpc: "2.0",
error: { code: -32000, message: "Method not allowed. Use POST." },
id: null,
});
});
app.delete("/mcp", (_req, res) => {
res.status(405).json({
jsonrpc: "2.0",
error: { code: -32000, message: "Method not allowed." },
id: null,
});
});
// --- Health check ---
app.get("/health", (_req, res) => {
res.json({ status: "ok" });
});
// --- Start ---
const PORT = parseInt(process.env.PORT || "3000", 10);
app.listen(PORT, "127.0.0.1", () => {
console.log(`MCP server listening on http://127.0.0.1:${PORT}/mcp`);
});
sessionIdGenerator: undefined cree un serveur stateless. Chaque requete est independante, avec sa propre paire McpServer + transport. C'est plus simple a deployer et fonctionne bien derriere un reverse proxy sans session sticky. La connexion a la base de donnees (db) est au scope du module et partagee entre les requetes, donc les donnees persistent entre les appels.
Le serveur ecoute sur 127.0.0.1, pas 0.0.0.0. Il n'accepte que les connexions locales. Nginx sera le seul moyen d'y acceder depuis l'exterieur.
Compilez et testez en local :
npm run build
Verifiez que le build reussit sans erreur.
Comment tester un serveur MCP en local ?
MCP Inspector est l'outil de test officiel. Il se connecte a votre serveur et vous permet d'appeler les tools de facon interactive.
Demarrez votre serveur dans un terminal :
MCP_AUTH_TOKEN=test-token-local npm start
Dans un autre terminal, testez avec curl :
curl -X POST http://127.0.0.1:3000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer test-token-local" \
-d '{
"jsonrpc": "2.0",
"method": "initialize",
"params": {
"protocolVersion": "2025-03-26",
"capabilities": {},
"clientInfo": { "name": "test-client", "version": "1.0.0" }
},
"id": 1
}'
Vous devriez voir une reponse SSE (event: message suivie d'une ligne data:) contenant les capacites du serveur, y compris les objets tools et resources. Cela confirme que le serveur accepte les connexions et repond au handshake d'initialisation MCP.
Testez le tool create_note :
curl -X POST http://127.0.0.1:3000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer test-token-local" \
-d '{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "create_note",
"arguments": { "title": "Test Note", "content": "Hello from curl" }
},
"id": 2
}'
La reponse devrait contenir "Note created with id: ...". Testez maintenant le tool de recherche :
curl -X POST http://127.0.0.1:3000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer test-token-local" \
-d '{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "search_notes",
"arguments": { "query": "Test" }
},
"id": 3
}'
Vous devriez voir la note que vous venez de creer dans les resultats. Verifiez qu'une requete sans header Authorization retourne une erreur 401 :
curl -s -o /dev/null -w "%{http_code}" -X POST http://127.0.0.1:3000/mcp \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"initialize","params":{},"id":1}'
Cela devrait afficher 401. Si c'est le cas, votre middleware d'authentification fonctionne.
Vous pouvez aussi utiliser le MCP Inspector pour des tests interactifs avec une interface web :
npx @modelcontextprotocol/inspector
L'Inspector ouvre une interface dans le navigateur ou vous pouvez vous connecter au serveur, parcourir les tools et resources, et tester les appels.
Comment deployer un serveur MCP sur un VPS ?
Transferez votre projet sur le VPS avec rsync, scp, ou poussez vers un depot Git et clonez sur le serveur. Les etapes suivantes supposent que vous etes connecte au VPS.
Creer un utilisateur dedie
Ne lancez jamais de processus applicatifs en root. Creez un utilisateur de service :
sudo useradd -r -m -s /usr/sbin/nologin mcpserver
Installer Node.js
Si Node.js 20+ n'est pas deja installe :
curl -fsSL https://deb.nodesource.com/setup_20.x -o nodesource_setup.sh
sudo bash nodesource_setup.sh
sudo apt-get install -y nodejs
node --version
npm --version
La premiere commande telecharge le script d'installation dans un fichier pour que vous puissiez l'inspecter avant de l'executer. Verifiez que la sortie affiche v20.x.x ou superieur pour Node.js et 10.x.x pour npm. Le SDK MCP necessite Node.js 18+ mais la version 20 LTS est recommandee en production.
Configurer le repertoire du projet
sudo mkdir -p /opt/mcp-notes-server
sudo cp -r /path/to/your/project/* /opt/mcp-notes-server/
cd /opt/mcp-notes-server
sudo npm ci --omit=dev
sudo npm run build
sudo chown -R mcpserver:mcpserver /opt/mcp-notes-server
Verifiez les droits :
ls -la /opt/mcp-notes-server/
Tous les fichiers doivent appartenir a mcpserver:mcpserver.
Creer le fichier d'environnement
Stockez le token d'authentification dans un fichier d'environnement restreint :
sudo mkdir -p /etc/mcp-notes-server
echo "MCP_AUTH_TOKEN=$(openssl rand -base64 32)" | sudo tee /etc/mcp-notes-server/env > /dev/null
sudo chmod 600 /etc/mcp-notes-server/env
sudo chown mcpserver:mcpserver /etc/mcp-notes-server/env
Lisez le token genere et conservez-le en lieu sur. Vous en aurez besoin pour la configuration des clients :
sudo cat /etc/mcp-notes-server/env
Creer le service systemd
sudo tee /etc/systemd/system/mcp-notes-server.service > /dev/null << 'EOF'
[Unit]
Description=MCP Notes Server
After=network.target
[Service]
Type=simple
User=mcpserver
Group=mcpserver
WorkingDirectory=/opt/mcp-notes-server
EnvironmentFile=/etc/mcp-notes-server/env
ExecStart=/usr/bin/node build/index.js
Restart=on-failure
RestartSec=5
StandardOutput=journal
StandardError=journal
# Hardening
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/opt/mcp-notes-server
PrivateTmp=true
[Install]
WantedBy=multi-user.target
EOF
EnvironmentFile charge MCP_AUTH_TOKEN depuis le fichier restreint. La section hardening limite les actions du processus. NoNewPrivileges empeche l'escalade de privileges. ProtectSystem=strict rend le systeme de fichiers en lecture seule sauf pour les chemins listes dans ReadWritePaths. ProtectHome bloque l'acces aux repertoires home des utilisateurs.
Activez et demarrez le service :
sudo systemctl enable --now mcp-notes-server
enable fait demarrer le service au boot. --now le lance immediatement.
Verifiez le statut :
sudo systemctl status mcp-notes-server
Vous devriez voir active (running). Si le service a echoue, consultez les logs :
journalctl -u mcp-notes-server -n 50 --no-pager
Verifiez que le serveur repond en local :
TOKEN=$(sudo grep MCP_AUTH_TOKEN /etc/mcp-notes-server/env | cut -d= -f2)
curl -s http://127.0.0.1:3000/health
Cela devrait retourner {"status":"ok"}.
Comment faire tourner un serveur MCP derriere Nginx avec TLS ?
Nginx termine le TLS et proxifie les requetes vers le serveur MCP. Le serveur MCP ne gere jamais le TLS directement. C'est le schema standard pour les deploiements Node.js en production.
Installer Nginx et Certbot
sudo apt update
sudo apt install -y nginx certbot python3-certbot-nginx
Configurer le server block Nginx
sudo tee /etc/nginx/sites-available/mcp.example.com.conf > /dev/null << 'NGINX'
server {
listen 80;
listen [::]:80;
server_name mcp.example.com;
# Certbot will add the redirect to HTTPS
location / {
return 444;
}
}
NGINX
Remplacez mcp.example.com par votre domaine reel.
Activez le site et obtenez un certificat TLS :
sudo ln -s /etc/nginx/sites-available/mcp.example.com.conf /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
sudo certbot --nginx -d mcp.example.com
Certbot modifie la configuration pour ajouter les parametres TLS et une redirection HTTP vers HTTPS. Mettez maintenant a jour la configuration pour ajouter le reverse proxy vers l'endpoint MCP :
sudo tee /etc/nginx/sites-available/mcp.example.com.conf > /dev/null << 'NGINX'
server {
listen 80;
listen [::]:80;
server_name mcp.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name mcp.example.com;
ssl_certificate /etc/letsencrypt/live/mcp.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mcp.example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
# Hide Nginx version
server_tokens off;
# MCP endpoint
location /mcp {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
# Required for Streamable HTTP / SSE responses
proxy_buffering off;
proxy_cache off;
chunked_transfer_encoding off;
# Keep connection open for streaming responses
proxy_set_header Connection "";
# Extended timeouts for long-running tool calls
proxy_read_timeout 300s;
proxy_send_timeout 300s;
# Forward client info
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Pass through Authorization header
proxy_set_header Authorization $http_authorization;
}
# Health check (no auth required)
location /health {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
}
# Block everything else
location / {
return 444;
}
}
NGINX
Les directives cles pour la compatibilite MCP :
proxy_buffering offempeche Nginx de mettre en tampon les reponses SSE. Sans cela, les reponses en streaming restent bloquees jusqu'a la fermeture de la connexion.proxy_cache offgarantit qu'aucune reponse dynamique n'est mise en cache.chunked_transfer_encoding offevite les problemes de chunking avec les flux SSE.Connection ""maintient la connexion ouverte sans declencher de comportement d'upgrade WebSocket.proxy_read_timeout 300sautorise les appels de tools a prendre jusqu'a 5 minutes. Le defaut de 60s est trop court pour des operations longues.
Testez et rechargez :
sudo nginx -t
sudo systemctl reload nginx
Verifiez depuis votre machine locale (pas le serveur) :
curl -s https://mcp.example.com/health
Cela devrait retourner {"status":"ok"}. Si c'est le cas, Nginx proxifie correctement vers votre serveur MCP avec TLS.
Regles de pare-feu
Bloquez l'acces direct au port 3000 depuis l'exterieur. Seul Nginx (sur localhost) doit atteindre le serveur MCP :
sudo apt install -y ufw
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
Verifiez que le port 3000 n'est pas accessible depuis l'exterieur :
# From your local machine, this should time out or be refused:
curl -s --connect-timeout 5 http://YOUR_VPS_IP:3000/health
La connexion devrait echouer. Votre serveur MCP n'est accessible que via Nginx sur le port 443.
Comment connecter des clients MCP a un serveur distant ?
Avec le serveur en fonctionnement derriere Nginx avec TLS, configurez vos clients MCP.
Claude Code
Ajoutez le serveur distant via le CLI :
claude mcp add --transport http \
--header "Authorization: Bearer YOUR_TOKEN_HERE" \
notes-server https://mcp.example.com/mcp
Remplacez YOUR_TOKEN_HERE par le token de /etc/mcp-notes-server/env.
Verifiez la connexion :
claude mcp list
Dans Claude Code, tapez /mcp pour verifier le statut du serveur. Le notes-server devrait apparaitre comme connecte avec les tools search_notes et create_note disponibles.
Claude Desktop
Claude Desktop se connecte aux serveurs MCP distants via l'interface Settings. Allez dans Settings > Connectors et ajoutez un nouveau serveur distant avec l'URL https://mcp.example.com/mcp.
Si vous devez passer le bearer token, vous pouvez aussi le configurer via un fichier .mcp.json local ou la commande CLI claude mcp add montree ci-dessus et importer le serveur dans Claude Desktop :
claude mcp add-from-claude-desktop
Cursor
Ouvrez les parametres de Cursor et naviguez vers la configuration MCP. Ajoutez un nouveau serveur dans le fichier mcp.json (ou via l'interface des parametres Cursor) :
{
"mcpServers": {
"notes-server": {
"url": "https://mcp.example.com/mcp",
"headers": {
"Authorization": "Bearer YOUR_TOKEN_HERE"
}
}
}
}
Cursor tente Streamable HTTP en premier lors de la connexion a une URL, donc aucune configuration de transport supplementaire n'est necessaire.
Verifier la connexion de bout en bout
Depuis n'importe quel client connecte, demandez a l'IA de :
- Creer une note : « Cree une note intitulee 'Server Test' avec le contenu 'Connected successfully' »
- La rechercher : « Cherche dans mes notes 'Server Test' »
Si les deux operations retournent des resultats, la chaine complete fonctionne : client vers Nginx vers serveur MCP vers SQLite et retour.
Reference des primitives MCP
| Primitive | Fonction | Exemple |
|---|---|---|
| Tools | Fonctions que l'IA peut appeler avec des entrees structurees | search_notes, create_note |
| Resources | Donnees en lecture seule que l'IA peut consulter | listing de notes notes://all |
| Prompts | Templates pre-ecrits pour des taches courantes | Non utilise dans ce tutoriel |
Les tools sont la primitive la plus souvent implementee. Les resources servent a exposer des donnees de reference sans calcul. Les prompts permettent de creer des templates reutilisables qui guident l'IA a travers des workflows specifiques.
Quelque chose ne fonctionne pas ?
Le serveur ne demarre pas : Verifiez le journal pour les erreurs :
journalctl -u mcp-notes-server -n 50 --no-pager
Causes frequentes : variable d'environnement MCP_AUTH_TOKEN manquante, permissions incorrectes sur notes.db, version de Node.js trop ancienne.
Nginx retourne 502 Bad Gateway : Le serveur MCP ne tourne pas ou n'ecoute pas sur le port 3000. Verifiez :
sudo systemctl status mcp-notes-server
curl -s http://127.0.0.1:3000/health
Le client recoit 401 Unauthorized : Le token dans la configuration du client ne correspond pas au token sur le serveur. Verifiez :
sudo cat /etc/mcp-notes-server/env
Les reponses en streaming expirent : Augmentez proxy_read_timeout dans la configuration Nginx. Les 300s par defaut couvrent la plupart des cas, mais des tools longs peuvent necessiter plus.
Erreurs de certificat : Verifiez que le certificat est valide et couvre votre domaine :
sudo certbot certificates
Si le certificat a expire, renouvelez-le :
sudo certbot renew
Erreurs de base de donnees verrouillee : Le mode WAL de SQLite gere bien les lectures concurrentes, mais les ecritures concurrentes peuvent entrer en conflit. Pour les serveurs a fort trafic, envisagez PostgreSQL.
Permission refusee sur notes.db : L'utilisateur mcpserver a besoin d'un acces en ecriture au repertoire de travail pour SQLite. Verifiez :
ls -la /opt/mcp-notes-server/notes.db
Le fichier doit appartenir a mcpserver:mcpserver. S'il a ete cree par root lors des tests, corrigez :
sudo chown mcpserver:mcpserver /opt/mcp-notes-server/notes.db
sudo chmod 640 /opt/mcp-notes-server/notes.db
Le client affiche « connection refused » ou « timeout » : Verifiez que votre enregistrement DNS A pointe vers l'IP du VPS et que les ports 80 et 443 sont ouverts dans le pare-feu :
sudo ufw status
dig +short mcp.example.com
La sortie de dig doit afficher l'adresse IP de votre VPS. Si ce n'est pas le cas, mettez a jour vos enregistrements DNS et attendez la propagation.
Prochaines etapes
Votre serveur MCP est en ligne et securise. Pistes pour la suite :
- Ajouter des tools qui se connectent a vos bases de donnees, API ou systemes de fichiers
- Implementer OAuth 2.1 au lieu des bearer tokens pour un acces multi-utilisateurs
- Ajouter du rate limiting dans Express ou Nginx pour proteger contre les abus
- Mettre en place du monitoring avec
journalctl -u mcp-notes-server -fet de l'alerting - Deployer plusieurs serveurs MCP derriere la meme instance Nginx sur des chemins differents
La documentation officielle du SDK MCP couvre les patterns avances, y compris les sessions stateful, le reporting de progression et les schemas de sortie structures.
Copyright 2026 Virtua.Cloud. Tous droits reserves. Ce contenu est une creation originale de l'equipe Virtua.Cloud. Toute reproduction, republication ou redistribution sans autorisation ecrite est interdite.
Prêt à essayer ?
Déployez votre serveur en quelques secondes. Linux, Windows ou FreeBSD.
Voir les offres VPS