Las herramientas MCP le dan a su agente IDE acceso a API, bases de datos y servicios externos. Una configuración no auditada puede exponer claves API, permitir escrituras no deseadas o acumular cargos. Este tutorial explica cómo auditar qué herramientas MCP están conectadas, clasificarlas por nivel de riesgo, verificar claves API de texto sin formato y monitorear el uso.
Requisitos previos
- Un IDE con soporte MCP (Cursor, VS Code, Windsurf)
- Al menos un servidor MCP configurado
- Comprensión básica de MCP
Guia paso a paso
Paso 1: Listar todos los servidores MCP configurados
Lea los archivos de configuración IDE para ver los servidores conectados.
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()Paso 2: Clasificar herramientas por riesgo
Clasifique cada herramienta como de solo lectura, de escritura o destructiva.
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}')Paso 3: Compruebe si hay claves API en texto sin formato
Verifique que las claves utilicen variables env, no valores sin formato.
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()Paso 4: Supervisar el uso de MCP
Realice un seguimiento de las herramientas a las que llama su agente.
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()Ejemplo en 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()Ejemplo en 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();Salida esperada
.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.