Seguridad de la configuración de MCP para cambios en repositorios
La seguridad de la configuración de MCP empieza con la revisión de las solicitudes de cambios. Aprende cómo las rutas de comandos, los ejecutores de paquetes, los argumentos, cwd y las variables de entorno cambian el riesgo.

Una configuración MCP de un repositorio es material ejecutable de despliegue disfrazado de pequeño archivo JSON. Puede seleccionar un binario, descargar un paquete, elegir dónde se inicia ese proceso, pasarle datos y darle acceso a una copia de trabajo. Por eso, la seguridad de la configuración de MCP es un asunto de revisión de solicitudes de cambios antes de convertirse en un problema de seguridad del agente.
He visto a equipos pasar una hora debatiendo si un agente debería tener permiso para llamar a una herramienta y después fusionar un lanzador capaz de instalar cualquier cosa que resolviera un nombre de paquete público esa misma tarde. La lista de herramientas es la parte visible. El proceso que crea esa lista ya ha cruzado un límite.
La configuración es una instrucción para iniciar un proceso
Un cambio en .mcp.json merece la misma atención que un cambio en un script de compilación, porque un cliente debe convertir sus campos en un proceso local. El esquema exacto cambia según el host, pero la estructura habitual resulta familiar: un comando, una matriz de argumentos, variables de entorno opcionales y, a veces, un directorio de trabajo o una configuración de transporte.
Ese proceso se inicia con los permisos del desarrollador o del host del agente que lo lanza. Puede leer los archivos que ese usuario puede leer, crear archivos donde tiene permiso de escritura, heredar determinados valores del entorno y realizar solicitudes de red, salvo que el sistema operativo u otro control lo impida. Que su función final sea «servidor MCP» no reduce esos permisos habituales de un proceso.
A menudo, los revisores deducen seguridad a partir del nombre del paquete o de lo limitada que parece la lista de herramientas anunciadas. Ninguna de las dos deducciones es válida. Un servidor llamado issue-reader puede exponer solo operaciones de lectura después de iniciarse, mientras su lanzador ejecuta un wrapper de shell que lee un token del directorio personal. Un servidor con un nombre que suena amplio puede ser un binario incluido en el repositorio que hace exactamente lo que documenta el proyecto. Empieza por las pruebas, no por los nombres.
La línea peligrosa suele ser visualmente aburrida:
{
"mcpServers": {
"docs": {
"command": "npx",
"args": ["-y", "@example/docs-mcp"]
}
}
}
Esto no significa que npx o un paquete de registro sean inaceptables automáticamente. Significa que la solicitud de cambios ha delegado parte de la cadena de suministro ejecutable para un momento posterior, en cada equipo que inicie el servidor. El revisor debe saber qué versión del paquete se ejecutará, de dónde procede, qué instala y qué hace en el primer inicio.
Una configuración incluida en el repositorio también genera presión social. Cuando aparece en el repositorio, un colaborador nuevo ve un servidor descrito como parte de la configuración del proyecto y supone que ya ha sido revisado. Precisamente por eso este tipo de archivo necesita una persona responsable y un hábito de revisión.
Los mensajes de MCP y los lanzadores del repositorio son capas distintas
La especificación del Model Context Protocol describe la conversación entre un cliente y un servidor MCP, incluida la inicialización, el descubrimiento de herramientas, las llamadas a herramientas y el comportamiento del transporte. No crea un formato universal para .mcp.json ni hace inofensiva una configuración del cliente. Cada cliente decide dónde lee la configuración y cómo inicia un servidor local mediante stdio.
La distinción parece académica hasta que una revisión sale mal. El protocolo puede limitar un servidor a un conjunto declarado de métodos después de establecerse la conexión. La configuración del host decide qué programa tiene la oportunidad de anunciar esos métodos en primer lugar. Si inspeccionas solo el comportamiento de cara al protocolo, empiezas la revisión después de que el lanzador ya haya actuado.
Mantén separadas estas dos preguntas:
- ¿Qué acciones puede solicitar o realizar el servidor conectado mediante sus herramientas?
- ¿Qué hace el lanzador local antes de que el cliente tenga una conexión con el servidor?
La primera pregunta corresponde a los permisos del agente, el flujo de aprobación y el diseño de las herramientas. La segunda corresponde a la confianza en el repositorio, la ejecución de procesos, la procedencia de las dependencias y el alcance del sistema de archivos. Una buena revisión responde a ambas, pero nunca permite que la respuesta a una sustituya la respuesta a la otra.
La documentación del protocolo anima a clientes y servidores a negociar capacidades. Eso resulta útil para la compatibilidad, pero no establece confianza en un comando del repositorio. La negociación de capacidades puede indicar al cliente que un servidor admite herramientas. No puede demostrar que la ruta del comando, el contenido del paquete o el hook de inicio merezcan el acceso del desarrollador.
Esto también explica por qué un servidor conocido puede seguir siendo arriesgado en una configuración nueva. El código del servidor puede no haber cambiado, pero un argumento modificado puede apuntarlo a otro endpoint, otra fuente de credenciales u otro directorio del proyecto. El contexto de inicio forma parte del comportamiento.
Lee el comando que se inicia antes que las herramientas anunciadas
Revisa la resolución del comando como una cadena, no como la primera cadena de texto del JSON. Pregunta qué programa ejecutará realmente el host después de resolver el comando mediante el entorno actual. python, node, uvx, npx, bunx, sh y una ruta relativa significan que otro resolvedor decide cuál será el ejecutable final.
Una ruta absoluta directa es la más fácil de inspeccionar, aunque también necesita una explicación sobre su procedencia. Una ruta relativa al repositorio puede ser aceptable cuando el repositorio contiene el archivo y la revisión normal del código lo cubre. Un nombre de comando sin ruta exige inspeccionar cómo funciona el PATH del desarrollador. Un comando de shell necesita el mayor nivel de sospecha, porque las comillas, las expansiones, las tuberías, las redirecciones y la sustitución de comandos ocultan más ejecución que una matriz de argumentos sencilla.
Los argumentos merecen una revisión propia. Es habitual que los revisores lean los dos primeros argumentos, reconozcan un nombre de paquete y sigan adelante. Lee todos los elementos. Un argumento puede seleccionar un archivo de configuración fuera de la copia de trabajo, elegir un directorio de salida, activar un cargador de plugins, apuntar a un registro alternativo o convertir un comando inofensivo en un evaluador de scripts.
Considera la diferencia entre estas dos entradas:
{
"command": "node",
"args": ["tools/mcp-server.js", "--root", "."]
}
{
"command": "node",
"args": ["tools/mcp-server.js", "--config", "../../shared/runtime.json"]
}
La segunda entrada puede ser legítima. También crea una dependencia de un archivo situado fuera de los límites de la copia de trabajo que la solicitud de cambios quizá no muestre. Si el servidor lee instrucciones o credenciales de ese archivo, los revisores no pueden evaluar el cambio solo a partir del diff. Pide al autor que incluya la configuración referenciada en la revisión, la sustituya por una ruta explícita del repositorio o explique por qué hace falta el archivo externo.
No aceptes una respuesta vaga como «el paquete se encarga de eso». Puede que el paquete lo gestione correctamente hoy, pero el cambio sigue otorgándole autoridad. Una respuesta útil nombra el programa, su versión, sus entradas y los archivos que espera. Si el autor no ha ejecutado el comando exacto desde una copia de trabajo nueva, está describiendo una intención, no un comportamiento.
Aplica a los wrappers de shell una regla predeterminada clara: recházalos, salvo que el repositorio tenga una necesidad concreta que una matriz de argumentos no pueda expresar. Un wrapper puede parecer práctico porque establece un valor de entorno e inicia dos auxiliares. También hace que la revisión dependa de las reglas de análisis del shell y de cualquier comando al que llegue el wrapper. Si tiene que existir, coloca la configuración inicial en un script revisado con un nombre claro y revisa ese script como código de la aplicación.
Los ejecutores de paquetes convierten el inicio en un evento de la cadena de suministro
Un ejecutor de paquetes puede descargar y ejecutar código durante el primer inicio del servidor, así que el nombre de un paquete por sí solo no basta para revisar la dependencia. Por eso, formas como npx -y package, uvx package y similares requieren más atención que un comando que invoque un archivo incluido en el repositorio.
El argumento habitual a favor de un ejecutor sin versión fijada es la comodidad. Los colaboradores no tienen que instalar nada manualmente y el proyecto parece mantenerse actualizado. El coste es que el repositorio deja de indicar exactamente qué código pide ejecutar a cada colaborador. Una versión de paquete recién publicada, una dependencia modificada o un cambio en el enrutamiento del registro pueden alterar el comportamiento sin una nueva solicitud de cambios.
Como mínimo, haz explícita la versión y deja claro el origen:
{
"mcpServers": {
"schema-checker": {
"command": "npx",
"args": ["-y", "@acme/[email protected]"],
"cwd": "${workspaceFolder}"
}
}
}
Fijar la versión no certifica el paquete. Estabiliza el objetivo de la revisión. Un revisor puede inspeccionar esa versión, compararla con la anterior y exigir una solicitud de cambios específica para actualizarla. Usa el archivo de bloqueo del gestor de paquetes, datos de integridad o un artefacto incluido en el repositorio cuando la cadena de herramientas lo permita. Una cadena de versión sin ninguna forma de verificar el contenido descargado deja una brecha, pero sigue siendo mejor que un nombre sin límites.
No confundas la caché de un gestor de paquetes con una revisión. La caché solo cambia de dónde proceden los bytes en un equipo. No indica al revisor qué bytes recibirán otros colaboradores, si se ejecutan hooks de instalación ni si un equipo limpio se comporta igual.
Haz una pregunta incómoda que detecta muchos cambios débiles: ¿qué ocurre si falta el paquete? Si la respuesta es «se instala solo», la configuración tiene una ruta de red y ejecución de código. Si la respuesta es «el inicio falla y muestra instrucciones para instalar una dependencia documentada», el equipo ha elegido una configuración más lenta, pero más visible. Ninguna respuesta es inherentemente correcta. Fingir que la diferencia no existe sí es un error.
Los directorios de trabajo y las variables de entorno determinan el alcance real
El campo cwd indica a un proceso dónde empezar a buscar archivos relativos, y esa elección suele controlar más cosas de las que la gente espera. Muchas herramientas descubren la configuración del proyecto, los entornos de ejecución, los archivos de exclusión, las credenciales y los plugins recorriendo los directorios superiores desde el directorio de trabajo. Un servidor que empieza en la raíz del repositorio puede ver un entorno muy distinto del de uno que empieza en un directorio de pruebas específico.
Establece el directorio de trabajo deliberadamente. Si un servidor solo necesita las especificaciones de API generadas en tools/specs, no lo inicies desde un directorio superior que contenga material de despliegue y notas privadas de desarrollo. Si debe inspeccionar toda la copia de trabajo, dilo en la solicitud de cambios. El objetivo no es hacer que todas las rutas sean diminutas. Es conseguir que el acceso aprobado por el revisor coincida con el acceso que recibe el servidor.
Las variables de entorno tienen un peso parecido. Algunas son ajustes operativos inofensivos, como la configuración regional o un puerto. Otras seleccionan un registro de paquetes, amplían una ruta de búsqueda de módulos, activan un modo de depuración que escribe cuerpos de solicitudes o transportan credenciales. Una configuración que usa ${TOKEN} oculta el valor del token en el archivo, pero sigue pasando ese secreto a un proceso secundario.
Evita las credenciales en la configuración MCP del repositorio siempre que el servidor pueda funcionar mediante un límite de acción separado. Si un servidor necesita realmente un secreto, documenta su origen, su propósito y si el proceso puede pasarlo a procesos secundarios. No pongas un token de producción de ejemplo en un comentario ni en una transcripción de shell copiada. Los desarrolladores copiarán el ejemplo que resulte más fácil de hacer funcionar.
También hay que prestar atención a los valores de entorno heredados. Un proceso puede heredar mucho más de lo que enumera el JSON. El host decide qué pasa al proceso, pero el autor del repositorio puede elegir un comando que lea ubicaciones de ejecución habituales. Esa es otra razón para preferir lanzadores directos y pequeños en lugar de shells generales y ejecutores de paquetes.
Un diff de una solicitud de cambios puede revelar el grafo de ejecución
Puedes revisar la mayoría de los cambios de configuración sin ejecutar código que no sea de confianza si amplías el diff hasta los procesos y las entradas que implica. Empieza por un diff específico en lugar de la vista del archivo renderizado, para que las rutas modificadas y los argumentos eliminados sigan siendo visibles:
git diff --check
git diff -- .mcp.json
El primer comando informa de errores de espacios en blanco cuando los encuentra. El segundo debería mostrar cada línea añadida, eliminada o modificada en la ruta de configuración. Si el repositorio guarda el archivo en otro sitio o lo genera, ajusta la ruta y pide también el cambio del generador. Una configuración generada sin su fuente es una revisión incompleta.
Observa este pequeño cambio:
"mcpServers": {
"release-notes": {
- "command": "node",
- "args": ["tools/release-notes-server.js"],
- "cwd": "${workspaceFolder}"
+ "command": "npx",
+ "args": ["-y", "release-notes-mcp"],
+ "cwd": ".."
}
}
La historia visible dice que el equipo sustituyó un auxiliar local por un servidor publicado. El grafo de ejecución cuenta algo más. El cliente resuelve npx mediante el PATH del desarrollador. npx puede descargar release-notes-mcp y sus dependencias. El paquete se inicia fuera de la raíz del repositorio porque cwd ahora apunta al directorio superior. El servidor puede descubrir allí configuraciones, escribir archivos de caché o leer proyectos vecinos. Cada flecha necesita una respuesta antes de fusionar el cambio.
Una revisión disciplinada pide pruebas en este orden:
- Identifica el ejecutable final y el paquete exacto o archivo del repositorio que lo proporciona.
- Enumera cada ruta de archivo, URL, registro y valor de entorno que pueda cambiar el comportamiento durante el inicio.
- Indica el directorio de trabajo del proceso y los directorios que el servidor lee o escribe durante el uso normal.
- Confirma qué ocurre en un equipo limpio antes de que exista una caché de paquetes.
- Compara la finalidad declarada de la herramienta con los permisos que el lanzador necesita realmente.
Esa secuencia es un artefacto concreto, no una formalidad. Evita el fallo habitual en el que un revisor aprueba la descripción de una herramienta mientras un instalador, un selector de entorno de ejecución o un directorio superior se cuela en un cambio de una sola línea.
Si tienes que ejecutar una configuración para validarla, hazlo con una cuenta desechable o en un entorno aislado sin credenciales de producción y con la caché de paquetes vacía. Registra el ejecutable resuelto, la versión del paquete, los hosts de salida y los archivos escritos. Una captura de pantalla del descubrimiento correcto de herramientas es una prueba débil porque omite la parte que causó el mayor riesgo.
Las descripciones de las herramientas no compensan un lanzador amplio
Un esquema de herramientas limitado no borra lo que ocurrió antes del handshake de MCP. Los equipos suelen tratar la salida de tools/list de un servidor como un inventario de permisos y decidir que parece segura porque ofrece search_docs y read_status. Ese inventario describe la interfaz después de la inicialización. Dice poco sobre la instalación del paquete, el descubrimiento de configuración, la telemetría, los procesos secundarios o los archivos leídos durante el inicio.
La distinción funciona en ambos sentidos. Un servidor con una herramienta capaz de escribir puede ser aceptable cuando el lanzador está fijado, es local, está documentado y se limita al proyecto previsto. Un servidor de solo lectura puede ser inaceptable cuando una configuración del repositorio ejecuta en silencio un paquete mutable de la red con acceso a un espacio de trabajo más amplio del desarrollador.
Pide al autor que describa el ciclo de vida con palabras sencillas: qué se inicia, qué lee antes de conectarse, qué descarga si descarga algo y qué puede tocar el servidor una vez conectado. La explicación debería caber en la descripción de una solicitud de cambios. Si hace falta una investigación larga para responder, la configuración es demasiado indirecta para una revisión rutinaria.
No dejes que «confiamos en este proveedor» cierre la conversación. La confianza es relevante, pero no fija una versión, no limita un directorio de trabajo ni demuestra si el comando usa un registro alternativo. Son controles distintos con modos de fallo distintos.
La propiedad del repositorio necesita un respaldo en tiempo de ejecución
La revisión del repositorio evita que las instrucciones de inicio inseguras se conviertan en parte normal de la configuración del proyecto. Los controles en tiempo de ejecución siguen siendo importantes, porque una dependencia aprobada puede estar comprometida, una instrucción maliciosa puede influir en el agente o un usuario puede pedirle que actúe con demasiada amplitud.
Mantén claro el límite. El repositorio controla lo que propone iniciar. La persona que opera el equipo controla si una sesión concreta del agente puede actuar. Las acciones sensibles necesitan registros que permitan reconstruir lo que hizo el agente y revocar la sesión cuando algo sale mal.
Sallyport mantiene las credenciales API y SSH fuera del proceso del agente, mientras que su autorización de sesiones y su registro de actividad ofrecen al operador un lugar separado para aprobar e inspeccionar las acciones. Eso no vuelve inofensivo un comando arriesgado del repositorio, por lo que la revisión de la configuración sigue siendo lo primero.
Para los equipos que usan otro límite de seguridad, aplica la misma prueba. ¿Puede un desarrollador ver qué proceso del agente solicitó acceso? ¿Puede detener ese proceso sin terminar tareas que no tienen relación? ¿Puede distinguir entre una acción intentada y una acción completada? Si la respuesta es negativa, una mala configuración tiene más tiempo para causar problemas después de fusionarse.
Trata estos archivos como código de ejecución bajo responsabilidad
Un repositorio debería asignar propietarios de código o una regla de revisión equivalente a la configuración de MCP, sus scripts wrapper y cualquier manifiesto de paquetes que determine qué instala el lanzador. La persona responsable no tiene que ser especialista en seguridad. Necesita suficiente contexto para preguntar por qué este cambio inicia este programa con este acceso.
Mantén las configuraciones pequeñas. Un servidor por propósito es más fácil de revisar que un auxiliar universal que llega a todos los sistemas que usa un desarrollador. Coloca junto a la configuración una explicación sencilla de los requisitos inusuales: comando esperado, política de versiones del paquete, directorio de trabajo, acceso de red necesario y entradas previstas. Esa nota convierte el conocimiento tácito en algo que el siguiente revisor puede cuestionar.
La prueba práctica es sencilla. Entrega el diff a un desarrollador experimentado que no conozca la funcionalidad y pídele que explique qué se ejecutará en un equipo limpio, dónde se ejecutará y qué podrá ver. Si no puede responder a partir de la solicitud de cambios y del código referenciado, el cambio necesita más trabajo antes de incorporarse al repositorio.
FAQ
¿Forma parte .mcp.json de la especificación de MCP?
No. El protocolo define cómo intercambian mensajes un cliente y un servidor; un archivo del repositorio que inicia un servidor es una convención del cliente o de la herramienta de desarrollo. Trata su comando, argumentos, variables de entorno y directorio de trabajo como instrucciones de ejecución local.
¿Puede una configuración de MCP ejecutar código cuando abro un repositorio?
Puede hacerlo, especialmente cuando usa un ejecutor de paquetes, un shell, un intérprete o un ejecutable relativo. Es posible que un servidor muestre herramientas aparentemente inofensivas después de que su lanzador ya haya leído archivos, contactado con un registro o instalado código.
¿Debería permitir npx en una configuración de MCP?
Pide una versión fijada del paquete o un ejecutable incluido en el repositorio con una suma de comprobación registrada. Un nombre de paquete sin versión deja el programa real a merced del estado del registro cuando un desarrollador inicia el servidor.
¿Por qué importa cwd en la configuración de un servidor MCP?
Solo cuando el repositorio tenga un motivo documentado y el equipo espere que el servidor pueda leer o escribir en ese directorio. En la práctica, el directorio de trabajo es un límite de acceso, aunque parezca una simple opción de comodidad.
¿Qué debería revisar en una solicitud de cambios para .mcp.json?
Lee el ejecutable, cada argumento, las variables de entorno, el directorio de trabajo y la forma en que el host decide iniciarlo. Los nombres y las descripciones de las herramientas dicen mucho menos sobre lo que ocurre antes de que el servidor se conecte.
¿Cómo reviso un instalador de paquetes en una configuración de MCP?
Pide el comando exacto que se resolverá, la versión del paquete, el origen del registro y los permisos que necesita el proceso. Si el autor no puede explicar qué descarga o escribe el primer inicio, el cambio no está listo para fusionarse.
¿Se inicia automáticamente un servidor MCP desde la configuración de un repositorio?
Depende del host. Algunos clientes esperan una acción explícita, mientras que otros pueden detectar u ofrecer servidores configurados al abrir un espacio de trabajo. Revisa el archivo como si un desarrollador fuera a ejecutarlo con el repositorio abierto y credenciales sensibles disponibles.
¿Son seguras las variables de entorno para las credenciales de MCP?
Los secretos en variables de entorno suelen llegar a procesos secundarios, salidas de diagnóstico, informes de fallos y hooks de instalación de paquetes. Mantener las credenciales fuera del agente es una buena práctica, pero el lanzador sigue necesitando revisión porque podría leer otros datos del equipo del desarrollador.
¿Cómo pueden los equipos hacer más seguras las configuraciones de MCP del repositorio?
Mantén el cambio pequeño, identifica cada binario que se inicia, fija las dependencias mutables y documenta el límite de acceso previsto. Después, pide a alguien que no haya escrito el cambio que reproduzca el inicio en una copia de trabajo desechable.
¿La aprobación en tiempo de ejecución sustituye la revisión de la configuración?
No. La aprobación puede detener una acción inesperada en el límite de acceso, pero no indica si el repositorio pidió iniciar el programa correcto. La revisión de la configuración evita un tipo de error; la aprobación en tiempo de ejecución contiene otro.