Les outils MCP donnent à votre agent IDE un accès à des API externes, bases de données et services. Une configuration non auditée peut exposer des clés API, permettre des écritures non intentionnelles ou générer des frais. Ce tutoriel vous guide pour auditer les outils MCP connectés, les classer par niveau de risque, vérifier les clés API en clair et surveiller l'utilisation.
Prérequis
- Un IDE compatible MCP (Cursor, VS Code, Windsurf)
- Au moins un serveur MCP configuré
- Compréhension de base de MCP
Parcours
Étape 1: Lister tous les serveurs MCP configurés
Lire les fichiers de configuration de l'IDE pour voir les serveurs connectés.
import json, os
def list_mcp():
for path in ['.mcp.json', os.path.expanduser('~/.cursor/mcp.json')]:
if os.path.exists(path):
config = json.load(open(path))
servers = config.get('mcpServers', config.get('servers', {}))
print(f'\n{path}:')
for name, srv in servers.items():
url = srv.get('url', srv.get('command', '?'))
print(f' {name}: {url}')
for k in srv.get('env', {}):
safe = '***' if any(s in k.lower() for s in ['key', 'secret', 'token']) else srv['env'][k]
print(f' {k}: {safe}')
list_mcp()Étape 2: Classer les outils par risque
Catégoriser chaque outil en lecture seule, écriture ou destructeur.
def classify(tool_name):
t = tool_name.lower()
if any(w in t for w in ['delete', 'remove', 'drop']): return 'HIGH'
if any(w in t for w in ['create', 'update', 'send', 'write']): return 'MEDIUM'
if any(w in t for w in ['search', 'get', 'list', 'fetch', 'read']): return 'LOW'
return 'REVIEW'
for tool in ['scavio_search', 'gmail_send_email', 'db_delete_record', 'list_files']:
print(f' [{classify(tool):6}] {tool}')Étape 3: Vérifier les clés API en clair
Vérifier que les clés utilisent des variables d'environnement, pas de valeurs brutes.
def audit_keys(path='.mcp.json'):
config = json.load(open(path))
issues = []
for name, srv in config.get('mcpServers', {}).items():
for k, v in srv.get('env', {}).items():
if any(s in k.lower() for s in ['key', 'secret', 'token']):
if not v.startswith('$') and len(v) > 10:
issues.append(f'{name}.{k}: plaintext key detected')
if issues:
for i in issues: print(f' WARNING: {i}')
else:
print(' No plaintext keys found.')
audit_keys()Étape 4: Surveiller l'utilisation de MCP
Suivre les outils que votre agent appelle.
from collections import Counter
class MCPMonitor:
def __init__(self): self.calls = Counter()
def log(self, tool): self.calls[tool] += 1
def report(self):
for tool, count in self.calls.most_common():
print(f' {tool:30} {count:4} calls [{classify(tool)}]')
m = MCPMonitor()
m.log('scavio_search'); m.log('scavio_search'); m.log('gmail_send_email')
m.report()Exemple Python
import json, os
def audit(path='.mcp.json'):
if not os.path.exists(path): print('Not found'); return
for name, srv in json.load(open(path)).get('mcpServers', {}).items():
url = srv.get('url', srv.get('command', '?'))
print(f'{name}: {url}')
for k, v in srv.get('env', {}).items():
print(f' {k}: {"***" if "key" in k.lower() else v}')
audit()Exemple JavaScript
const fs = require('fs');
function audit(path = '.mcp.json') {
if (!fs.existsSync(path)) return console.log('Not found');
const config = JSON.parse(fs.readFileSync(path, 'utf8'));
for (const [name, srv] of Object.entries(config.mcpServers || {})) {
console.log(`${name}: ${srv.url || srv.command || '?'}`);
for (const [k, v] of Object.entries(srv.env || {}))
console.log(` ${k}: ${/key|secret|token/i.test(k) ? '***' : v}`);
}
}
audit();Sortie attendue
.mcp.json:
scavio: https://mcp.scavio.dev/mcp
SCAVIO_API_KEY: ***
[LOW ] scavio_search
[MEDIUM] gmail_send_email
[HIGH ] db_delete_record
No plaintext keys found.