Aller au contenu principal

Authentification et sécurité des serveurs MCP dans Cursor

Authentification MCP

Les serveurs Model Context Protocol (MCP) étendent Cursor avec des capacités externes puissantes, allant de l'interrogation de plateformes publicitaires à la gestion des flux de paiement. Cependant, chaque connexion externe introduit des considérations d'authentification et de sécurité. Ce guide vous accompagne à travers tout le spectre de l'authentification des serveurs MCP dans Cursor, couvrant les flux OAuth, la gestion des clés API, les couches d'approbation humaine pour les paiements pilotés par l'IA, et les défis spécifiques auxquels les utilisateurs sont confrontés avec des services comme le Live Meta Ads MCP.

Pourquoi l'authentification MCP est importante​

Lorsque Cursor se connecte à un serveur MCP, ce serveur peut avoir besoin d'agir en votre nom : lire des données privées, publier du contenu, voire dépenser de l'argent. L'authentification est le gardien qui détermine ce que l'agent peut et ne peut pas faire.

Le modèle de sécurité en un coup d'œil​

CoucheResponsabilitéExemple
CursorHéberge le client MCP, gère les connexionsLit mcp.json, lance les processus serveur
Serveur MCPGère les appels d'API externesAppelle l'API Graph de Meta, l'API Stripe
Fournisseur d'authentificationValide l'identitéJeton OAuth de Meta, clé API du fournisseur
Approbation humaineContrôle les actions sensiblesApprouver avant qu'un paiement ne soit soumis
attention

Ne stockez jamais les clés API de production ou les jetons OAuth en clair dans votre dépôt. Utilisez toujours des variables d'environnement ou un gestionnaire de secrets. Commettre des identifiants dans git est l'un des incidents de sécurité les plus courants auxquels les développeurs sont confrontés.

Prérequis​

Avant de configurer l'authentification MCP dans Cursor, assurez-vous d'avoir :

  1. Cursor installé et mis à jour vers la dernière version
  2. Node.js 18+ pour exécuter les serveurs MCP basés sur npx
  3. Un compte auprès du service externe que vous souhaitez connecter (par exemple, Meta for Developers, Stripe)
  4. Identifiants d'application auprès du fournisseur (ID client, secret client ou clé API)

Comprendre les méthodes d'authentification MCP​

Cursor prend en charge deux modèles d'authentification principaux pour les serveurs MCP, et le choix dépend entièrement de ce que le serveur auquel vous vous connectez prend en charge.

Méthode 1 : Authentification par clé API​

Le modèle le plus simple. Le serveur MCP attend une clé API statique transmise via une variable d'environnement ou un en-tête.

{
"mcpServers": {
"my-api-server": {
"command": "npx",
"args": ["-y", "@my-org/api-mcp-server"],
"env": {
"API_KEY": "${MY_API_KEY}"
}
}
}
}

La syntaxe ${MY_API_KEY} indique à Cursor de lire la valeur depuis votre environnement. Définissez-la dans votre profil shell :

# ~/.zshrc ou ~/.bashrc
export MY_API_KEY="sk-your-actual-key-here"
astuce

Sur Windows, définissez les variables d'environnement via PowerShell ou les propriétés système. Dans PowerShell :

[System.Environment]::SetEnvironmentVariable("MY_API_KEY", "sk-your-key", "User")

Puis redémarrez Cursor pour qu'il récupère la nouvelle variable.

Méthode 2 : Authentification OAuth 2.0​

OAuth est plus sûr car il évite les clés statiques et prend en charge un accès à portée limitée et révocable. Cependant, il est plus complexe à configurer. Le serveur MCP initie un flux OAuth qui ouvre un navigateur, vous demande de vous connecter au fournisseur, et renvoie un jeton à Cursor.

{
"mcpServers": {
"oauth-server": {
"command": "npx",
"args": ["-y", "@my-org/oauth-mcp-server"],
"env": {
"OAUTH_CLIENT_ID": "${CLIENT_ID}",
"OAUTH_CLIENT_SECRET": "${CLIENT_SECRET}",
"OAUTH_REDIRECT_URI": "http://localhost:3000/callback"
}
}
}
}

Le flux OAuth se déroule comme suit :

  1. Cursor démarre le processus du serveur MCP
  2. Le serveur détecte l'absence de jeton valide et initie OAuth
  3. Votre navigateur s'ouvre sur la page de connexion du fournisseur
  4. Vous autorisez l'application
  5. Le fournisseur redirige vers localhost:3000/callback avec un code d'autorisation
  6. Le serveur échange le code contre des jetons d'accès et de rafraîchissement
  7. Les jetons sont stockés localement pour une utilisation future

Configuration du Live Meta Ads MCP​

Le Live Meta Ads MCP est l'une des intégrations MCP les plus demandées pour Cursor. Il se connecte à l'API Graph de Meta pour permettre à votre agent d'interroger les performances publicitaires, les données de campagne et les insights d'audience. Les utilisateurs du forum signalent fréquemment que ce MCP ne parvient pas à s'authentifier. Voici comment le configurer correctement.

Étape 1 : Créer une application Meta​

  1. Allez sur le portail Meta for Developers
  2. Cliquez sur Créer une application
  3. Sélectionnez Entreprise comme type d'application
  4. Ajoutez le produit Marketing API
  5. Notez votre App ID et App Secret

Étape 2 : Générer un jeton d'accès longue durée​

Les jetons d'accès par défaut de Meta expirent rapidement. Pour une utilisation avec MCP, vous avez besoin d'un jeton longue durée :

# Échanger un jeton courte durée contre un jeton longue durée
curl -X GET "https://graph.facebook.com/v19.0/oauth/access_token" \
-d "grant_type=fb_exchange_token" \
-d "client_id=$META_APP_ID" \
-d "client_secret=$META_APP_SECRET" \
-d "fb_exchange_token=$SHORT_LIVED_TOKEN"

La réponse inclut un jeton valide pendant environ 60 jours.

Étape 3 : Configurer le serveur MCP dans Cursor​

{
"mcpServers": {
"meta-ads": {
"command": "npx",
"args": ["-y", "@mcp/meta-ads-server"],
"env": {
"META_ACCESS_TOKEN": "${META_ACCESS_TOKEN}",
"META_APP_ID": "${META_APP_ID}",
"META_APP_SECRET": "${META_APP_SECRET}",
"META_API_VERSION": "v19.0"
}
}
}
}

Étape 4 : Vérifier la connexion​

Redémarrez Cursor, puis ouvrez les paramètres de Cursor et accédez à la section MCP. Vous devriez voir meta-ads listé avec un indicateur de statut vert. S'il affiche une erreur, consultez la section de dépannage ci-dessous.

attention

Les jetons longue durée de Meta expirent après 60 jours. Configurez un rappel de calendrier pour rafraîchir le jeton avant qu'il n'expire. Si le jeton expire, votre agent échouera silencieusement à récupérer les données publicitaires, et le seul symptôme pourrait être des résultats vides ou des erreurs d'authentification enfouies dans les journaux MCP.

Échecs d'authentification MCP courants​

Les utilisateurs du forum signalent plusieurs problèmes récurrents avec l'authentification MCP dans Cursor. Voici les échecs les plus courants et leurs solutions.

Échec 1 : Jeton introuvable dans l'environnement​

Symptôme : Le serveur MCP démarre mais renvoie 401 Non autorisé à chaque requête.

Cause : Cursor n'a pas récupéré la variable d'environnement. Cela se produit souvent lorsque la variable a été définie dans un profil shell différent ou après que Cursor était déjà en cours d'exécution.

Solution :

# Vérifier que la variable existe
echo $META_ACCESS_TOKEN

# Si vide, l'ajouter à votre profil shell et redémarrer Cursor
echo 'export META_ACCESS_TOKEN="your-token"' >> ~/.zshrc
source ~/.zshrc

Puis quittez complètement et rouvrez Cursor.

Échec 2 : Incompatibilité de l'URI de redirection OAuth​

Symptôme : Le flux OAuth ouvre le navigateur, mais après autorisation, vous voyez une page d'erreur.

Cause : L'URI de redirection dans la configuration de votre application Meta ne correspond pas à celui que le serveur MCP utilise.

Solution : Dans votre tableau de bord Meta for Developers, allez dans Paramètres de l'application > Avancé > Paramètres OAuth et ajoutez http://localhost:3000/callback (ou l'URI que votre serveur MCP utilise) aux URI de redirection autorisés.

Échec 3 : Jeton expiré ou invalide​

Symptôme : Le serveur MCP fonctionnait auparavant mais renvoie soudainement des erreurs d'authentification.

Cause : Le jeton longue durée de Meta a expiré (limite de 60 jours) ou a été révoqué.

Solution : Relancez le flux d'échange de jeton et mettez à jour la variable d'environnement.

Échec 4 : Portées d'autorisation manquantes​

Symptôme : L'authentification réussit, mais l'agent ne peut pas accéder à certaines données (par exemple, peut lire les campagnes mais pas les données d'audience).

Cause : L'application Meta ne dispose pas des autorisations API requises.

Solution : Dans le tableau de bord de l'application Meta, allez dans Rôles > Révision de l'application > Autorisations et fonctionnalités et demandez les portées supplémentaires :

PortéeCe qu'elle permet
ads_readLire les données de performance des campagnes
ads_managementCréer et gérer des campagnes
read_insightsAccéder aux analyses détaillées
business_managementGérer les paramètres commerciales

Construire des couches d'approbation humaine pour les paiements par agents IA​

L'un des cas d'usage les plus puissants et les plus dangereux de MCP dans Cursor est la connexion d'un agent IA à des systèmes de paiement. Un agent qui peut effectuer des achats ou transférer des fonds a besoin d'une porte d'approbation humaine. Les utilisateurs du forum ont construit des couches d'approbation personnalisées pour y remédier.

Pourquoi les couches d'approbation sont essentielles​

Sans couche d'approbation, un agent IA avec accès au MCP de paiement pourrait :

  • Facturer des montants inattendus sur votre carte
  • Envoyer des paiements à de mauvais destinataires
  • Déclencher des transactions financières irréversibles
  • Accumuler des coûts par des micro-transactions répétées

Architecture d'une couche d'approbation de paiement​

Le modèle recommandé insère une passerelle d'approbation entre Cursor et le serveur MCP de paiement :

Cursor Agent --> Approval Gateway --> Payment MCP Server --> Stripe/PayPal API
^
|
Human Review

Implémentation de la passerelle d'approbation​

Créez un serveur MCP léger qui enveloppe le serveur de paiement réel et exige une approbation :

// approval-gateway.ts
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";

const server = new Server({
name: "payment-approval-gateway",
version: "1.0.0",
}, {
capabilities: { tools: {} },
});

// Pending approvals stored in memory (use a database for production)
const pendingApprovals = new Map();

server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [
{
name: "request_payment",
description: "Request a payment. Requires human approval before execution.",
inputSchema: {
type: "object",
properties: {
amount: { type: "number", description: "Amount in cents" },
currency: { type: "string", description: "ISO currency code" },
recipient: { type: "string", description: "Recipient identifier" },
reason: { type: "string", description: "Why this payment is needed" },
},
required: ["amount", "currency", "recipient", "reason"],
},
},
{
name: "approve_payment",
description: "Approve a pending payment by ID",
inputSchema: {
type: "object",
properties: {
approval_id: { type: "string" },
},
required: ["approval_id"],
},
},
],
}));

server.setRequestHandler(CallToolRequestSchema, async (request) => {
if (request.params.name === "request_payment") {
const { amount, currency, recipient, reason } = request.params.arguments;
const approvalId = `appr_${Date.now()}`;

pendingApprovals.set(approvalId, {
amount,
currency,
recipient,
reason,
status: "pending",
createdAt: new Date(),
});

return {
content: [{
type: "text",
text: `Payment request created. Approval ID: ${approvalId}\n\n` +
`Amount: ${amount/100} ${currency.toUpperCase()}\n` +
`Recipient: ${recipient}\n` +
`Reason: ${reason}\n\n` +
`To execute this payment, a human must approve it using the approve_payment tool with approval_id: ${approvalId}`,
}],
};
}

if (request.params.name === "approve_payment") {
const { approval_id } = request.params.arguments;
const approval = pendingApprovals.get(approval_id);

if (!approval) {
return { content: [{ type: "text", text: "Error: Approval ID not found." }] };
}

// Forward to actual payment server here
approval.status = "approved";
return {
content: [{
type: "text",
text: `Payment approved and forwarded to payment processor.\nAmount: ${approval.amount/100} ${approval.currency.toUpperCase()}`,
}],
};
}
});

const transport = new StdioServerTransport();
await server.connect(transport);

Configuration de la passerelle d'approbation dans Cursor​

{
"mcpServers": {
"payments": {
"command": "npx",
"args": ["tsx", "./mcp-servers/approval-gateway.ts"],
"env": {
"STRIPE_SECRET_KEY": "${STRIPE_SECRET_KEY}",
"APPROVAL_TIMEOUT_MS": "300000"
}
}
}
}
astuce

Définissez un délai d'approbation afin que si un humain n'approuve pas dans un délai raisonnable, la demande expire automatiquement. Cinq minutes est une bonne valeur par défaut. Cela empêche les demandes de paiement obsolètes de s'accumuler et d'être approuvées hors contexte.

attention

Le modèle de passerelle d'approbation ne fonctionne que si l'agent IA ne peut pas le contourner. Assurez-vous que le serveur MCP de paiement direct n'est PAS configuré dans Cursor. Seule la passerelle doit être exposée. Si les deux sont configurés, l'agent pourrait théoriquement appeler le serveur direct et ignorer l'approbation.

Configuration sécurisée du serveur MCP​

Au-delà de l'authentification, la façon dont vous configurez les serveurs MCP dans Cursor a des implications de sécurité. Suivez ces bonnes pratiques.

Utiliser une configuration au niveau du projet vs globale​

Cursor prend en charge à la fois les configurations globales (~/.cursor/mcp.json) et au niveau du projet (.cursor/mcp.json).

PortéeFichierCas d'usage
Globale~/.cursor/mcp.jsonServeurs personnels utilisés dans tous les projets
Projet.cursor/mcp.jsonServeurs spécifiques à un projet
astuce

Utilisez la configuration au niveau du projet pour les serveurs sensibles. Cela keep les identifiants hors de votre configuration globale et facilite l'audit des projets ayant accès à quels services. Ajoutez .cursor/mcp.json à .gitignore s'il contient des secrets, ou utilisez exclusivement des références de variables d'environnement.

Restriction de l'accès aux outils MCP​

Vous pouvez limiter les outils qu'un serveur MCP expose à Cursor en utilisant le champ disabledTools :

{
"mcpServers": {
"meta-ads": {
"command": "npx",
"args": ["-y", "@mcp/meta-ads-server"],
"env": {
"META_ACCESS_TOKEN": "${META_ACCESS_TOKEN}"
},
"disabledTools": ["delete_campaign", "pause_all_campaigns"]
}
}
}

Cela empêche l'agent d'utiliser des outils destructeurs même si le serveur MCP les expose.

Sécurité du transport​

Pour les serveurs MCP distants (basés sur SSE), utilisez toujours HTTPS :

{
"mcpServers": {
"remote-server": {
"url": "https://mcp.example.com/sse",
"headers": {
"Authorization": "Bearer ${REMOTE_MCP_TOKEN}"
}
}
}
}
attention

N'utilisez jamais HTTP (non chiffré) pour les serveurs MCP distants. La connexion transporte vos jetons d'authentification, et un attaquant sur le réseau pourrait les intercepter. Utilisez toujours HTTPS et vérifiez le certificat TLS du serveur.

Modèles de rafraîchissement des jetons​

De nombreux fournisseurs OAuth émettent des jetons d'accès à courte durée (1 heure) alongside des jetons de rafraîchissement à longue durée. Votre serveur MCP doit gérer le rafraîchissement automatiquement pour éviter les interruptions.

Modèle 1 : Rafraîchissement côté serveur (Recommandé)​

Le serveur MCP gère le rafraîchissement du jeton en interne. Lorsqu'un jeton d'accès expire, le serveur utilise le jeton de rafraîchissement pour en obtenir un nouveau sans intervention de l'utilisateur.

// Inside your MCP server
let accessToken = await loadToken();
let tokenExpiry = Date.now() + 3600 * 1000; // 1 hour

async function ensureValidToken() {
if (Date.now() >= tokenExpiry - 60000) { // refresh 1 min before expiry
const response = await fetch("https://oauth.provider.com/token", {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({
grant_type: "refresh_token",
refresh_token: process.env.REFRESH_TOKEN,
client_id: process.env.CLIENT_ID,
client_secret: process.env.CLIENT_SECRET,
}),
});
const data = await response.json();
accessToken = data.access_token;
tokenExpiry = Date.now() + data.expires_in * 1000;
await saveToken(accessToken, tokenExpiry);
}
return accessToken;
}

Modèle 2 : Rechargement d'environnement côté Cursor​

Si votre serveur MCP ne prend pas en charge le rafraîchissement automatique, vous pouvez recharger l'environnement dans Cursor :

  1. Rafraîchir le jeton en externe
  2. Mettre à jour la variable d'environnement
  3. Redémarrer le serveur MCP dans Cursor via les paramètres

Modèle 3 : Script d'emballage​

Créez un script d'emballage qui rafraîchit le jeton avant de démarrer le serveur MCP :

#!/bin/bash
# refresh-and-start.sh

# Refresh the Meta token
NEW_TOKEN=$(node /path/to/refresh-token.js)
export META_ACCESS_TOKEN=$NEW_TOKEN

# Start the MCP server
exec npx -y @mcp/meta-ads-server

Configurez Cursor pour utiliser l'emballage :

{
"mcpServers": {
"meta-ads": {
"command": "bash",
"args": ["/path/to/refresh-and-start.sh"]
}
}
}
astuce

Pour le Live Meta Ads MCP spécifiquement, l'expiration du jeton à 60 jours est la cause la plus courante des signalements "s'est arrêté de fonctionner soudainement". Automatisez le processus de rafraîchissement en utilisant une tâche cron ou une tâche planifiée. Sur macOS/Linux, utilisez cron. Sur Windows, utilisez le Planificateur de tâches.

Dépannage de l'authentification MCP​

Vérifier les journaux du serveur MCP​

Cursor n'affiche pas toujours les erreurs du serveur MCP dans l'interface. Pour voir ce qui se passe :

  1. Ouvrez la Palette de commandes (Cmd/Ctrl + Shift + P)
  2. Recherchez Output : Show Output Channels
  3. Sélectionnez MCP dans le menu déroulant
  4. Consultez les journaux pour les erreurs d'authentification

Tester l'authentification indépendamment​

Avant de déboguer via Cursor, testez le serveur MCP directement :

# Run the server manually
npx -y @mcp/meta-ads-server

# In another terminal, send a test request
echo '{"jsonrpc":"2.0","method":"tools/list","id":1}' | npx -y @mcp/meta-ads-server

Si le serveur ne parvient pas à s'authentifier en dehors de Cursor, le problème vient de vos identifiants, pas de Cursor.

Vérifier que les variables d'environnement sont chargées​

# Create a test script
cat > test-env.js << 'EOF'
console.log("META_ACCESS_TOKEN:", process.env.META_ACCESS_TOKEN ? "SET" : "NOT SET");
console.log("META_APP_ID:", process.env.META_APP_ID ? "SET" : "NOT SET");
console.log("META_APP_SECRET:", process.env.META_APP_SECRET ? "SET" : "NOT SET");
EOF

# Run with the MCP server's environment
node test-env.js

Si les variables s'affichent comme NOT SET, le problème vient de votre profil shell ou de la façon dont Cursor charge l'environnement.

Liste de contrôle de sécurité​

Avant de déployer des serveurs MCP dans un contexte de production, parcourez cette liste de contrôle :

  • Les clés API sont stockées dans des variables d'environnement, jamais dans des fichiers de configuration
  • .cursor/mcp.json ajouté à .gitignore s'il contient des secrets
  • Les URI de redirection OAuth sont restreints à localhost
  • Les outils destructeurs sont désactivés via disabledTools
  • Les serveurs MCP de paiement sont enveloppés avec des passerelles d'approbation
  • Le rafraîchissement des jetons est automatisé pour éviter les échecs silencieux
  • Les serveurs MCP distants utilisent uniquement HTTPS
  • Les journaux du serveur MCP sont surveillés pour les échecs d'authentification inattendus
  • Les jetons d'accès sont limités aux permissions minimales requises
  • Les serveurs MCP inutilisés sont supprimés de la configuration

Résumé​

L'authentification MCP dans Cursor couvre un spectre allant de simples variables d'environnement de clé API à des flux OAuth complexes avec rafraîchissement automatique des jetons. Le Live Meta Ads MCP est un point de douleur courant en raison de l'expiration de son jeton à 60 jours et des exigences de portée d'autorisation. En suivant les modèles de ce guide, vous pouvez construire des intégrations MCP sécurisées et fiables qui protègent les actions sensibles derrière des couches d'approbation humaine et gardent vos identifiants en sécurité.