MCP e Cursor: Connetti il tuo IDE a Database e API
Immagina di poter chiedere al tuo IDE di accedere direttamente al tuo database PostgreSQL, interrogare le issue aperte su GitHub, leggere la documentazione da Confluence e chiamare API REST esterne, tutto senza mai uscire dall'editor e senza copiare-incollare manualmente dati e schemi. Non e fantascienza: e esattamente quello che permette il Model Context Protocol (MCP) integrato in Cursor.
MCP e uno standard aperto sviluppato da Anthropic e lanciato a novembre 2024 che definisce come i modelli di linguaggio possono comunicare con sistemi esterni in modo strutturato, sicuro e componibile. In pochi mesi e diventato lo standard de facto per l'integrazione tra AI e strumenti di sviluppo: Cursor lo ha adottato nativamente, e oggi l'ecosistema conta centinaia di server MCP pronti all'uso per database, API, filesystem, sistemi di ticketing e molto altro.
In questo articolo approfondiamo MCP da un punto di vista pratico e avanzato: architettura, configurazione in Cursor, server prebuilt per i casi d'uso più comuni, creazione di server custom in TypeScript, gestione della sicurezza e troubleshooting. Al termine avrai tutto il necessario per trasformare Cursor in un agente capace di interagire con l'intera infrastruttura del tuo progetto.
Cosa Imparerai in Questo Articolo
- Architettura MCP: host, client, server, tools, resources e prompts
- Configurare MCP in Cursor con il file
.cursor/mcp.json(scope progetto e globale) - Connettere Cursor a PostgreSQL, MySQL e SQLite via server MCP
- Integrare API REST, GraphQL, GitHub e Jira con server MCP prebuilt
- Creare un server MCP custom in TypeScript con l'SDK ufficiale
- Gestire sicurezza, permessi e rotazione delle credenziali
- Diagnosticare e risolvere i problemi più comuni di connessione MCP
- Confronto MCP vs approcci tradizionali di integrazione
Prerequisiti
- Cursor IDE installato (versione 0.43+ raccomandata per MCP stabile)
- Node.js 18+ e npm installati
- Conoscenza base di TypeScript e JSON
- Facoltativamente: un database PostgreSQL o MySQL accessibile per gli esempi pratici
1. Cos'è il Model Context Protocol
Il Model Context Protocol (MCP) e uno standard aperto basato su JSON-RPC 2.0 che definisce come un'applicazione AI (il client) può connettersi a sistemi esterni (i server) per ottenere contesto, eseguire azioni e accedere a risorse in modo strutturato. E il "linguaggio comune" che permette a Cursor di parlare con il tuo database nello stesso modo in cui potrebbe parlare con GitHub, Jira o qualsiasi altra API.
Prima di MCP, ogni IDE AI implementava le proprie integrazioni proprietarie: strumenti diversi, API diverse, formati diversi. Con MCP, un server scritto una volta funziona con Cursor, Claude Desktop, VS Code Copilot e qualsiasi altro client compatibile. E lo stesso principio che ha reso HTTP lo standard del web.
2. Architettura MCP: Host, Client e Server
L'architettura MCP si articola su tre livelli che e fondamentale comprendere prima di configurare qualsiasi integrazione:
I Tre Livelli MCP
- Host: l'applicazione con cui l'utente interagisce direttamente. In questo caso Cursor IDE. L'host gestisce il ciclo di vita dei client MCP e orchestra le interazioni con i modelli AI.
- Client MCP: il componente interno all'host che mantiene una connessione 1:1 con un singolo server MCP. Cursor gestisce automaticamente la creazione e il mantenimento dei client per ogni server configurato.
- Server MCP: processo esterno (o remoto) che espone capabilities: tools, resources e prompts. Può essere un processo locale (stdio) o un servizio remoto (HTTP/SSE).
Ogni server MCP espone tre tipi di primitive che il client può utilizzare:
// Primitive MCP: overview concettuale
// 1. TOOLS - azioni che il modello può invocare
// (lettura/scrittura, chiamate API, esecuzione query)
{
"name": "execute_query",
"description": "Esegue una query SQL sul database",
"inputSchema": {
"type": "object",
"properties": {
"query": { "type": "string" }
},
"required": ["query"]
}
}
// 2. RESOURCES - dati che il modello può leggere
// (simili a endpoint GET di una REST API)
{
"uri": "postgres://mydb/tables",
"name": "Database Tables",
"description": "Lista di tutte le tabelle del database",
"mimeType": "application/json"
}
// 3. PROMPTS - template riutilizzabili
// (istruzioni pre-costruite per task comuni)
{
"name": "analyze_schema",
"description": "Analizza lo schema del database e suggerisce ottimizzazioni",
"arguments": [
{ "name": "table_name", "required": true }
]
}
La comunicazione tra client e server avviene tramite JSON-RPC 2.0 su uno dei trasporti supportati:
- stdio (Standard I/O): il client avvia il server come processo figlio e comunica tramite stdin/stdout. E il trasporto più semplice e adatto per server locali. Cursor gestisce automaticamente il ciclo di vita del processo.
- Streamable HTTP: il server gira come servizio HTTP indipendente. Ideale per server remoti condivisi tra più sviluppatori o per integrazioni cloud. Dal marzo 2025 ha sostituito SSE come trasporto HTTP raccomandato.
SSE Transport Deprecato
Il trasporto SSE (Server-Sent Events) e stato deprecato dalla specifica MCP del 26 marzo 2025. Se stai
usando configurazioni SSE esistenti, migra al formato streamableHttp. Cursor versione
0.43+ supporta la nuova specifica.
3. Configurare MCP in Cursor
Cursor supporta due scope di configurazione MCP, che determinano dove sono disponibili i server configurati:
# Configurazione GLOBALE (disponibile in tutti i progetti)
~/.cursor/mcp.json
# Configurazione PROGETTO (solo nel workspace corrente)
.cursor/mcp.json <-- nella root del progetto
# La configurazione progetto ha PRIORITA su quella globale
# in caso di conflitti di nomi
La struttura base del file di configurazione e semplice e consistente tra i due scope:
// .cursor/mcp.json - Struttura base
{
"mcpServers": {
"nome-server": {
"command": "comando-da-eseguire",
"args": ["argomento1", "argomento2"],
"env": {
"VARIABILE": "valore"
}
}
}
}
Per server remoti via HTTP, la struttura e leggermente diversa:
// .cursor/mcp.json - Server remoto HTTP
{
"mcpServers": {
"nome-server-remoto": {
"url": "https://mio-server-mcp.example.com/mcp",
"headers": {
"Authorization": "Bearer {{env.MCP_API_TOKEN}}"
}
}
}
}
Dopo aver salvato il file di configurazione, riavvia Cursor o premi Cmd/Ctrl + Shift + P e cerca
"MCP: Reload Servers" per applicare le modifiche. Puoi verificare lo stato dei server in
Settings > MCP dove vedrai ogni server con indicatore verde (connesso) o rosso (errore).
4. Server MCP per Database
I server MCP per database sono tra i più utili per gli sviluppatori: permettono al modello AI di Cursor di ispezionare schemi, eseguire query, analizzare performance e suggerirti ottimizzazioni basate sulla struttura reale del tuo database, non su assunzioni generiche.
4.1 PostgreSQL
Il server MCP ufficiale per PostgreSQL di Anthropic espone lo schema del database come risorse MCP e permette di eseguire query in sola lettura (read-only per sicurezza):
// .cursor/mcp.json - PostgreSQL server ufficiale
{
"mcpServers": {
"postgres": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-postgres",
"postgresql://utente:password@localhost:5432/mio_database"
]
}
}
}
Non Mettere Credenziali nel File di Configurazione
Evita di inserire username e password direttamente nell'URL della stringa di connessione nel file
mcp.json, specialmente se il file e versionato in git. Usa variabili d'ambiente:
// .cursor/mcp.json - PostgreSQL con variabili d'ambiente
{
"mcpServers": {
"postgres": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-postgres"
],
"env": {
"POSTGRES_CONNECTION_STRING": "postgresql://{{env.DB_USER}}:{{env.DB_PASSWORD}}@localhost:5432/mio_database"
}
}
}
}
# Nel tuo .env (NON versionato):
DB_USER=myuser
DB_PASSWORD=supersecretpassword
Una volta configurato, puoi interagire con il database direttamente dalla chat di Cursor:
Esempi di Prompt con PostgreSQL MCP
- "Mostrami lo schema della tabella users e dimmi se mancano indici importanti"
- "Quante righe ci sono nella tabella orders create nell'ultimo mese?"
- "Analizza questa query lenta e suggerisci ottimizzazioni basate sullo schema reale"
- "Genera una migration TypeORM per aggiungere la colonna email_verified alla tabella users"
4.2 MySQL e MariaDB
Per MySQL e MariaDB esistono server MCP community che offrono funzionalità simili:
// .cursor/mcp.json - MySQL tramite server community
{
"mcpServers": {
"mysql": {
"command": "npx",
"args": ["-y", "@benborla29/mcp-server-mysql"],
"env": {
"MYSQL_HOST": "localhost",
"MYSQL_PORT": "3306",
"MYSQL_USER": "root",
"MYSQL_PASS": "password",
"MYSQL_DB": "mio_database",
"ALLOW_INSERT_OPERATION": "false",
"ALLOW_UPDATE_OPERATION": "false",
"ALLOW_DELETE_OPERATION": "false"
}
}
}
}
4.3 SQLite per Sviluppo Locale
// .cursor/mcp.json - SQLite (ottimo per sviluppo locale e test)
{
"mcpServers": {
"sqlite": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-sqlite",
"--db-path",
"./database/dev.db"
]
}
}
}
5. Server MCP per API e Servizi Esterni
Oltre ai database, l'ecosistema MCP offre server prebuilt per integrare i tool più comuni nel workflow di sviluppo quotidiano.
5.1 GitHub MCP
Il server MCP ufficiale di GitHub (mantenuto direttamente da GitHub) permette di gestire repository, issue, pull request, workflow CI/CD e molto altro direttamente dalla chat di Cursor:
// .cursor/mcp.json - GitHub MCP ufficiale (via Docker)
// NOTA: Il package npm e stato deprecato ad aprile 2025
// Usa l'immagine Docker ufficiale:
{
"mcpServers": {
"github": {
"command": "docker",
"args": [
"run",
"--rm",
"-i",
"-e", "GITHUB_PERSONAL_ACCESS_TOKEN",
"ghcr.io/github/github-mcp-server"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_xxxxxxxxxxxx"
}
}
}
}
// Alternativa: via npx (versione community)
{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_xxxxxxxxxxxx"
}
}
}
}
Con il server GitHub configurato, Cursor può:
- Leggere e creare issue e pull request
- Analizzare la cronologia dei commit per capire il contesto di un bug
- Cercare nel codice di repository pubblici e privati
- Triggherare workflow GitHub Actions
- Leggere e scrivere commenti su PR
5.2 Filesystem MCP
Il server filesystem di Anthropic permette al modello di leggere e scrivere file su percorsi specifici, con controllo granulare degli accessi:
// .cursor/mcp.json - Filesystem con accesso limitato
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/Users/federicocalo/progetti",
"/tmp/cursor-workspace"
]
}
}
}
// ATTENZIONE: specifica SOLO le directory necessarie
// Non dare accesso a / (root) o home directory completa
5.3 Configurazione Multi-Server
Un aspetto potente di MCP in Cursor e la possibilità di configurare più server contemporaneamente, combinando database, API esterne e tool interni in un unico file:
// .cursor/mcp.json - Configurazione completa multi-server
{
"mcpServers": {
// Database principale
"postgres-prod": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-postgres"],
"env": {
"POSTGRES_CONNECTION_STRING": "postgresql://user:pass@prod-db:5432/app"
}
},
// Database di sviluppo
"postgres-dev": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-postgres"],
"env": {
"POSTGRES_CONNECTION_STRING": "postgresql://user:pass@localhost:5432/app_dev"
}
},
// Repository GitHub
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_xxxx"
}
},
// Filesystem progetti
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/Users/federicocalo/progetti/mio-app"
]
},
// Server custom interno
"api-interna": {
"command": "node",
"args": ["/Users/federicocalo/mcp-servers/api-server/dist/index.js"],
"env": {
"API_BASE_URL": "https://api.mia-azienda.com",
"API_KEY": "key_xxxx"
}
}
}
}
6. Creare un Server MCP Custom in TypeScript
I server prebuilt coprono molti casi d'uso comuni, ma spesso avrai bisogno di connettere Cursor a sistemi interni, API proprietarie o logiche specifiche del tuo progetto. L'SDK TypeScript ufficiale rende la creazione di server custom sorprendentemente semplice.
6.1 Setup del Progetto
# Inizializza il progetto
mkdir mio-mcp-server
cd mio-mcp-server
npm init -y
# Installa le dipendenze
npm install @modelcontextprotocol/sdk zod
npm install -D typescript @types/node ts-node
# Configura TypeScript
npx tsc --init --target ES2022 --module commonjs --outDir dist
// package.json - scripts necessari
{
"name": "mio-mcp-server",
"version": "1.0.0",
"main": "dist/index.js",
"scripts": {
"build": "tsc",
"start": "node dist/index.js",
"dev": "ts-node src/index.ts"
},
"dependencies": {
"@modelcontextprotocol/sdk": "^1.0.0",
"zod": "^3.22.0"
},
"devDependencies": {
"typescript": "^5.3.0",
"@types/node": "^20.0.0",
"ts-node": "^10.9.0"
}
}
6.2 Server MCP Base con Tools e Resources
Vediamo come costruire un server MCP completo che espone tool per interrogare un'API REST interna e resources per esporre dati statici:
// src/index.ts - Server MCP completo
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
CallToolRequestSchema,
ListResourcesRequestSchema,
ListToolsRequestSchema,
ReadResourceRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
import { z } from "zod";
const API_BASE_URL = process.env.API_BASE_URL || "https://api.esempio.com";
const API_KEY = process.env.API_KEY || "";
// Inizializza il server MCP
const server = new Server(
{
name: "mio-server-mcp",
version: "1.0.0",
},
{
capabilities: {
resources: {},
tools: {},
},
}
);
// === TOOLS ===
// I tools sono azioni che il modello può invocare
// Lista i tools disponibili
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: "get_utenti",
description: "Recupera la lista degli utenti attivi dall'API",
inputSchema: {
type: "object",
properties: {
limite: {
type: "number",
description: "Numero massimo di utenti da restituire (default: 10)",
},
ruolo: {
type: "string",
enum: ["admin", "user", "guest"],
description: "Filtra per ruolo utente",
},
},
required: [],
},
},
{
name: "crea_report",
description: "Genera un report aggregato per un periodo specificato",
inputSchema: {
type: "object",
properties: {
data_inizio: {
type: "string",
format: "date",
description: "Data inizio periodo (YYYY-MM-DD)",
},
data_fine: {
type: "string",
format: "date",
description: "Data fine periodo (YYYY-MM-DD)",
},
tipo: {
type: "string",
enum: ["vendite", "utenti", "performance"],
description: "Tipo di report da generare",
},
},
required: ["data_inizio", "data_fine", "tipo"],
},
},
],
};
});
// Gestisce l'esecuzione dei tools
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
switch (name) {
case "get_utenti": {
const limite = (args?.limite as number) || 10;
const ruolo = args?.ruolo as string | undefined;
const url = new URL(`






