Cada servidor MCP representa otro secreto más que su agente puede filtrar.
Cada servidor MCP representa un secreto activo adicional y amplía el alcance de lo que una entrada maliciosa puede afectar. Audite los alcances de los tokens y aplique cuatro correcciones que reduzcan el radio de impacto.
Fuentes: Every MCP Server You Add Gives Your Agent Another Credential
Comienza de forma inocente. Se conecta GitHub el lunes, Slack el martes, luego Postgres, después Notion, y finalmente un servidor interno de facturación que un colega escribió una tarde sin documentarlo nunca. Cada adición hace que el agente sea más capaz. Cada una también añade una llave al collar que lleva consigo.
Los problemas suelen surgir por casualidad, cuando alguien está depurando algo sin relación y abre el archivo de configuración. Seis servidores, seis secretos activos, todos en texto plano en un directorio personal, sin fecha de vencimiento ni propietario. En ese punto, MCP deja de parecer una herramienta útil y comienza a parecer una carga.
La aritmética
Después de un par de meses de entusiasmo, una configuración típica se ve así:
{
"mcpServers": {
"gh": { "cmd": "gh-mcp", "env": { "GH_TOKEN": "ghp_live_9f2a" } },
"db": { "cmd": "pg-mcp", "env": { "PG_URL": "postgres://app:hunter2@prod/main" } },
"sl": { "cmd": "slk-mcp", "env": { "SLACK_TOKEN": "xoxb-live-771" } }
}
}
Tres servidores, tres secretos, un archivo y sin rotación. Puede verificar su propia máquina en segundos buscando en las carpetas de configuración habituales cadenas que parezcan tokens.
grep -rIl "ghp_\|xoxb-\|sk-" ~/.config ~/.claude ~/Library 2>/dev/null | wc -l
Quienes lo administran a menudo encuentran más de lo que esperaban. Un total de once cuando se suponía que serían tres no es algo inusual.
La parte que realmente causa problemas
Las credenciales almacenadas en el disco son solo la mitad menos grave del problema. La parte más grave es que cada una de esas claves ahora está en manos de una sola persona encargada de tomar decisiones, y esa persona lee texto de Internet.
one agent loop
|
+---------+---------+---------+---------+
| | | | |
github slack postgres notion billing
(14 scp) (9 scp) (rw all) (rw ws) (rw all)
| | | | |
+---------+---------+---------+---------+
|
one poisoned input
Un comentario de problema, una página de Notion o una fila en una tabla pueden sugerir una acción cada uno, y el agente cuenta con todas las herramientas necesarias para llevarla a cabo. Este es el problema del representante confundido, pero con un disfraz diferente. El agente no está comprometido; simplemente está siendo útil, y no puede distinguir tus instrucciones del texto que solo se parece a ellas.
Medir la brecha
Un ejercicio útil es registrar cada llamada a las herramientas durante dos semanas y luego comparar lo que cada token está autorizado a hacer con lo que realmente hizo. Un resultado de uno de estos auditorías:
| Service | Granted Scopes | Scopes Used | Utilization |
| -------- | --------------: | ------------------: | ----------: |
| GitHub | 14 | 3 | 21.4% |
| Slack | 9 | 2 | 22.2% |
| Postgres | Full RW | 1 table, reads only | Minimal |
| Notion | Whole workspace | 2 pages | Minimal |
Aproximadamente cuatro quintas partes del acceso otorgado no se utilizaron. Esa brecha no se debe a la comodidad; representa un riesgo innecesario del que no se obtiene beneficio alguno.
Soluciones, ordenadas por beneficio
Un token por servidor, adaptado a las funciones reales de ese servidor. Los tokens compartidos implican responsabilidades compartidas. Cuando algo sale mal, el registro de auditoría debe señalar al servidor y no a una persona.
Por defecto, todo lo que almacena datos debe tener acceso solo de lectura. Dos líneas de SQL, un rol dedicado y derechos de selección solo sobre las tablas que el agente realmente necesita leer, transforman el peor escenario de una tabla eliminada a una consulta filtrada.
create role agent login password 'rotate_me';
grant usage on schema public to agent;
grant select on orders, users to agent;
Tokens de corta duración en lugar de los permanentes. Que un bóveda emita una credencial bajo demanda, con un tiempo de validez medido en minutos. Un secreto robado el martes por la mañana ya no tiene valor para el martes por la tarde.
async function tok(srv) {
const r = await fetch(`${VAULT}/issue/${srv}`, { method: "POST" });
const { token, ttl } = await r.json();
return { token, exp: Date.now() + ttl * 1000 };
}
Se registran las llamadas, no solo el chat. Un sencillo recubrimiento que graba el servidor, los argumentos y una marca de tiempo alrededor de cada función de la herramienta consiste en unas pocas líneas de código. En la auditoría mencionada anteriormente, se descubrió que un servidor llamaba a un endpoint al que nadie le había solicitado acceder.
function wrap(name, fn) {
return async (args) => {
log({ srv: name, args, at: Date.now() });
return fn(args);
};
}
Una regla a adoptar
Antes de incorporar un servidor, imagínalo como algo hostil y pregúntese qué podría lograr sin ninguna ayuda. Cuando la respuesta honesta resulte incómoda, reduzca los privilegios otorgados o excluya al servidor. No prometa arreglarlo más tarde, porque ese momento rara vez llega, y mucho menos los viernes.
Nada de esto es un argumento en contra de MCP. Él resolvió el desorden en la integración que hacía que los agentes parecieran juguetes. El punto es que cada servidor que añada también introduce una credencial, y las credenciales merecen la misma atención que cualquier otra clave crítica en el entorno de producción.
Leer más
- Notas prácticas: Construir un agente financiero AI con el servidor MCP de EODHD — Guía paso a paso de las Notas prácticas: Construir un agente financiero AI con el servidor MCP de EODHD: contratos, verificaciones y espacios para código listo para usar para equipos que desarrollan sistemas MCP sin él.
- Notas prácticas: ¿Puede su agente buscar MCPs? — Guía paso a paso de las Notas prácticas: ¿Puede su agente buscar MCPs?: contratos, verificaciones y espacios para código listo para usar para equipos que implementan este patrón.