Le ricerche per “mcp server” superano le 60 000 al mese negli Stati Uniti: tutti gli assistenti AI più diffusi, da Claude a Copilot di VS Code, comunicano con il mondo esterno tramite questo unico protocollo. La maggior parte dei tutorial si ferma al classico “hello world” e ignora la parte critica, ovvero la gestione di file, database e chiavi API. Questa guida, aggiornata al 2026, ti accompagna passo dopo passo nella costruzione di un server MCP sicuro, partendo da un semplice script Python fino a una distribuzione remota con autenticazione.
Cos'è il Model Context Protocol e perché va indurito
Anthropic ha introdotto il Model Context Protocol (MCP) a novembre 2024 come standard aperto per collegare i modelli di IA a strumenti e dati esterni senza dover scrivere integrazioni personalizzate per ogni coppia di sistemi. Nella sua prima comunicazione, l’azienda ha affermato: “Oggi open‑sourceamo il Model Context Protocol, un nuovo standard per connettere assistenti AI ai sistemi dove risiedono i dati, includendo repository di contenuti, strumenti aziendali e ambienti di sviluppo.”
Due anni dopo, la specifica più recente è stata rilasciata il 28 luglio 2026 e il protocollo è ormai la “plumbing” predefinita per le AI agentiche. AgentMarketCap segnala più di 10 000 server MCP attivi e circa 97 milioni di download SDK in 17 mesi (aprile 2026).
Il motivo per cui la sicurezza è cruciale è semplice: gli strumenti esposti al modello diventano potenzialmente eseguibili dal modello stesso, anche se il suo input proviene da pagine web o documenti non fidati. Se il server accetta l’input senza validazione, si crea un primitivo di esecuzione di codice remoto. Il report “2026 MCP security” di Practical DevSecOps elenca vulnerabilità comuni, tra cui accessi troppo ampi ai file e tool che modificano il comportamento dopo l’installazione.
Diffusione dell'ecosistema MCP
Il protocollo non è più limitato ai prodotti Anthropic. VS Code ha introdotto l’integrazione MCP nella versione 1.102 (metà 2025) e da allora molti editor e IDE hanno seguito. Microsoft ha lanciato Azure MCP Server 3.0 (ottobre 2026) e la beta Azure MCP Server 4.0.0‑beta.6 (novembre 2026). MongoDB Local MCP Server v3.2.1 ha aggiunto l’opzione timeoutMs (ottobre 2026) e JFrog ha rilasciato la versione 1.148 (ottobre 2026).
Questa diffusione rende l’investimento in un server MCP non legato a Claude: una volta costruito correttamente, il server può essere utilizzato da qualsiasi client compatibile, riducendo i costi di sviluppo a lungo termine.
Versioni della specifica e supporto client
La specifica più recente è il rilascio del 28 luglio 2026; la proposta di ciclo di rilascio sposta la data di versione successiva da dicembre 2026 a 30 marzo 2027. Le implementazioni più comuni (Quarkus MCP Server v2.0.0 e v2.0.4) hanno adottato le API di versione protocollo ad agosto e ottobre 2026.
Il supporto client ora include Claude Desktop, Claude Code, Claude Cowork e le varianti di piano (Free, Pro, Max, Ultra, Team, Enterprise). Il modello più recente, Claude Haiku 5.5 (rilasciato 7 ottobre 2026), costa $0,10 per milione di token in ingresso e $0,50 per milione di token in uscita, ideale per test intensivi.
Casi d'uso reali di server MCP personalizzati
Prima di immergersi nella configurazione, è utile capire a quale scenario ci si sta dirigendo. I server MCP produttivi rientrano in quattro macro‑categorie:
- Wrapper di database: forniscono query su cataloghi prodotti, sistemi di ticket o store di metriche, tipicamente con credenziali in sola lettura e scrittura limitata a tool specifici.
- Accesso a file e documenti: espongono codice sorgente, knowledge base o unità di rete; richiedono difese contro path traversal (vedi Step 5).
- Wrapper di API: traduzione leggera di API REST/GraphQL per fornire al modello un set di strumenti ristretto.
- Workflow e automazione: attivano azioni come creazione di eventi in calendario o aperture di ticket, spesso con approvazione umana.
Scelta dell'architettura
Per la maggior parte dei progetti consigliamo un'architettura a micro‑servizi con Docker, perché facilita l'isolamento, la scalabilità e la gestione delle credenziali. Il passo 1 del tutorial prevede l'installazione di Python 3.12, pip e la creazione di un ambiente virtuale dedicato.
Guida passo‑passo: costruire e indurire il server MCP
Passo 1 – Preparare l’ambiente
```bash
sudo apt update && sudo apt install -y python3.12 python3.12-venv git
python3.12 -m venv mcp-env
source mcp-env/bin/activate
pip install fastapi uvicorn pydantic
```
Creiamo la struttura di progetto:
```bash
mkdir mcp-server && cd mcp-server
git init
touch main.py
```
Passo 2 – Implementare il server base
Nel file main.py inseriamo il modello di base MCP con FastAPI:
```python
from fastapi import FastAPI, Request, HTTPException
from pydantic import BaseModel
app = FastAPI(title="MCP Server 2026")
class MCPRequest(BaseModel):
tool: str
input: dict
@app.post("/mcp")
async def handle_mcp(req: MCPRequest):
# placeholder per la logica dei tool
return {"status": "ok", "tool": req.tool}
```
Avviamo il server con uvicorn main:app --host 0.0.0.0 --port 8000 e verifichiamo il “hello world” con curl -X POST -d '{"tool":"ping","input":{}}' http://localhost:8000/mcp.
Passo 3 – Aggiungere i tool concreti
Implementiamo tre tool di esempio: readfile, querydb e call_api. Ogni tool è una funzione separata, registrata in un dizionario TOOLS e richiamata dinamicamente in base al campo tool della richiesta.
```python
import os, json, sqlite3, requests
def read_file(input):
path = input.get("path")
# validazione path (vedi passo 5)
with open(path, "r") as f:
return {"content": f.read()}
def query_db(input):
conn = sqlite3.connect("catalog.db")
cur = conn.cursor()
cur.execute(input["sql"])
rows = cur.fetchall()
return {"rows": rows}
def call_api(input):
resp = requests.post(input["url"], json=input.get("payload", {}))
return {"statuscode": resp.statuscode, "body": resp.json()}
TOOLS = {"readfile": readfile, "querydb": querydb, "callapi": callapi}
```
Passo 4 – Validazione dell’input
Utilizziamo pydantic per definire schemi specifici per ogni tool, evitando payload arbitrari.
```python
class ReadFileInput(BaseModel):
path: str
class QueryDBInput(BaseModel):
sql: str
class CallAPIInput(BaseModel):
url: str
payload: dict = {}
```
Nel gestore handle_mcp scegliamo lo schema corretto e lo validiamo prima di eseguire il tool.
Passo 5 – Difese contro path traversal e injection
Per read_file limitiamo l’accesso a una directory whitelist, ad esempio /app/data. Verifichiamo che il percorso risolto sia effettivamente all’interno della directory consentita:
```python
BASE_DIR = os.path.abspath("/app/data")
def safepath(userpath):
abspath = os.path.abspath(os.path.join(BASEDIR, user_path))
if not abspath.startswith(BASEDIR):
raise HTTPException(status_code=400, detail="Path traversal detected")
return abs_path
```
Per query_db utilizziamo query parametrizzate e rifiutiamo comandi DDL o DML non consentiti.
Passo 6 – Autenticazione e autorizzazione
Implementiamo token JWT firmati con chiave RSA. Il client (Claude) deve includere l’header Authorization: Bearer <token>. Verifichiamo il token in un middleware FastAPI.
```python
from fastapi.security import HTTPBearer
from jose import jwt, JWTError
security = HTTPBearer()
@app.middleware("http")
async def authmiddleware(request: Request, callnext):
credentials = await security(request)
try:
payload = jwt.decode(credentials.credentials, PUBLIC_KEY, algorithms=["RS256"])
request.state.user = payload["sub"]
except JWTError:
raise HTTPException(status_code=401, detail="Invalid token")
response = await call_next(request)
return response
```
Passo 7 – Logging strutturato e monitoraggio
Usiamo structlog per generare log JSON contenenti timestamp, user, tool, e eventuali errori. Configuriamo un handler per inviare i log a un endpoint Loki o a CloudWatch.
Passo 8 – Test di integrazione con Claude Desktop
Dal client Claude, aggiungiamo l’endpoint http://localhost:8000/mcp e verifichiamo che i tool siano riconosciuti. Eseguiamo una serie di prompt di prova:
- “Leggi il file README.md” → dovrebbe chiamare
read_file. - “Recupera i prodotti dal catalogo” →
query_dbcon SQL predefinito. - “Invia i dati a https://api.example.com/ingest” →
call_api.
Passo 9 – Hardening del runtime
Creiamo un Dockerfile basato su python:3.12-slim, impostiamo USER nonroot e limiti di capacità Linux (seccomp, read‑only filesystem). Esempio:
```Dockerfile
FROM python:3.12-slim
WORKDIR /app
COPY . /app
RUN pip install --no-cache-dir fastapi uvicorn pydantic structlog python-jose
RUN adduser --system --group --no-create-home appuser
USER appuser
EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
```
Passo 10 – Deploy su cloud con certificati TLS
Su Azure, utilizziamo Azure Container Instances con un Application Gateway per terminare TLS. Generiamo certificati con Let's Encrypt (certbot) o usiamo i certificati gestiti da Azure.
Passo 11 – Rotazione delle chiavi e revoca
Implementiamo un endpoint interno /rotate-key protetto da admin JWT, che rigenera la chiave RSA, aggiorna le variabili d’ambiente e invalida i token precedenti.
Passo 12 – Audit post‑deployment
Eseguiamo scansioni con trivy per vulnerabilità di immagine, test di penetrazione con zap e verifiche di conformità OWASP Top 10. Documentiamo tutti i risultati in un report interno e impostiamo alert su metriche di utilizzo anomalo (es. numero di chiamate per tool).
Conclusioni
Seguendo questi 12 passaggi avrai un server MCP funzionante, pronto per gestire richieste da Claude, VS Code, o qualsiasi altro client compatibile, con una robusta superficie di sicurezza. La chiave è trattare ogni server come un punto di ingresso potenzialmente esposto: validare l’input, limitare i permessi, autenticare i client e monitorare costantemente il comportamento. Con queste pratiche, il tuo progetto passerà da “esperimento del weekend” a componente affidabile di un’infrastruttura AI aziendale.
