# Aleja los agentes MCP de las variables de entorno: migra las credenciales

Poner credenciales en el entorno de un servidor MCP es un atajo que se vuelve peligroso cuando un agente puede ejecutar comandos, inspeccionar archivos, solucionar fallos o crear procesos auxiliares. El problema no es que todos los agentes vayan a mostrar deliberadamente un token. El problema es que has entregado un secreto reutilizable a un proceso diseñado para explorar y actuar, y luego le has pedido que se comporte como si no pudiera verlo.

Saca la autoridad del proceso del agente. Haz que el agente solicite una acción HTTP o SSH definida y que un componente local con la credencial la ejecute. El cambio parece pequeño, pero te obliga a identificar qué hace realmente cada herramienta, qué identidad necesita y cómo demostrarás que el token no se ha colado en la nueva ruta.

He visto migraciones fallar porque alguien quitó `API_TOKEN` de un archivo de configuración, pero lo dejó en un perfil de shell, un ejecutor de tareas o una plantilla de proyecto copiada. La llamada a la API seguía funcionando, todos se relajaron y el agente aún tenía la credencial antigua. Una migración limpia trata el descubrimiento, el reemplazo y la comprobación como tareas separadas.

## Las variables de entorno dan al agente más autoridad de la que necesita la herramienta

Una variable de entorno no pertenece a una sola solicitud. Pertenece a un proceso y, a menudo, a todo lo que ese proceso inicia. Si un cliente MCP inicia un servidor con `SERVICE_TOKEN` en su entorno, el servidor puede leerlo. También pueden hacerlo los procesos hijo que lo hereden, salvo que alguien lo elimine cuidadosamente. Los comandos de depuración, los informes de fallos, los datos de prueba y una salida accidental de `env` pueden convertir una comodidad local en una filtración duradera.

Esto es distinto de que una herramienta reciba un resultado autenticado. El resultado puede contener una lista de repositorios, el estado de un despliegue o una respuesta de error. El agente necesita esos datos para continuar su trabajo. No necesita el token bearer que hizo posible la solicitud.

La diferencia se difumina porque ambos diseños pueden producir la misma solicitud correcta. No son equivalentes:

- **Posesión de la credencial** significa que el agente puede usar, copiar, transformar o exfiltrar un secreto fuera de la llamada prevista a la herramienta.
- **Autoridad de acción** significa que el agente puede pedir a un ejecutor local de confianza que realice una solicitud con controles definidos.
- **Acceso al resultado** significa que el agente ve la respuesta que necesita para decidir su siguiente acción.

Confundir esta diferencia lleva a una recomendación problemática muy común: guardar los tokens en un gestor de secretos y después inyectarlos en el entorno del agente al iniciar. Eso puede mejorar el almacenamiento en reposo, pero no cambia el límite durante la ejecución. El agente sigue recibiendo el token.

La especificación MCP describe un protocolo para clientes, servidores y herramientas. No declara que las variables de entorno sean un límite de credenciales. Trátalas como transporte de configuración local solo cuando el proceso que las recibe ya tenga autorización para manejar el secreto subyacente. Los agentes autónomos de programación a menudo no cumplen ese criterio.

## Crea un inventario de herramientas antes de cambiar la configuración

Empieza con un inventario escrito. No comiences editando archivos JSON, porque los archivos de configuración rara vez cuentan toda la historia. Una herramienta puede leer una variable directamente, invocar un envoltorio que lea otra o depender de un cliente de línea de comandos que cargue las credenciales desde un archivo del directorio personal.

Para cada herramienta MCP, registra el nombre de la herramienta, el comando, el destino, el método de autenticación, el propietario de la credencial, el alcance de los permisos y la solicitud inocua que puedes usar para probarla. Registra también dónde entra actualmente el secreto en el proceso: configuración del cliente, archivo de inicio del shell, archivo `.env`, exportación de CI, comando del gestor de contraseñas o script auxiliar.

Un inventario compacto podría tener este aspecto:

| Herramienta | Destino de la acción | Ruta actual del secreto | Nuevo límite | Prueba |
| --- | --- | --- | --- | --- |
| búsqueda de incidencias | API de incidencias | `ISSUES_TOKEN` en la configuración del cliente | acción HTTP local | listar un proyecto conocido |
| estado del despliegue | API de despliegues | `.env.local` | acción HTTP local | leer el estado del servicio |
| diagnóstico del host | alias de host SSH | ruta al archivo de clave privada | acción SSH local | ejecutar `uname` |
| publicación de paquetes | API del registro | exportación del shell | acción HTTP local | leer los metadatos del paquete |

No escondas permisos amplios detrás de nombres imprecisos como `prod-token` o `default-key`. Da al registro de la credencial un nombre que indique al operador qué puede hacer y adónde se dirige. `deploy-api-production-read` es menos elegante y mucho más seguro durante una revisión apresurada.

El inventario también muestra si una credencial debería existir. He encontrado tokens con capacidad de escritura asociados a herramientas que solo leían metadatos de proyectos porque alguien copió una configuración de desarrollo. Una migración es el momento adecuado para emitir credenciales más limitadas. No es una razón para conservar todos los privilegios antiguos dentro de un contenedor más bonito.

## Elimina la inyección del secreto en lugar de disfrazarla

Una configuración migrada debe dejar de entregar el secreto al agente o a su servidor MCP. Sustituir un token literal por `${SERVICE_TOKEN}`, `$(secret-tool lookup ...)` o una ruta a un archivo sin protección no cumple ese objetivo. Has cambiado la forma de escribirlo, no la autoridad.

Primero, busca las referencias actuales. En un directorio de proyecto, esto detecta muchos casos evidentes:

```sh
rg -n --hidden --glob '! .git' 'API[_-]?KEY|API[_-]?TOKEN|SECRET|PASSWORD|PRIVATE[_-]?KEY|Authorization: Bearer' .
```

El formato esperado de la salida es una lista de entradas `archivo:línea:texto coincidente`. No pegues esa salida en una incidencia si incluye valores activos. Úsala para crear una lista de correcciones y busca después por separado en las ubicaciones habituales del usuario, como los perfiles de shell y la configuración del cliente MCP.

Después, compara el entorno visible para el proceso del agente antiguo con el visible para el nuevo. En un shell de prueba controlado, muestra los nombres sin imprimir los valores:

```sh
env | cut -d= -f1 | sort | rg 'TOKEN|KEY|SECRET|PASSWORD'
```

Los nombres antiguos deben desaparecer del proceso que inicia el agente. Si `SERVICE_TOKEN` aparece allí, la migración está incompleta aunque la nueva ruta de pasarela funcione.

Evita el diseño intermedio tentador en el que el servidor MCP tiene el token, pero el agente principal no. Eso reduce una vía de exposición, pero el servidor sigue recibiendo la posesión ilimitada de la credencial. Si ese servidor puede ejecutar comandos arbitrarios, cargar complementos o escribir registros, solo has trasladado el problema a un proceso que a menudo recibe menos atención.

Usa configuración sin secretos para seleccionar el destino. Una URL base, un alias de host, un identificador de cuenta y una etiqueta de credencial pueden estar en la configuración si no conceden acceso. Guarda el material autenticado en un almacén local que el agente no pueda consultar como datos.

## Modela la nueva ruta como solicitudes, credenciales y resultados

El nuevo flujo debe tener un límite claro: el agente nombra una acción y proporciona datos normales de la solicitud, el ejecutor local selecciona e inyecta la credencial y después devuelve la respuesta. El agente nunca recibe un marcador que pueda resolver para obtener el secreto.

En una herramienta HTTP, separa la forma pública de la solicitud del paso privado de autenticación. El agente puede pedir que se realice esta solicitud:

```text
GET https://api.example.internal/projects/atlas/issues?state=open
```

El ejecutor local añade la credencial bearer, básica o de una cabecera personalizada adecuada y devuelve el cuerpo y el estado de la respuesta. Si el agente solicita un host, método o cuenta no aprobados, el ejecutor debe rechazar la solicitud en lugar de adivinar qué credencial encaja.

En SSH, la solicitud contiene un host y un comando, mientras la clave privada permanece local. Esto importa porque las herramientas SSH suelen trasladar autoridad mediante rutas, reenvío del agente, inclusiones de configuración y `SSH_AUTH_SOCK` heredado. Una ruta a una clave privada en la configuración de la herramienta no es un reemplazo seguro. El agente a menudo puede leer el archivo, copiarlo o modificar el comando que lo utiliza.

Sallyport aplica este modelo mediante su adaptador stdio integrado `sp mcp`: los agentes realizan llamadas MCP, mientras la aplicación ejecuta llamadas a API HTTP y comandos SSH sin entregar claves de API ni claves SSH al agente. Ese límite solo sirve si también eliminas la inyección antigua desde el entorno.

No conviertas el ejecutor local en una pasarela de propósito general con una única credencial todopoderosa. La solicitud del agente debe identificar un destino y una credencial configurados, no proporcionar una URL arbitraria junto con una elección de token. De lo contrario, un agente manipulado mediante una instrucción puede convertir una credencial legítima en el firmante de solicitudes dirigidas a un lugar que nunca pretendiste autorizar.

## Elige puntos de aprobación que las personas aún puedan evaluar

La aprobación humana funciona cuando una persona puede entender qué está aprobando. Falla cuando un agente de larga duración genera una pila de solicitudes casi idénticas hasta que la persona las acepta todas sin leer. Ese fallo es previsible y es un defecto de diseño, no un problema de vigilancia del operador.

Usa una aprobación por sesión cuando necesites establecer que un proceso de agente concreto puede usar las acciones configuradas durante una ejecución. La aprobación debe identificar el proceso de una forma que ayude a distinguir el cliente real de una imitación. El nombre del proceso, por sí solo, es una prueba débil porque cualquier programa puede elegir un nombre conocido.

Reserva la aprobación por llamada para credenciales cuyas consecuencias necesiten una decisión humana nueva. El acceso de escritura en producción, un comando destructivo en un host y una API relacionada con pagos merecen esa fricción. Una consulta de incidencias de solo lectura normalmente no. Si cada llamada a una herramienta exige una decisión, los operadores dejan de leer la decisión.

Un almacén bloqueado debe rechazar las solicitudes incluso si un agente aprobado anteriormente sigue en ejecución. Ese es el objetivo del control del almacén. Un proceso desatendido no debe conservar la autoridad solo porque la tuviera antes, durante la misma tarde.

Sallyport tiene tres controles fijos en lugar de un lenguaje de políticas: un control del almacén, autorización para cada proceso de agente nuevo y un requisito opcional de aprobación por clave. El modelo fijo es deliberadamente más limitado que un motor de reglas, por lo que ofrece menos reglas ingeniosas que un operador cansado pueda escribir mal.

## Comprueba por separado el éxito y el secreto

Una respuesta correcta de la herramienta solo demuestra que algo autenticó la solicitud. No demuestra que el agente no pudiera obtener la credencial. Ejecuta una prueba de migración que compruebe ambas afirmaciones, empezando por una acción de bajo riesgo.

Usa esta secuencia para cada herramienta:

1. Bloquea el almacén local e invoca la herramienta. La llamada debe fallar sin recurrir a un token del entorno.
2. Desbloquea el almacén, inicia un proceso de agente nuevo y apruébalo si tu configuración lo requiere. Ejecuta la solicitud inocua identificada en el inventario.
3. Inspecciona el registro de acciones o el registro de auditoría del servidor para comprobar el destino exacto, la cuenta, el método y el estado del resultado. Confirma que registra la acción sin registrar el secreto.
4. Desde la ruta de ejecución permitida al agente, inspecciona su entorno en busca del nombre de la variable antigua y busca el prefijo del token en su espacio de trabajo. El token no debe aparecer en ninguno de los dos lugares.
5. Reinicia el proceso del agente y repite la solicitud. Así compruebas que no dependías por accidente del estado heredado del shell antiguo.

El primer paso detecta un error sutil pero grave. A veces los equipos configuran una ruta al almacén, pero dejan la variable antigua como alternativa. Cuando el almacén está bloqueado, la herramienta funciona de todos modos. Parece fiable hasta que la misma alternativa aparece en un trabajador de CI, un repositorio copiado o una transcripción del agente.

No pidas al agente que muestre todas sus variables de entorno como prueba principal. Esa prueba crea una vía de divulgación y puede colocar el token antiguo en el historial de la conversación. Comprueba los nombres desde un shell controlado y usa una variable marcador deliberadamente no secreta durante las pruebas en seco si necesitas validar el comportamiento de herencia.

Para SSH, prueba un comando que devuelva información inocua sobre la identidad del sistema en lugar de un comando que cambie el estado. Confirma el resultado y después confirma que la configuración del agente contiene una referencia al host, no el material de la clave privada. Inspecciona también la configuración SSH en busca de `ForwardAgent yes`. El reenvío del agente puede dar a un host remoto una vía para usar identidades locales, un riesgo distinto de exponer el archivo de la clave privada.

## Los registros de auditoría deben permitir reconstruir una acción discutida

Un registro de acciones es útil cuando responde a una pregunta difícil de un lunes por la mañana: ¿qué ejecución del agente realizó esta solicitud, mediante qué credencial configurada y la aprobó una persona? Una línea imprecisa como `tool succeeded` no resolverá nada.

Conserva un registro de sesión para las ejecuciones de agentes y un registro de llamadas para cada acción. El registro de sesión indica cuándo comenzó un proceso, qué identidad aprobaste y cuándo la revocaste. El registro de llamadas indica qué ocurrió durante esa sesión. No mezcles ambos en un único flujo plano de eventos si necesitas investigar una ejecución entre muchas.

La evidencia de manipulación importa porque un agente con ejecución de comandos locales puede intentar borrar sus huellas después de una acción no deseada. Un registro encadenado mediante hashes te permite detectar historiales modificados o eliminados, pero solo si la verificación no depende de que el agente coopere.

Sallyport crea ambos registros a partir de un registro de auditoría cifrado, de escritura ciega y encadenado mediante hashes, y permite verificar la cadena sin conexión sobre el texto cifrado con este comando:

```sh
sp audit verify
```

Un resultado correcto debe indicar que la verificación terminó con éxito. Si falla, trata el registro como sospechoso hasta entender qué se ha roto. La verificación no te dice si la acción fue sensata. Te dice si el registro conserva su continuidad.

Mantén los datos de auditoría fuera de las instrucciones del modelo y de las transcripciones normales del chat. El registro puede contener contexto sensible de la solicitud o metadatos de la respuesta aunque nunca contenga la credencial. El acceso para investigar no debe convertirse en una puerta trasera para consultar datos sin cuidado.

## La rotación es la limpieza que demuestra que la migración era real

Después de que cada nueva ruta supere sus pruebas, rota la credencial antigua. Dejarla válida porque «quizá necesitemos volver atrás» prolonga el periodo en el que las configuraciones olvidadas aún pueden autenticarse. Diseña la reversión alrededor de un reemplazo controlado por separado, no alrededor de un secreto que ya has distribuido por entornos locales.

El orden de la rotación importa. Crea la nueva credencial con permisos limitados, guárdala localmente, valida la nueva ruta, elimina la inyección del secreto antiguo y después revoca la credencial antigua. Si un token antiguo pudo aparecer en el control de código fuente, un mensaje de chat, un ticket de soporte o la salida de una compilación, revócalo primero y acepta la interrupción mientras recuperas el acceso seguro.

Repite la búsqueda de descubrimiento después de la revocación. Busca referencias obsoletas, no valores secretos activos. Elimina los nombres de variables muertos de archivos de ejemplo, documentos de incorporación, perfiles de shell, scripts de tareas e instrucciones de prueba. Los futuros desarrolladores copian los ejemplos con una fidelidad sorprendente.

Por último, deja una prueba de fallo deliberada en tus notas operativas: bloquea el almacén y ejecuta una llamada inofensiva a una herramienta. Si la llamada funciona, alguien ha vuelto a introducir una vía alternativa. Esa comprobación detecta más migraciones defectuosas que otro diagrama de arquitectura impecable.

## Trata las credenciales amplias como un defecto de diseño de la herramienta

Mover un token a un almacén no hace que un token amplio sea apropiado para un agente. Solo cambia quién lo tiene. Una herramienta que puede consultar incidencias de proyectos no debería llevar silenciosamente permisos para eliminar proyectos, cambiar la facturación o desplegar código en producción.

Divide las herramientas según el trabajo real y sus consecuencias. Las acciones de descubrimiento de solo lectura pueden usar una credencial limitada y una aprobación sencilla. Las acciones que cambian el estado necesitan alcances más estrictos, destinos explícitos y, en algunos casos, consentimiento por llamada. Esto también facilita la supervisión de un agente porque sus verbos disponibles coinciden con la tarea que le has asignado.

Desconfía de una credencial universal `admin` justificada por la simplicidad de la herramienta. Esta configuración es popular porque reduce el trabajo de configuración hoy. Mañana complica la respuesta a incidentes porque no puedes distinguir qué solicitudes necesitaban ese poder y cuáles simplemente lo heredaron.

La migración funciona cuando un agente puede completar el trabajo previsto, un almacén bloqueado lo detiene, un proceso nuevo debe obtener la autoridad que has configurado y ningún token antiguo permanece en su entorno. Si alguna de estas afirmaciones no tiene una prueba, tienes una demostración funcional, no un límite de credenciales.
