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_db con 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.